Semelhante à minha perguntaaqui, exceto com vários ssh, e semelhante aessa questãomas com espaço em branco nos argumentos...
Gostaria de executar um script local test.sh
em um servidor remoto por meio de vários ssh. test.sh
aceita um argumento que geralmente contém várias palavras.
teste.sh:
#!/bin/bash
while getopts b: opt;
do
case $opt in
b)
bval="$OPTARG"
;;
esac
done
echo $bval
call_test.sh
#!/bin/bash
# Do some stuff
PHRASE="multi word arg"
ssh -A user@host1 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
e run ./call_test.sh
, isso gera corretamente
multi word arg
Mas quando eu mudo a última linha call_test.sh
para o seguinte:
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
e run ./call_test.sh
, ele gera:
multi
Basicamente, mudar de SSH único para SSH múltiplo quebra meu argumento de várias palavras.
Acho que os vários comandos ssh estão desembrulhando as aspas do argumento de várias palavras em cada etapa, mas não tenho certeza de como evitar isso. Alguma idéia de como passar com êxito o argumento de várias palavras para o script executado em vários ssh?
Editar:
Eu acreditoesta respostachega ao problema que estou enfrentando.
Responder1
Se você passar por 2 comandos ssh, será necessário escapar aspas da string DUAS VEZES. Faça isso com uma PHRASE=${PHRASE@Q}
tarefa extra.
Tenha cuidado, no entanto, que ambos ${var@Q}
e printf %q
(descritos abaixo) usarão o $'...'
formato quote-escape, que pode não ser suportado pelo shell remoto.
Depois de corrigir a última linha do seu test.sh
script em echo "$bval"
vez de echo $bval
:
PHRASE="multi word arg"
PHRASE=${PHRASE@Q}
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
multi word arg
Em vez do ${var@P}
formulário de expansão que não é compatível com versões mais antigas do bash, você pode usarprintf -v var %q
:
PHRASE="multi word arg"
printf -v PHRASE %q "$PHRASE"
printf -v PHRASE %q "$PHRASE"
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "$PHRASE"
Além disso, em vez de fornecer seu script via stdin, o que é ineficiente (o bash fará uma chamada de sistema de leitura para cada byte ao ler o script do stdin), você pode simplesmente colocar o script inteiro e seus argumentos em uma variável:
printf -v cmd 'bash -c %q bash -b %q' "$(cat test.sh)" 'multi word wahterve'
printf -v cmd %q "$cmd"
ssh localhost ssh localhost "$cmd"
multi word wahterve