Eu quero verificar se o comando exit
é executado com sucesso em uma sessão ssh.
Minha primeira tentativa é usar o comando:
exit && echo $? || echo $?'.The 'echo $? || echo $?
ele deve imprimir 0
se a saída for bem-sucedida. O problema é que echo
nunca é executado se exit
executar com êxito porque a conexão está desconectada e o comando posterior é perdido.
Minha segunda tentativa é dividir o comando em dois comandos, como este:
$ exit
$ echo $?
echo $?
deve ser 0
se exit
for executado com sucesso. Mas outro problema é echo $?
talvez ser engolido porque é enviado tão rapidamente que chegou ao host ssh remoto antes de exit
ser executado.
Então, como garantir que exit
seja executado no host remoto antes de enviar o próximo comando?
O estágio using é execute o comando shell em uma linguagem de programa e envie uma mensagem por um fluxo de pipe ssh. Portanto, não sei o tempo de execução do comando exit
. Se o comando exit
não for concluído, siga comandos serão engolidos porque eles enviam para o host que está saindo.
É por isso que me preocupo com o comando exit
executado.
No começo, quero descrever o problema da maneira mais simples possível, mas parece mais confuso. Estou escrevendo uma biblioteca SSH com o idioma Scala na biblioteca git .
Não é um terminal interativo. A mensagem de resposta do host remoto é o fluxo IO da rede, retida pelo programa, analisa o resultado como String. Isso significa que preciso lidar com todos os códigos de caracteres e finalmente decidir se o comando foi executado com sucesso ou não.
Algum código de exemplo é mostrado assim:
//create a ssh by JSch library which is a SSH implement by Java Language.
val shell = Shell(Auth("host", "username", 22, "mypassword"))
//execute shell command as we do at terminal for example.
val rst1 = shell.exc("ls")
//create a new shell based on this shell.
val newShell = shell.newShell(Auth("xxx.xxx.xxx.xxx", "username2", 22, "mypassword"))
//do something on the new shell
val rst2 = newShell.exc("touch somefile")
//exit from new shell
newShell.exit()
O newShell
é criado por sshpass -p 'password' ssh -T username@hostname
como um comando normal enviado por JSch
, portanto, não é mágica. É como enviar um comando normal, como ls
.
O problema na implementação do método exit()
, se ignorarmos o código Scala, ele se tornará o comando shell:
$ echo '' && echo 'some-splitter-string' && exit
$ echo $? && echo 'some-splitter-string'
Depois de enviar esse comando para o host remoto, o que espero é uma resposta, mas, na verdade, isso não acontece, estou anexando explicitamente um caractere \n
para ler diretamente:
\n
some-splitter-string\n
0\n
some-splitter-string\n
Isso significa que eu posso dividir o fluxo IO em dobro some-splitter-string
e obter o 0
(talvez outros) para decidir o comando exit
execute completed, que é o meu protocolo para decodificar um resultado do comando shell.
Na verdade, o comando exit()
me responde:
\n
some-splitter-string\n
O segundo comando echo $? && echo 'some-splitter-string'
está perdido! Isso porque o comando $ echo $? && echo 'some-splitter-string'
também foi enviado para o host do newShell.
Mas após exit
concluído, esse comando é engolido pelo host newShell. Apenas considere este comando simplesmente exit && touch somefile
. O último touch somefile
nunca pôde ser executado.
Minha solução atual é sleep 1s depois de enviar o comando echo '' && echo 'some-splitter-string' && exit
, deve ser mais elegância. Portanto, quero encontrar uma maneira de garantir que exit
seja executado e, em seguida, enviarei o segundo comando para concluir meu protocolo.
Como a "execução" da saída pode falhar?
Não é exatamente o foco na falha ou sucesso neste momento. Isso significa que, se exit
não pode falhar, deixe-me saber que a execução completa está ok.
Estamos falando de uma saída de casca aqui?
Sim, o objetivo da questão é encontrar uma maneira de decidir o comando de saída executado em um ambiente de pipe ssh.