Depois de fazer login ssh
, digito este comando bash
:
sleep 50000000000000 &
Então eu kill -9
o sleep
processo pai do processo (ou seja, bash
). Então a janela do terminal se desconecta simultaneamente.
Quando faço login novamente, descubro que o sleep
processo ainda está ativo.
Pergunta: Por que o sleep
processo pode sobreviver quando eu saio e o terminal é fechado? Na minha opinião, tudo, exceto daemons e nohup
programas, será eliminado durante o logout. Se sleep
puder sobreviver dessa forma, isso significa que posso usar esse método em vez do nohup
comando?
Responder1
dr:
Por que o
sleep
processo pode sobreviver quando eu saio e o terminal é fechado? Na minha opinião, tudo, exceto daemons enohup
programas, será eliminado durante o logout. Sesleep
puder sobreviver dessa forma, isso significa que posso usar esse método em vez donohup
comando?
A menos que a bash
instância gerada por ssh
tenha a huponexit
opção definida, nenhum processo será encerrado de forma alguma ao sair/logout, e quando a huponexit
opção for definida, usar kill -9
no shell não é uma boa alternativa para usar nohup
nos processos filhos do shell; nohup
nos processos filhos do shell ainda os protegerá de SIGHUPs que não vêm do shell, e mesmo quando isso não for importante nohup
ainda é preferível porque permite que o shell seja encerrado normalmente.
Existe bash
uma opção chamada huponexit
, que se definida tornará bash
o SIGHUP seu filho ao sair/logout;
Em interativosem login bash
instâncias, como em uma bash
instância gerada por gnome-terminal
, esta opção é ignorada; esteja huponexit
definido ou não, bash
os filhos de nunca serão SIGHUPped na bash
saída;
Em interativoConecte-se bash
instâncias, como em uma bash
instância gerada por ssh
, esta opção não é ignorada (no entanto, ela não está definida por padrão); se huponexit
estiver definido, bash
os filhos de serão SIGHUPped bash
ao sair/logout; se huponexit
não estiver definido, bash
os filhos de 's não serão SIGHUPped bash
ao sair/logout;
Portanto, em geral, sair/efetuar logout de uma bash
instância de login interativa, a menos que a huponexit
opção esteja definida, não tornará o shell SIGHUP seu filho, e sair/efetuar logout de uma bash
instância interativa sem login não tornará o shell SIGHUP seu filho sem considerar;
Isto é, no entanto, irrelevante neste caso: using kill -9
sleep
sobreviverá independentemente, porque matar seu processo pai ( bash
) não deixará chance para o último fazer issoqualquer coisapara o primeiro (ou seja, por exemplo, se a bash
instância atual era uma bash
instância de login e a huponexit
opção foi definida, para SIGHUP).
Além disso, ao contrário de outros sinais (como um sinal SIGHUP enviado para bash
), um sinal SIGKILL nunca é propagado para os processos filhos de um processo e, portanto, sleep
nem mesmo é eliminado;
nohup
inicia um processo imune aos sinais SIGHUP, o que é algo diferente; evitará que o processo seja interrompido ao receber um sinal SIGHUP, que neste caso poderia ser recebido pela bash
instância de login interativo caso a huponexit
opção fosse definida e o shell fosse encerrado; portanto, tecnicamente, usar nohup
para iniciar um processo em uma bash
instância de login interativa com a huponexit
opção não definida impedirá que o processo seja interrompido após a recepção de um sinal SIGHUP, mas sair/sair do shell não o SIGHUP de qualquer maneira;
Em geral, porém, quando nohup
é necessário evitar que sinais SIGHUP venham do shell pai, não há razão para preferir o kill -9
método on the parent ao nohup
método on the child; em vez disso, deveria ser o oposto.
Matar o pai usando o kill -9
método não deixa uma chance para o pai sair normalmente, enquanto iniciar o filho usando o nohup
método permite que o pai seja encerrado por outros sinais, como SIGHUP (para dar um exemplo que faça sentido no contexto de uma criança começou a usar nohup
), o que permite que ela saia normalmente.
Responder2
bash
por padrãonão envia o sinal HUP para processos filhos ao sair. Mais detalhadamente (obrigado @kos), isso nunca aconteceshells sem login.
Você pode configurar o bash para fazer issoshells de loginse definir a opção huponexit
. Em um terminal, faça:
[romano:~] % bash -l
(isso inicia um novo shell de "login")
romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout
Agora verifique o sleep
processo:
[romano:~] % ps augx | grep sleep
romano 32231 0.0 0.0 16000 2408 pts/11 S+ 15:23 0:00 grep sleep
...não está em execução: recebeu o sinal HUP e saiu conforme solicitado.
Responder3
Se
sleep
posso sobreviver desta forma, se isso significa que posso usar este método em vez donohup
comando?
kill -9
realmente não é o caminho que se deve seguir. É como atirar com uma arma na TV para desligá-la. Além do componente cômico não há vantagem. Os processos não podem capturar ou ignorar SIGKILL
. Se você não der ao processo a chance de terminar o que está fazendo e limpá-lo, ele poderá deixar arquivos corrompidos (ou outro estado) e não será possível recomeçar. kill -9
é a última esperança, quando nada mais funciona.
Por que o processo de suspensão pode sobreviver quando eu saio e o terminal é fechado. Na minha opinião, tudo, exceto o daemon e o programa nohup, será eliminado ao sair.
O que acontece no seu caso:
O processo pai sleep
é o shell atualmente em execução bash
. Quando você kill -9
faz esse bash, o processo bash não tem a chance de enviar um SIGHUP
para nenhum de seus processos filhos, porque SIGKILL
(que é enviado por kill -9
) não é capturável pelo processo. O processo de suspensão continua em execução. dormir agora se tornou umprocesso órfão.
O processo init (PID 1) executa um mecanismo chamado reparenting. Isso significa que o processo init agora se torna o pai desse processo órfão. init é uma exceção, os processos podem se tornar filhos, pois coleta processos que perderam seu processo pai original. A propósito: um daemon (como sshd
) faz isso quando "está em segundo plano".
Se isso não acontecesse, o processo órfão mais tarde (quando concluído) se tornaria um processo zumbi. Isto é o que acontece quando waitpid()
não é chamado (uma responsabilidade do processo pai que não pode ser cumprida quando esse processo foi eliminado). init chama waitpid()
em um intervalo específico para evitar filhos zumbis.
Responder4
O uso &
fará com que o programa seja executado em segundo plano. Para ver o programa em segundo plano, use bg
o comando e, para fazê-lo rodar em primeiro plano novamente, execute fg
.
Sim, há muitas maneiras de manter o programa em execução mesmo com a saída do terminal principal.