script zsh que leva um número variável de argumentos

3

Acabei de descobrir (tardiamente) que posso ssh -t de uma máquina para outra e executar um comando lá.

O pensamento então me levou a pensar em um script que seguisse um arquivo de log (de um par) em uma máquina fazendo algo como

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

e, de fato, se eu colocar em 1,2 e 3 à mão, funciona bem.

Meu problema é que eu posso ter 1,2 ou 3 hosts para pular entre fazer isso funcionar.

Como eu faria isso em zsh? Eu fiz algumas escavações e parece que a mudança pode ser minha amiga, mas estou um pouco perdida.

    
por Peter NUnn 05.09.2018 / 14:46

2 respostas

2

Como eu não sou realmente um usuário zsh , vou escrever uma sh solution ( zsh deve ser capaz de executá-lo também).

A essência geral é criar uma lista com um ssh -t hostname bit para cada opção de linha de comando, exceto a última, e depois executar essa lista como um comando.

#!/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 "$@"

Executando isso como

sh script.sh alpha beta gamma zeta

criaria a lista

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

O último comando no script executaria isso como um comando.

A lista é construída em $@ , a lista de parâmetros posicionais, que no início do script contém os parâmetros da linha de comando do script. O loop registra quando o último elemento da lista original é encontrado e o trata especialmente.

O comando set , quando usado como acima, será anexado à lista e shift removerá o primeiro elemento da lista (aquele que estamos processando atualmente).

Tenho certeza de que isso poderia ser mais curto e mais elegante com a sintaxe zsh -específica.

    
por 05.09.2018 / 15:09
2

Eu não acho que você consiga fugir facilmente sem um loop:

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

Com relação a isso, já que é uma linha de comando do shell que você passa para ssh , se quisesse suportar valores arbitrários para esses $1 , $2 , seria necessário citar esses argumentos e adicionar um nível extra de cotação para cada ssh.

Aqui assumindo que o shell de login do usuário em todos os hosts é parecido com Bourne:

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

Isso deve funcionar quando chamado como

that-script host1 host2 'dir with spaces and other nasty characters'
    
por 05.09.2018 / 23:04