가변 개수의 인수를 취하는 zsh 스크립트

가변 개수의 인수를 취하는 zsh 스크립트

방금 한 컴퓨터에서 다른 컴퓨터로 ssh -t를 사용하여 명령을 실행할 수 있다는 사실을 (뒤늦게) 발견했습니다.

그런 다음 다음과 같은 작업을 수행하여 컴퓨터의 로그 파일을 한 쌍으로 추적하는 스크립트를 만들 수 있어야 한다는 생각이 들었습니다.

ssh -t $1 ssh -t $2 tailf /pathtofile/$3/log.log

실제로 1,2,3을 수동으로 입력하면 정상적으로 작동됩니다.

내 문제는 이 작업을 수행하려면 1, 2 또는 3개의 호스트 사이를 이동해야 할 수도 있다는 것입니다.

zsh에서 어떻게 할 수 있나요? 좀 파헤쳐보니 변신이 내 친구일 것 같지만 조금 헷갈립니다.

답변1

저는 실제 사용자가 아니기 때문에 솔루션 zsh을 작성하겠습니다 sh(zsh ~해야 한다실행도 가능합니다)

일반적인 요점은 ssh -t hostname마지막 항목을 제외한 각 명령줄 옵션에 대해 1비트 목록을 만든 다음 해당 목록을 명령으로 실행하는 것입니다.

#!/bin/sh

argn=$#
i=0

for arg do
   shift
   i=$(( i + 1 ))

   if [ "$i" -lt "$argn" ]; then
       set -- "$@" ssh -t "$arg"
   else
       set -- "$@" "/pathtofile/$arg/log.log"
   fi
done

command "$@"

다음과 같이 실행하세요.

sh script.sh alpha beta gamma zeta

목록이 생성됩니다

ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log

스크립트의 마지막 명령은 명령으로 실행됩니다.

이 목록은 $@스크립트 시작 부분에 있는 스크립트의 명령줄 인수를 포함하는 위치 인수 목록에 내장되어 있습니다. 루프는 원래 목록의 마지막 요소가 언제 발견되는지 추적하고 이를 특별하게 처리합니다.

set명령을 위와 같이 사용하면 목록에 추가되고 shift목록의 첫 번째 요소(현재 작업 중인 요소)가 제거됩니다.

zsh특정 구문을 사용하면 이 내용을 더 짧고 우아하게 만들 수 있다고 확신합니다 .

답변2

나는 당신이 루프에서 쉽게 벗어날 수 없다고 생각합니다.

cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log

엄밀히 말하면, 전달하는 쉘 명령줄이므로 이러한 임의의 값을 지원할 수 있으 ssh려면 이러한 매개변수를 인용하고 각 ssh에 인용 수준을 추가해야 합니다.$1$2

여기서는 모든 호스트의 사용자 로그인 쉘이 Bourne과 유사하다고 가정합니다.

cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv)) {
  cmd=(ssh -t "$argv[-1]" ${(j: :)${(qq)cmd}})
  argv[-1]=()
}

이렇게 하면 호출 시 작동하게 됩니다.

that-script host1 host2 'dir with spaces and other nasty characters'

관련 정보