1. Script em Args

1. Script em Args

Suponha que eu queira me conectar à máquina B por meio da máquina A. Como aprendi, existem várias maneiras de fazer isso, por exemplo

ssh -T -J user@machineA user@machineB << END_OF_SSH_CONNECTION
  # Some commands in machine B
END_OF_SSH_CONNECTION

ou

ssh -T user@machineA << END_OF_MACHINE_A
  ssh -T machine B << END_OF_MACHINE_B
    # Some commands in machine B
  END_OF_MACHINE_B
END_OF_MACHINE_A

No entanto, não está claro para mim como iniciar um shell interativo onde o usuário possa digitar comandos quando conectado à máquina B. Por exemplo, isso funciona:

ssh user@machineA -t 'bash -l -c "bash"'

e isso também funciona:

ssh -J user@machineA user@machineB -t 'bash -l -c "bash"'

O seguinte não funciona, no entanto:

ssh -J user@machineA user@machineB -t 'sudo apt-get update; bash -l -c "bash"'
E: Command line option 'l' [from -l] is not understood in combination with the other options.
Connection to machineB closed.

E nem o seguinte:

ssh -J user@machineA user@machineB -t 'if [ 1 -eq 1 ]; then bash -l -c "bash"; fi'
/usr/local/sbin/start_ttylog.sh: line 67: exec: if: not found
Connection to machineB closed.

Eu também tentei isso:

ssh -T -J user@machineA user@machineB << EOF

  # Some commands on machineB

  # Check whether apache2 has been correctly installed
  if [ $(dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -c "ok installed") -eq 1 ];
  then
    printf "done\n";
  else
    printf "fail\nStarting an interactive shell: enter exit to quit\n";
    bash -l -c "bash";
  fi
EOF

Esta última versão quase funciona (ou seja, não retorna erros), mas não inicia um shell interativo onde o usuário pode digitar comandos como seria de esperar.

Espero que alguém possa me ajudar. Desde já, obrigado.

Responder1

Obrigado pela ajuda, @attie. Modifiquei um pouco seu código proposto, que relato aqui abaixo

#!/usr/bin/env bash

ssh -T -J user@machineA user@machineB 'cat >/tmp/myscript' <<"EOF"
if dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -q 'ok installed'; then
  echo "done";
else
  echo "fail, starting an interactive shell";
  bash -l -c "bash";
fi
EOF

ssh -t -J user@machineA user@machineB "bash '/tmp/myscript'"

nisso, que nem precisa gravar em um arquivo externo.

#!/usr/bin/env bash

ssh -T -J user@machineA user@machineB << "EOF"
if dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -q "ok installed"; then
  echo "done";
else
  echo "fail, starting an interactive shell";
  bash -l -c "bash";
fi
EOF

Basicamente, eu estava sentindo falta das aspas EOF, usadas para evitar uma tentativa de expansão do campo ${Status}.

Responder2

Se você deseja executar um script no host remotoeobter um shell interativo, você terá duas opções:

  1. Coloque todo o script nos argumentos da linha de comando para ssh.
  2. Envie o script para o host remoto (por exemplo: usando scpou ssh) e execute-o (por exemplo: usando ssh)

1. Script em Args

Seu último exemplo está à beira de "longo" para esta abordagem, mas você pode ajudar na legibilidade usandomapfile(um embutido bash). Observe o citado "EOF"para evitar uma tentativa de expansão ${Status}.

mapfile -t SCRIPT <<"EOF"
if dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -q 'ok installed'; then
  echo "done";
else
  echo "fail, starting an interactive shell";
  bash -l -c "bash";
fi
EOF

ssh -t -J user@machineA user@machineB "${SCRIPT[@]}"

2. Envie o script e execute

Pontos de bônus por usar mktempe limpar depois. Nota citada "EOF"novamente.

Com base em uma das mensagens de erro fornecidas (em torno de exec, veja abaixo para mais informações), esse uso cat >/tmp/myscriptprovavelmente não funcionará.

ssh -T -J user@machineA user@machineB 'cat >/tmp/myscript' <<"EOF"
if dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -q 'ok installed'; then
  echo "done";
else
  echo "fail, starting an interactive shell";
  bash -l -c "bash";
fi
EOF

ssh -t -J user@machineA user@machineB "bash '/tmp/myscript'"

O primeiro passo deve ser sempre tentar dividir o problema na forma mais simples... Quanto ao seu último encantamento, tente o seguinte:

ssh -T user@machineA << EOF
  bash -l -c "bash";
EOF

O que acontece? Você receberá mensagens de boas-vindas do host remoto, mas a sessão terminará imediatamente e silenciosamente, sem erros.

Alterar -T(explicitamentedesabilitarAlocação de PTY) para -t(forçar alocação de PTY) fornece uma dica na direção certa:

ssh -t user@machineA << EOF
  bash -l -c "bash";
EOF
Pseudo-terminal will not be allocated because stdin is not a terminal.

Isso indica que você está usando stdinpara fornecer um script e também tentando conectá-lo stdin(um canal, não um terminal) ao PTY remoto.

Então vamos remover o stdinfator:

ssh -t user@machineA bash -l -c "bash"

E funciona!

Fundamentalmente vocênão podecompartilhe stdin com um script e um terminal.


Quanto aos outros erros:

E: Command line option 'l' [from -l] is not understood in combination with the other options.

Novamente, analise-o para encontrar o problema. Infelizmente esses comandos funcionam para mim, suspeito porque os sistemas aos quais tenho acesso estão usando sh -c "${ARGS}"ou similares. No entanto, outro erro que você forneceu dá uma dica:

/usr/local/sbin/start_ttylog.sh: line 67: exec: if: not found

Parece que seu sistema está usando execpara executar o comando fornecido como argumento para ssh... o que significa que o shell não é capaz de lidar com coisas como ifou ;para você como você espera - então ifnão é um binário no caminho e falha .

Da mesma forma, todos os argumentos são dados de sudouma só vez:

  1. sudo
  2. apt-get
  3. update;
  4. bash
  5. -l
  6. -c
  7. "bash"

Com certeza, o argumento sudode -l(lista) é mutuamente exclusivo com -c(classe de login).

informação relacionada