Aparentemente, as pessoas tentam manter os processos iniciados em ssh
execução, mesmo quando a conexão termina, consulte https://duckduckgo.com/?q=ssh+process+still+active+after+connection+close
Então eu acreditava que os processos normalmente seriam encerrados com a conexão - até hoje.
grep
Analisando aleatoriamente a saída de ps
na minha máquina, encontrei processos que gerei semanas atrás usando ssh
e me perguntei como eles chegaram lá, e agora não sei como não manter um processo ativo (consulte https://xkcd.com/2797 ).
Iniciando processos de longa execução como htop
, sleep
ou dmesg
como usuário normal (mas qualquer outro usuário também está bem) assim
ssh localhost sleep 123
permaneça vivo até que eu os mate manualmente.
pstree -spc $(pgrep -f "sleep 123")
enquanto a conexão ainda está viva me dá
systemd(1)───sshd(1299)───sshd(1887616)───sshd(1887654)───sleep(1887655)
Mas depois de encerrar a sessão ssh (usando CTRL-C), o mesmo comando me dá
systemd(1)───sleep(1887655)
Então, para mim, parece sshd
que a conexão acabou, mas em vez de encerrar o processo associado, ele a entrega systemd
.
Mesmo que todos pareçam tentar conseguir o oposto, como posso ter certeza de que o encerramento de uma ssh
conexão também encerra/interrompe o processo gerado?
Nota: ssh localhost -t sleep 123
de alguma forma resolve meu problema, mas IMO porque muda a maneira como stdin/stdout está sendo tratado. Posso dizer ssh
para não entregar processos depois que a conexão for encerrada?
O sshd nunca finaliza processos em primeiro lugar. Tudo o que ele faz é sair quando você se desconecta, e os processos filhos restantes obtêm automaticamente o PID 1 como seu novo pai; a saída automática que você espera é feita por outra coisa.
(Além disso, esta não é uma transferência explícita do sshd – é algo que sempre acontece sempre que um processo não tem mais um pai, e esse tem sido o comportamento padrão desde os primeiros dias do UNIX.)
Se você executar uma conexão SSH interativa - uma com um tty associado - então ter a saída sshd "desligará" implicitamente o dispositivo tty, o que faz com que o sistema operacional envie automaticamente um SIGHUP para todos os processos que o tinham como controle tty. A maioria dos programas interpreta este sinal como uma indicação de que devem sair. Daí o nome da
nohup
ferramenta popular – ela faz os programas sobreviverem simplesmente ignorando o SIGHUP. (Embora os "daemons" muitas vezes o utilizem indevidamente como um sinal de 'recarregamento' e, portanto, não saiam.)O acima acontece quando você a) não especifica nenhum comando e é colocado em um shell interativo ou b) especifica um comando e a
-t
opção.No entanto, executar
ssh
com um comando direto (e sem-t
) desativa a alocação tty e substitui stdin/stdout por pipes – comparessh myhost tty
comssh -t myhost tty
– e os pipes não fazem a coisa de "SIGHUP imediato", o que significa que não há nada que sinalize imediatamente os processos para sair, então eles continuam em execução e o sistema operacional apenas os repara no PID 1. Eles podem eventualmente sair ou serem mortos posteriormente quando tentarem escrever algo no stdout e receber um SIGPIPE (devido à outra extremidade do tubo stdout já sendo fechados), mas talvez não.(Os pipes são usados neste modo porque são "limpos de 8 bits", ou seja, qualquer valor de byte de 0 a 255 passará inalterado, enquanto os dispositivos tty geralmente executam processamento adicional que é útil para uso interativo, mas corromperia os dados binários. )
Existem mecanismos que o sshd poderia usar para fazer com que os processos filhos morressem (PDEATHSIG), mas ele nunca os usou, até onde eu sei.
Somente com o systemd um novo mecanismo para eliminar processos restantes foi realmente adicionado. Se você
KillUserSomething=
habilitou em /etc/systemd/logind.conf, isso fará com que o systemd mate tudo deliberadamente quando a sessão terminar (ou talvez quando o usuário não tiver mais sessões; não me lembro de imediato). Algumas distribuições permitem isso por padrão, outras não.O mecanismo systemd funciona através do mecanismo de 'sessão' do PAM, quando o sshd chama "fechar sessão" antes de sair (pam_systemd também tem uma maneira de detectar quando o processo morre) e mata tudo no cgroup que foi gerenciado pelo systemd-logind.