O SSH não aloca um pseudo-TTY quando você especifica um comando para ser executado. Tente adicionar a opção "-t" para substituir isso.
Eu tenho alguns firewalls do Juniper SSG que preciso gerenciar, e gostaria de poder enviar comandos para eles a partir de alguns scripts de monitoramento. Configurei o acesso SSH usando chaves públicas e consigo fazer login automaticamente nos firewalls.
Quando executo o SSH interativamente, tudo funciona bem:
$ssh <firewall IP>
FIREWALL-> <command>
<command output>
FIREWALL-> exit
Connection to <firewall IP> closed.
$
Mas quando tento executar o comando a partir da linha de comando, não funciona:
$ssh <firewall IP> <command>
$
Isso, é claro, funciona bem ao enviar um comando para uma caixa Linux remota:
$ssh <linux box IP> <command>
<command output>
$
Por que isso está acontecendo? Qual é a diferença entre executar o SSH interativamente e especificar o comando para executar na linha de comando do SSH?
Também funciona bem com um roteador Cisco. Apenas esses firewalls da Juniper parecem se comportar dessa maneira.
Da saída de depuração do SSH, parece que a conexão é estabelecida corretamente, mas a caixa Juniper responde com um EOF ao enviar o comando, enquanto a caixa do Linux responde com a saída real do comando:
Linux:
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug2: channel 0: send open
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug1: Sending command: uptime
debug2: channel 0: request exec confirm 0
debug2: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug2: channel 0: rcvd adjust 131072
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
16:44:44 up 25 days, 1:06, 3 users, load average: 0.08, 0.02, 0.01
debug2: channel 0: rcvd eof
debug2: channel 0: output open -> drain
debug2: channel 0: obuf empty
debug2: channel 0: close_write
debug2: channel 0: output drain -> closed
debug2: channel 0: rcvd close
debug2: channel 0: close_read
debug2: channel 0: input open -> closed
debug2: channel 0: almost dead
debug2: channel 0: gc: notify user
debug2: channel 0: gc: user detached
debug2: channel 0: send close
debug2: channel 0: is dead
debug2: channel 0: garbage collecting
debug1: channel 0: free: client-session, nchannels 1
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.1 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 0
Juniper:
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug2: channel 0: send open
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
debug2: channel 0: request env confirm 0
debug1: Sending command: get system
debug2: channel 0: request exec confirm 0
debug2: callback done
debug2: channel 0: open confirm rwindow 2048 rmax 1024
debug2: channel 0: rcvd eof
debug2: channel 0: output open -> drain
debug2: channel 0: obuf empty
debug2: channel 0: close_write
debug2: channel 0: output drain -> closed
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug2: channel 0: rcvd close
debug2: channel 0: close_read
debug2: channel 0: input open -> closed
debug2: channel 0: almost dead
debug2: channel 0: gc: notify user
debug2: channel 0: gc: user detached
debug2: channel 0: send close
debug2: channel 0: is dead
debug2: channel 0: garbage collecting
debug1: channel 0: free: client-session, nchannels 1
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.2 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 1
O SSH não aloca um pseudo-TTY quando você especifica um comando para ser executado. Tente adicionar a opção "-t" para substituir isso.
Passar o comando na linha de comando não é o mesmo que digitar comandos no shell. No primeiro caso, o shell precisa analisar os argumentos e, no segundo, ele precisa ler as linhas da entrada padrão.
Se é um shell interativo mudo (ou limitado, se você preferir chamá-lo), pode muito bem não ter sido codificado para suportar ambos (eu vi esse comportamento na prática). No entanto, como o shell obviamente suporta comandos digitados, você provavelmente teria mais sorte se enviasse todos os comandos para sua entrada padrão. Assim:
echo command | ssh ...
Como alguém comentou, tente adicionar -t ou mesmo -tt para forçá-lo. Um problema semelhante foi supostamente corrigido com essa solução alternativa.
Estou tendo um problema relacionado a este, na verdade, exceto para mim, ele está funcionando na CLI, mas não está funcionando no cron.
isso funciona em um SRX240:
( echo 'sh conf|d s|n'; echo 'quit' ) | ssh [email protected] "cli"
Isso pode ser melhorado ainda mais, fazendo com que ele use um heredoc bash para que você possa colar instruções completas nele, mas este exemplo deve guiá-lo suficientemente por enquanto.