O que exatamente determina se um trabalho em segundo plano é morto quando o shell é encerrado ou morto?

12

Esta questão surgiu bastante um monte ( realmente muito ), mas eu estou encontrando as respostas para ser geralmente incompleto. A pergunta geral é "Por que meu trabalho não é morto quando saio / ssh?", E aqui está o que encontrei. A primeira pergunta é: Quão geral é a seguinte informação? O seguinte parece ser verdadeiro para o Linux moderno Debian, mas estou faltando alguns bits; e o que os outros precisam saber?

  1. Todos os processos filhos, em segundo plano ou não de um shell aberto em uma conexão ssh, são eliminados com SIGHUP quando a conexão ssh é fechada apenas se a huponexitopção estiver configurada: execute shopt huponexitpara verificar se isso é verdade.

  2. Se isso huponexitfor verdade, você poderá usar nohupou disowndesassociar o processo do shell para que ele não seja morto quando você sair. Ou, execute as coisas com screen.

  3. Se huponexitfor false, que é o padrão em pelo menos alguns linuxes atualmente, os trabalhos em segundo plano não serão eliminados no logout normal.

  4. Mas mesmo se huponexité falsa, então se a conexão ssh se matou , ou gotas (diferentes do que o logout normal), processos, em seguida, backgrounded ainda vai ser morto. Isso pode ser evitado por disownou nohupcomo em (2).

  5. Há alguma distinção entre (a) processos cujo processo pai é o terminal e (b) processos que possuem stdin, stdout ou stderr conectados ao terminal . Não sei o que acontece com processos que são (a) e não (b), ou vice-versa.

Pergunta final: Como posso evitar o comportamento (3)? Em outras palavras, por padrão, os processos em segundo plano do Debian são executados sozinhos após o logout, mas não após a conexão ssh. Gostaria que o mesmo acontecesse com os processos, independentemente de a conexão ser fechada normalmente ou interrompida. Ou isso é uma má ideia?

Edit: Outra maneira importante de impedir que os trabalhos sejam mortos, que funciona (?) Em ambos os casos, é executá-los na tela . Mas, a questão é mais sobre como entender quando as coisas são mortas e quando não: às vezes as pessoas querem que os trabalhos sejam mortos no logout, por exemplo.

Mais tópicos: - Esclarecimento sobre sinais (suspiro), trabalhos e terminal de controle - /server/117152/do-background-processes-get-a-sighup-when-logging-off - Continue SSH tarefa / trabalhos em segundo plano ao fechar o SSH - Um trabalho colocado em segundo plano continuará em execução após o encerramento de uma sessão SSH? - Impedir que um processo em segundo plano já em execução seja interrompido após o fechamento do cliente SSH - Como posso iniciar um processo pelo SSH para que ele continue em execução após eu desconectar? - Não é possível manter o trabalho remoto em execução no OS X - Fechar a conexão SSH

petrelharp
fonte

Respostas:

1

Um processo não é "morto com SIGHUP" - pelo menos, não no sentido estrito da palavra. Em vez disso, quando a conexão é interrompida, o processo de controle do terminal (neste caso, Bash) recebe um sinal de desligamento *, que normalmente é abreviado como "sinal HUP" ou apenas SIGHUP.

Agora, quando um processo recebe um sinal, ele pode lidar com ele da maneira que desejar **. O padrão para a maioria dos sinais (incluindo o HUP) é sair imediatamente. No entanto, o programa é livre para ignorar o sinal ou mesmo para executar algum tipo de função do manipulador de sinal.

Bash escolhe a última opção. Seu manipulador de sinal HUP verifica se a opção "huponexit" é verdadeira e, em caso afirmativo, envia SIGHUP para cada um de seus processos filhos. Apenas uma vez terminado, o Bash sai.

Da mesma forma, cada processo filho é livre para fazer o que quiser quando receber o sinal: deixe-o definido como o padrão (por exemplo, morra imediatamente), ignore-o ou execute um manipulador de sinal.

Nohup altera apenas a ação padrão para o processo filho "ignorar". No entanto, uma vez que o processo filho está em execução, é gratuito alterar sua própria resposta ao sinal.

Acho que é por isso que alguns programas morrem mesmo que você os tenha executado com nohup:

  1. Nohup define a ação padrão para "ignorar".
  2. O programa precisa fazer algum tipo de limpeza quando sair, para instalar um manipulador SIGHUP, substituindo aliás o sinalizador "ignorar".
  3. Quando o SIGHUP chega, o manipulador é executado, limpando os arquivos de dados do programa (ou o que for necessário) e sai do programa.
  4. O usuário não conhece nem se importa com o manipulador ou a limpeza e apenas vê que o programa foi encerrado apesar do nohup.

É aqui que entra em "renúncia". Um processo que foi renegado por Bash nunca recebe o sinal HUP, independentemente da opção huponexit. Portanto, mesmo que o programa configure seu próprio manipulador de sinais, o sinal nunca é realmente enviado, portanto o manipulador nunca é executado. Observe, no entanto, que se o programa tentar exibir algum texto para um usuário desconectado, isso causará um erro de E / S, o que poderia causar a saída do programa de qualquer maneira.

* E, sim, antes de você perguntar, a terminologia de "interrupção" é deixada nos dias de mainframe dial-up do UNIX.

** A maioria dos sinais, pelo menos. SIGKILL, por exemplo, sempre faz com que o programa seja encerrado imediatamente, ponto final.

HiddenWindshield
fonte
2

Os pontos 1 a 4 estão corretos. Não sei nada sobre o ponto 5. Quanto ao seu ponto final, uma boa aplicação, tela , permitirá que todos os processos sejam executados até o fim natural, independentemente de como você encerra sua conexão. A tela está nos repositórios.

A descrição do homem da tela não é fácil de ler, mas, entre outras coisas, afirma:

Quando a tela é chamada, ela cria uma única janela com um shell (ou o comando especificado) e sai do seu caminho para que você possa usar o programa como faria normalmente. Em seguida, a qualquer momento, você pode criar novas janelas (em tela cheia) com outros programas (incluindo mais shells), eliminar janelas existentes, exibir uma lista de janelas, ativar e desativar o log de saída, copiar e colar texto entre janelas, visualize o histórico de rolagem, alterne entre janelas da maneira que desejar, etc. Todas as janelas executam seus programas completamente independentes entre si. Os programas continuam em execução quando a janela não está visível no momento e mesmo quando a sessão de tela inteira é desconectada do terminal do usuário. Quando um programa termina, a tela (por padrão) mata a janela que o continha. Se esta janela estava em primeiro plano, o visor muda para a janela anterior; se não sobrar, a tela sai.

Eu destaquei a parte mais importante: você pode desanexar a janela com o comando Ctrl + a + d e, em seguida, você pode matar / sair da sua sessão, e a janela agora desanexada continuará ativa, com os programas internos ainda em execução. Quando você se reconecta, por exemplo, iniciando uma nova sessão ssh, a tela de comando -r continuará a sessão de tela que havia sido desconectada anteriormente, com toda a saída para erro / saída padrão claramente visível.

MariusMatutiae
fonte