Como posso executar o script local na máquina remota e incluir argumentos?

97

Eu escrevi um script que funciona bem quando executado localmente:

./sysMole -time Aug 18 18

Os argumentos "- time" , "Aug" , "18" e "18" são passados com sucesso para o script.

Agora, esse script foi projetado para ser executado em uma máquina remota, mas a partir de um diretório local na máquina local. Exemplo:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

Isso também funciona bem. Mas o problema surge quando tento incluir os argumentos acima mencionados (- time ago 18 18) , por exemplo:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

Depois de executar esse script, recebo o seguinte erro:

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

Por favor, me diga o que estou fazendo de errado, isso é muito frustrante.

    
por AllenD 20.08.2013 / 03:52

3 respostas

132

Você estava muito perto do seu exemplo. Funciona bem quando você o usa com argumentos como esses.

Script de exemplo:

$ more ex.bash 
#!/bin/bash

echo $1 $2

Exemplo que funciona:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

Mas isso falha para esses tipos de argumentos:

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

O que está acontecendo?

O problema que você está enfrentando é que o argumento -time ou --time no meu exemplo está sendo interpretado como uma mudança para bash -s . Você pode pacificar bash finalizando-o de usar qualquer um dos argumentos de linha de comando restantes usando o argumento -- .

Assim:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

Exemplos

# 1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

# 2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

# 3:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

# 4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

OBSERVAÇÃO: Apenas para deixar claro que onde quer que o redirecionamento apareça na linha de comando não faz diferença, porque ssh chama um shell remoto com a concatenação de seus argumentos de qualquer maneira, a citação não faz muita diferença, exceto quando você precisa citar no shell remoto como no exemplo # 4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>
    
por 20.08.2013 / 04:05
3

Como lidar com argumentos arbitrários

Se você realmente está usando apenas uma única string, por exemplo. -time Aug 18 18 , então você pode simplesmente codificá-lo e as respostas existentes informam como fazer isso adequadamente. Por outro lado, se você precisar passar argumentos desconhecidos (como uma mensagem a ser exibida no outro sistema ou o nome de um arquivo criado onde os usuários finais podem controlar seu nome), então é necessário ter mais cuidado.

Com bash ou ksh como /bin/sh

Se o seu controle remoto /bin/sh for fornecido por bash ou ksh, você pode seguramente fazer o seguinte com uma lista de argumentos não confiáveis, de forma que nomes maliciosos (como $(rm -rf $HOME).txt ) possam ser passados como argumentos com segurança:

runRemote() {
  local args script

  script=$1; shift

  # generate eval-safe quoted version of current argument list
  printf -v args '%q ' "$@"

  # pass that through on the command line to bash -s
  # note that $args is parsed remotely by /bin/sh, not by bash!
  ssh user@remote-addr "bash -s -- $args" < "$script"
}

com qualquer /bin/sh compatível com POSIX

Para estar protegido contra dados de argumentos suficientemente maliciosos (tentando tirar proveito da citação não compatível com POSIX usada por printf %q no bash quando caracteres não-imprimíveis estão presentes na cadeia que está sendo escapada) mesmo com /bin/sh que é a linha de base -POSIX (como dash ou ash ), fica um pouco mais interessante:

runRemote() {
  local script=$1; shift
  local args
  printf -v args '%q ' "$@"
  ssh user@remote-addr "bash -s" <<EOF

  # pass quoted arguments through for parsing by remote bash
  set -- $args

  # substitute literal script text into heredoc
  $(< "$script")

EOF
}

Uso (para qualquer um dos acima)

As funções dadas acima podem ser chamadas como:

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

... ou ...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"
    
por 28.11.2016 / 22:38
-3

diz que a.a é um arquivo local que contém ls

$ssh servername "cat | bash" < a.a

altere 127.0.0.1 para qualquer que seja o seu ip remoto

estes dois dão uma mensagem sobre a alocação do pseudo-tty mas eles funcionam.

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

Ou

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a

    
por 11.06.2015 / 12:06