Execute o script local com o arquivo de entrada local no host remoto

5

Eu tenho um script local que desejo executar em vários servidores remotos. A sintaxe de comando que estou usando é:

ssh <remote_server> "bash -s" < ./local_script.sh

Isso funciona bem e até me permite passar parâmetros para local_script.sh . No entanto, eu realmente gostaria de passar um arquivo de entrada para ele, como em:

local_script.sh < local_file.txt

A combinação dessas duas declarações fornece:

ssh <remote_server> "bash -s" < ./local_script.sh < local_file.txt

Quando eu corro isso, eu pego

bash: line 1: FOO: command not found
bash: line 2: BAR: command not found
bash: line 3: BAZ: command not found
...

onde FOO, BAR, BAZ, etc. são a primeira palavra em cada linha de local_file.txt :

FOO     FOO_PARAM1
BAR     BAR_PARAM1
BAZ     BAZ_PARAM2
...

Portanto, parece que "bash -s" no servidor remoto está interpretando local_file.txt como um arquivo de script, em vez de um arquivo de entrada para local_script.sh . Existe alguma maneira de corrigir isso (além de criar um script de wrapper)?

    
por Nester 28.09.2016 / 20:30

2 respostas

5

Enquanto ssh fornece dois fluxos de saída separados (para stdout e stderr), ele alimenta apenas um fluxo de entrada (stdin). Então, você precisaria passar o conteúdo do script e o arquivo de entrada por meio de mecanismos diferentes.

Por exemplo, um através de uma variável, um via stdin:

LC_CODE=$(cat local_script.sh) ssh host 'eval "$LC_CODE"' < input

(supondo que seu cliente ssh passe a variável LC_* ( SendEnv in ssh_config ) e o servidor sshd os aceite ( AcceptEnv in sshd_config ))

Ou simplesmente passe o conteúdo do local_script.sh como o código do shell remoto supondo que o shell de login do usuário remoto seja o correto para a sintaxe desse script:

ssh host "$(cat local_script.sh)" < input

Ou concatene o código e a entrada alimentados para o stdin de ssh como:

{
  echo '{'; cat local_script.sh; echo '}; exit'
  cat input
} | ssh host 'bash -s some arguments'

Aqui, usando bash , porque bash cuidará da leitura da entrada, um byte de cada vez, para não ler além daquela linha }; exit , enquanto nem todas as outras camadas fazem isso.

Ou se sed no host remoto for GNU sed :

echo '#END-OF-SCRIPT' | cat local_script.sh - input |
  ssh host 'set some arguments; eval "$(sed -u "/^#END-OF-SCRIPT/q")"'

(aqui tendo o código avaliado pelo shell de login do usuário remoto e assumindo que é como o Bourne)

    
por 28.09.2016 / 22:49
1

Isso funciona bem e até permite que você passe o conteúdo de vários arquivos para o script:

ssh host "bash -s -- '$(cat local_file_1.txt)'  '$(cat local_file_2.txt)'" < local_script.sh

A explicação é que ssh executará bash -s no login, com os argumentos de script sendo tudo depois de -- . Portanto, $1 será o conteúdo de local_file_1.txt e $2 será o conteúdo de local_file_2.txt . bash -s lê os comandos do stdin que vem de < local_script.sh .

    
por 13.04.2017 / 23:08