Como sei quando um comando executado sobre ssh foi concluído?

1

Estou criando scripts de implantação para o meu projeto e criando uma função que deve ser capaz de executar um comando local e remotamente (em um servidor através do ssh) e retornar a saída de texto.

Ao executar um comando local, posso saber facilmente se o comando foi concluído aguardando seu PID. Quando envio um comando por uma conexão SSH aberta, recebo a saída novamente, mas não sei se o comando saiu ou se o comando ainda está em execução e gerará mais saída posteriormente.

Atualmente, eu "resolvi" isso abrindo uma nova conexão com o servidor para cada comando, o que nem é preciso dizer que é terrivelmente lento .

Parece que isso pode ser um problema comum e pode ter uma solução simples, talvez até algo embutido no SSH, por isso estou perguntando aqui: Como posso, em uma conexão SSH aberta, saber se os comandos que eu tenho enviado estão concluídos. Se eu pudesse, de alguma forma, coletar o código de saída também seria ótimo.


Para dar um exemplo mais concreto, isso basicamente demonstra meu problema no Ruby:

io = IO.popen(["ssh", "-q", "my-server"], "r+")

io.write("some command\n")

# Sleep for some arbitrary amount of time, because I don't know when the
# command has finished :(
sleep 1

output = io.readpartial(1_000_000)

io.write("some command\n")

# Sleep for some arbitrary amount of time, because I don't know when the
# command has finished :(
sleep 1

output = io.readpartial(1_000_000)
Hubro
fonte
Que tal executar um script e negociar como foi executado localmente ou fornecer um comando longo (algo como) Mycommnad; InterestingPID=$? ; ... ;wait $InterestingPIDcomo comando de várias linhas da instrução ssh? BTW você pode usar wait?
Hastur 23/06
@Hastur eu tenho medo que eu não entendo o que você quer dizer ...
Hubro
Me desculpe, eu não estava suficientemente claro. Imagino que você quer fazer algo como isso , pegando o PID de um comando por exemplo ( my_command -myoptions AndParameters) com LetsStoreInterestingPID=$? apenas após o comando, e depois de alguns outros comandos wait $LetsStoreInterestingPID...
Hastur

Respostas:

2

Envolva seu comando em um script que o notificará quando terminar.

Se você tem um servidor SMTP disponível que aceita e-mails enviados do seu servidor, você pode usá-lo.

O exemplo abaixo será executado your-command, capturará sua saída e stderr em um arquivo e, em seguida, usará malixpara enviar os resultados. Certamente há uma maneira muito melhor de garantir que o arquivo capturado pela saída seja exclusivo do que usar o $$pseudovariável (talvez use uma rotina que gere uma sequência aleatória).

#/bin/bash
your-command > /tmp/$$.$0.output 2>&1
RESULT=$?
echo >> /tmp/$$.$0.output
echo "Exit code $RESULT" >> /tmp/$$.$0.output
cat /tmp/$$.$0.output | mailx -s "your-command has finished with exit code $RESULT." [email protected]
rm /tmp/$$.$0.output

Se você deseja algo que permita especificar uma fila de comandos, consulte o Spooler de Tarefas ( apt-get install tspno Debian), que permite adicionar e excluir comandos de uma fila e acredito que pode enviar por e-mail a saída deles.

Lendo sua pergunta com mais cuidado ... parece que você está tratando o que a conexão SSH está entrando / saindo como um fluxo de E / S bruto.

O SSH fornece um canal criptografado e possui alguns recursos para encaminhamento de porta, e não muito mais. A coisa típica conectada a esse tubo é uma concha que normalmente espera um usuário interativo do outro lado.

Eu acho que as chaves de uso único podem alcançar o que você está tentando fazer com alguma facilidade, mas o mais fácil será criar um pequeno script de wrapper que faça isso:

#/bin/bash
$@ 
echo "==== Command Output Finished ===="

e, em seguida, procure a cadeia de caracteres ==== Command Output Finished ====em suas rotinas de E / S para determinar onde estão os limites entre as saídas do comando. Obviamente, você deve escolher algo que não possa ser parte de uma saída válida para um comando. Um esquema mais elaborado é possível.

O SMTP faz algo semelhante com os cabeçalhos de limite.

LawrenceC
fonte
Meu problema é que estou executando comandos rápidos como o find -type f -exec chmod 664que leva 0,001 segundos ou mais. Quando abro uma conexão SSH para cada comando, eles acabam levando vários segundos cada, o que torna meu script de implantação lento. Envolvendo servidores SMTP e-mail provavelmente não vai consertar isso ...
Hubro
@Hubro Criar a lista de comandos para executar e usar esta solução pode ajudar? (o que está com cat list_of_command | ssh ...) #
2139 Hastur
Eu atualizei minha resposta.
LawrenceC
Parece com o que planejei como minha solução de backup. Pensei em gerar uma sequência SHA1 aleatória e anexá-la ; echo "$? c8m2js7a9...após cada comando enviado ao servidor e usá-la para saber quando o comando foi concluído e ler o status de saída. Eu só esperava que talvez houvesse uma solução mais elegante, como a execução de comandos, como de costume, que estão sendo executados de forma transparente no servidor remoto.
Hubro 24/06
0

Se você mantiver a solução de executar cada comando em uma sessão SSH separada, poderá acelerar o tempo necessário para iniciar cada sessão usando uma conexão já aberta. Isso significa que você só precisa pagar a sobrecarga da conexão uma vez, agilizando o início das sessões subseqüentes.

A maneira mais simples de configurá-lo é abrindo a primeira conexão com isso:

ssh -M -S /tmp/ssh_mux_%h_%p_%r myserver

Em seguida, abra cada conexão subsequente com:

ssh -S /tmp/ssh_mux_%h_%p_%r myserver "command"

Há mais informações na página de ssh_configmanual em ControlMastere ControlPath, ou online aqui e aqui .

Tim
fonte