Questão Como sei quando um comando executado sobre o ssh terminou?


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

Ao executar um comando local, posso facilmente saber se o comando terminou aguardando seu PID. Quando envio um comando através de uma conexão SSH aberta, recebo a saída de volta, 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 é desnecessário dizer que é excruciante lento.

Isso parece ser um problema comum e pode ter uma solução simples, talvez até mesmo algo embutido no SSH, então estou perguntando aqui: como eu, em uma conexão SSH aberta, sei se os comandos enviados estão acabados. 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)

1


origem


Que tal executar um script e lidar como foi executado localmente ou para dar um longo comando (algo como) Mycommnad; InterestingPID=$? ; ... ;wait $InterestingPID como comando multi-line de instruções ssh? BTW você pode usar wait? - Hastur
@Hastur Tenho medo de não entender o que você quer dizer ... - Hubro
Me desculpe, eu não estava claro o suficiente. Eu imagino que você quer fazer algo assim, pegando o PID de um comando, e. ( my_command -myoptions AndParameters) com LetsStoreInterestingPID=$?  logo após o comando e depois de alguns outros comandos wait $LetsStoreInterestingPID... - Hastur


Respostas:


Envolva o seu comando em um script que irá notificá-lo quando estiver pronto.

Se você tiver um servidor SMTP disponível que aceitará emails de saída do seu servidor, você poderá usá-lo.

O exemplo abaixo será executado your-command, capture sua saída e stderr para um arquivo, então use malix para enviar os resultados. Há certamente uma maneira muito melhor de garantir que o arquivo que a saída é capturada seja único do que usar o arquivo $$ pseudovariável (talvez use uma rotina que gera uma string 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." you@some-mail-server.invalid
rm /tmp/$$.$0.output

Se você quiser algo que permita especificar uma fila de comandos, procure Spooler de Tarefas (apt-get install tsp no Debian), que permite adicionar e excluir comandos de uma fila e acredito que pode até mesmo enviar por e-mail a saída deles.


2



Meu problema é que estou executando comandos rápidos como find -type f -exec chmod 664 o que leva 0,001 segundos ou mais. Quando estou abrindo uma conexão SSH para cada comando desse tipo, eles acabam demorando vários segundos cada, o que torna meu script de implantação lento. Envolvendo servidores SMTP e email provavelmente não irá corrigir isso ... - Hubro
@Hubro Crie a lista de comandos para executar e usar esta solução pode ajudar? (aquele com cat list_of_command | ssh ...) - Hastur
Eu atualizei minha resposta. - LawrenceC
Isso parece o que planejei como minha solução de backup. Eu pensei em gerar uma string SHA1 aleatória e anexar ; echo "$? c8m2js7a9... depois de cada comando eu envio para o servidor, e uso isso para saber quando o comando terminar e ler o status de saída. Eu estava apenas esperando que talvez houvesse uma solução mais elegante, como executar comandos como de costume, que são transparentemente executados no servidor remoto. - Hubro


Se você mantiver a solução de cada comando executado 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 de conexão uma vez, tornando as sessões subseqüentes rápidas para começar.

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 no ssh_config manpage sob ControlMaster e ControlPathou online Aqui e Aqui.


0