Processo de morte gerado pelo ssh quando o ssh morre

23

Esta é uma pergunta que foi abordada várias vezes, não apenas aqui, mas também em outros sites da rede de troca de pilhas (por exemplo, como fazer o ssh matar o processo remoto quando eu interrompo o próprio ssh? ). No entanto, não posso fazer nenhuma das soluções funcionar para mim.

Estou executando um comando através do ssh. Sempre que eu sair do ssh, quero que o comando morra também. Este comando é um daemon chamado ktserver que é executado indefinidamente até você pressionar Ctrl-C.

Eu o executo da seguinte maneira: ssh -t compute-0-1 ktservere, de fato, quando pressiono Ctrl-C, o processo termina normalmente e a sessão ssh termina.

No entanto, se em vez de pressionar Ctrl-C, eu matar o processo ssh usando o killcomando (por exemplo, enviando SIGINT ou SIGHUP), o ktserverprocesso permanecerá ativo.

Como posso fazer o ktserversempre morrer independente de como sshé morto?

Edição : Se, em vez de ktservereu executar algo completamente diferente, como gedit, tudo funciona como um encanto (ou seja, gedit morre quando a conexão morre). Portanto, pode haver algo errado com o próprio processo. Por exemplo, eu pensei que poderia estar ignorando SIGHUP ou SIGINT. No entanto, quando executo kill -1 ktserverou kill -2 ktserver, o processo morre conforme o esperado.

EDIT2 : Como aponta Mark Plotnick, o problema está relacionado ao fato de não haver comunicação circulando no canal ssh. Confirmei executando ssh -t <host> reade matando o processo ssh posteriormente. readainda estava vivo e chutando.

Alemão
fonte
Você já tentou kill -9 ktserver?
@HermanTorjussen Claro, isso funciona. O problema é que esse comando é executado em outro processo e talvez eu não tenha controle sobre todas as possibilidades que podem causar a morte do meu processo e, portanto, a sessão ssh com ele. Por isso, preciso de uma maneira confiável de garantir que, sempre que meu processo - e, portanto, desmoronar, o ktserver morrerá com eles.
precisa saber é
Minha experiência com o Linux é que, se o comando remoto não fizer nenhuma E / S na conexão dead tcp, ele continuará em execução. Os ssh example.com dd ...trabalhos foram concluídos até horas depois que a sshconexão morreu devido a problemas de rede. Se você pode alterar ktservera opção de gerar algo de vez em quando, isso pode ser uma solução alternativa.
Mark Plotnick
@ MarkPlotnick De fato, tentei rodar readno computador remoto e, depois de matar a conexão ssh, readnão morreu. Infelizmente, não posso mudar o ktserver para produzir nada. Não há solução então?
precisa saber é o seguinte
2
Presumo que, quando o ssh morre, seu shell também morre. Você pode configurar seu shell para enviar um sinal -1 (SIGHUP) quando ele terminar. ( shopt -s huponexit) Você pode testar se isso funciona para você?
Hennes

Respostas:

13

Geralmente, quando a conexão ssh morre, o shell também morre. Você pode configurar seu shell para enviar um sinal -1 (SIGHUP) quando terminar para todos os seus filhos.

Para o bash, você pode configurar esta opção através do comando interno shopt . ( shopt -s huponexit)

Para zsh você quer .setoptHUP

Hennes
fonte
Eu pensei que esta era a resposta para o meu problema atual, mas parece não funcionar. Estou executando: ssh $ host "scp LargeFile.dat $ OtherHost: / tmp" & pid = $! e, em seguida, tentando interromper essa transferência com: shopt -s huponexit; mate $ pid, mas o scp não para quando eu mato o ssh que iniciei. Alguma ideia?
David Doria
Você pode testar com as opções de shell definidas antes de iniciar o comando scp? Ou iniciando um shell, configurando shopt e iniciando scp?
Hennes
2
Isso funciona para mim, mas primeiro tive que me certificar de que estava usando ssh -t -t(observe -tduas vezes!) O que força a alocação de tty, em vez de apenas pty.
Nicolas Wu
13

Eu descobri que simplesmente usar -t -tcomo argumento para sshfazer funcionar. Não precisei definir huponexito shell de origem ou remoto.

Eu testei isso da seguinte maneira:

Não funciona:

ssh user@remote sleep 100
^C

Isso matou a sessão ssh, mas posso ver que o processo de suspensão ainda está em execução no host remoto ( ps -ef | grep sleepmostra).

Funciona:

ssh -t -t user@remote sleep 100
^C

Isso mata a sessão ssh e o processo de suspensão remota também foi interrompido. Também verifiquei que o sinal enviado ao processo remoto é SIGINTse você usar Control- C. Também verifiquei que o SIGKILL (-9) aplicado ao sshprocesso também matará o processo remoto.

EDIT 1:

Isso era verdade para sleep... para processos remotos mais teimosos, descobri que sshlida com ^ C de maneira diferente do SIGINT. Ctrl- Cfuncionou, mas não kill -INT $pidfuncionou

Aqui está o que eu finalmente descobri que funcionou para a minha aplicação real (roubando as outras respostas).

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

Observe o uso aninhado de aspas duplas e aspas simples. Observe que seu processo remoto DEVE responder ao SIGHUP saindo realmente!

Mark Lakata
fonte
Isso funcionou melhor para mim, mas, para sua informação, também causou a perda de caracteres de controle do terminal, o que pode causar resultados engraçados. Portanto, a solução mais fácil no meu caso foi agrupar os comandos chamados e canalizar sua saída cat. Por exemplo, #ssh -ttq user@host '{ cmd; cmd; } | cat'
Droj 17/06
Ctrl-Cnem sempre é equivalente a kill -INT $pid, ver a minha resposta sobre unix.stackexchange.com/questions/377191/... e outro sobre stackoverflow.com/questions/8398845/... para os detalhes ;-)
thecarpy
@thecarpy - sua primeira resposta diz que Ctrl-C é semelhante ao SIGINT e a outra resposta diz que ^Cenvia SIGINT . Então, qual é a diferença exata se eles não são equivalentes?
MarkLakata
1

Se o ssh não propagar sinais, ele recebe o que você esperaria dele?

UPD. (especial para JosephR): é obviamente um erro em questão que resulta de mal-entendidos - "Processo de matança gerado pelo ssh quando o ssh morre". O SSH normalmente não gera processos (às vezes ocorre, mas essa é outra história), mas o SSHD, quando olhamos para o outro lado da conexão. O SSH apenas depende do servidor remoto de abstração pseudo-terminal. É por isso que a única coisa que pode ajudar é a capacidade do terminal de emitir sinais para seus processos conectados. Isso é bastante básico para todos os sistemas semelhantes ao UNIX.

poige
fonte
1
Isso não fornece uma resposta para a pergunta. Para criticar ou solicitar esclarecimentos a um autor, deixe um comentário abaixo da postagem.
Anthon
@ Anthon, é uma explicação. Mas ninguém está afirmando que essa deve ser a única resposta correta. Obrigado pelo seu comentário abaixo.
precisa
1
@poige Talvez explique a explicação para que possa ser útil ao OP e a outros.
Joseph R.
@ JosephphR., Ok, apenas para você.
poige
1
Se eu disser "Processo de interrupção gerado pelo sshd quando a conexão ssh for perdida", pareceria melhor para você? Não acho que reformular resolva meu problema de forma alguma.
GermanK
0

A solução postada aqui não funcionou para mim, mas como essa pergunta surgiu primeiro, quando eu estava procurando por uma solução para um problema semelhante e também -t -tfoi mencionado um truque, vou postar uma solução que funcionou para mim para outras pessoas tentarem.

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

Meu comando de longa duração não estava mais sendo executado quando a conexão foi encerrada assim.

Greg0ry
fonte