Evitar que a desconexão do terminal mate um job em execução em zsh [duplicate]

2

Eu passei pela principal resposta a essa pergunta: Diferença entre nohup, disown e & e eu leia specfically o seguinte:

With disown the job is still connected to the terminal, so if the terminal is destroyed (which can happen if it was a pty, like those created by xterm or SSH, and the controlling program is terminated, by closing the xterm or terminating the SSH connection), the program will fail as soon as it tries to read from standard input or write to the standard output.

Parece que disown não pode impedir que um trabalho seja eliminado se o terminal for fechado. nohup pode, mas só pode ser usado quando o trabalho é iniciado.

Assumindo que entendi isso corretamente, o que posso fazer para garantir que um trabalho iniciado sem nohup não seja eliminado quando eu fechar meu terminal, encerre minha conexão SSH ?

Emitiria setopt NO_HUP da linha de comando? E se assim for, isso não afeta todos os trabalhos em execução que iniciei no mesmo terminal?

    
por Amelio Vazquez-Reina 10.08.2015 / 17:07

3 respostas

3

Para um shell padrão (bash) (POSIX.1)

Comece com & , faça-o ler algo diferente do padrão stdin (== /dev/tty == /dev/stdin == /dev/fd/0 ) + faça com que ele grave algo diferente do% padrãostdout (== /dev/tty == /dev/stdin == /dev/fd/1 ) (o mesmo para stderr ) e certifique-se de que o trabalho não seja ou não seja suspenso (= parado ). Se for interrompido ou precisar ler o terminal e continuar após o terminal do trabalho desligar, certifique-se de que os processos no trabalho tenham um manipulador (trap) para o sinal SIGHUP . Se ele precisar gravar no terminal e sobreviver a um terminal, certifique-se de que os processos que gravam no terminal tenham um manipulador para SIGPIPE .

Explicação:

Os processos em segundo plano são enviados SIGTTIN no momento em que eles tentam ler a partir do terminal. A disposição padrão para SIGTTIN é parar (= suspender) o processo. Um desligamento de terminal fará com que a primeira geração de processos de seus trabalhos em segundo plano sejam reparados no init, fazendo com que o grupo de processos da primeira geração de processos do seu trabalho se torne um grupo de processos órfãos. (Grupos de processos órfãos são aqueles em que nenhum dos membros tem um pai em um grupo de processos diferente, mas na mesma sessão.) O sistema enviará todos os grupos de processos órfãos (suspensos) parados SIGHUP seguidos por SIGCONT (para garantir que eles obtenham o SIGHUP ) em um desligamento terminal porque, por definição, nenhum dos processos nesse grupo de processos pode ser despertado por um pai da mesma sessão. Consequentemente, esses processos devem ser despertados pelo sistema, mas, ao mesmo tempo, de uma forma que sinalize que o processo foi despertado devido ao desligamento do terminal, e não devido à operação normal. SIGHUP é o mecanismo que faz isso e a disposição padrão para SIGHUP é abortar.

Desligar um terminal também fará com que gravações subsequentes nesse terminal aumentem SIGPIPE , que também é mortal se não for manipulado.

TL; DR Se seus grupos de processos órfãos não estiverem suspensos (via SIGTTIN ou ^ Z ou de outra forma, eles não precisarão ficar com medo do SIGHUP sinal e se enviarem para um arquivo em vez do terminal em stdout e stderr e lido de um arquivo em vez do terminal, então eles não precisam ter medo de SIGPIPE . Se você estiver executando em cima de um multiplexador de terminal em vez de um terminal bruto, você não precisa ter medo de SIGHUP ou SIGPIPE .

para zsh

Eu joguei com zsh e acontece que enquanto bash se comporta como eu descrevi acima (o comportamento descrito acima deve estar em conformidade com POSIX.1), zsh envia SIGHUP para executar trabalhos em segundo plano. setopt NO_HUP faz isso (ou o sistema; não tem certeza aqui) só envia SIGHUP nas situações descritas acima.

Para testar isso, você pode tentar executar algo como:

( rm -f hup; trap 'echo HUP > hup' HUP; sleep 100)

de várias formas ( fundo, primeiro plano, parado ) e desconectando-se com ele. Em seguida, você pode verificar se o arquivo hup foi criado, o que significaria que o trabalho obteve um SIGHUP .

    
por 10.08.2015 / 18:19
1

Você pode achar útil (embora não use disown , nohup ou & ) tentando screen ou tmux . Ambas as ferramentas permitem que você execute vários terminais e desconecte-os sem parar o que está acontecendo em cada um deles. Eu acho tmux mais conveniente.

Usando tmux

Você pode nomear sessões,

tmux new-session -s ${SESSION_NAME}

inicie um sem anexá-lo,

tmux new-session -d -s ${SESSION_NAME} '/home/user/script.sh'

listar sessões,

tmux list-sessions

e até mesmo enviar comandos para eles:

tmux send-keys -t ${SESSION_NAME} "echo Hello world"
tmux send-keys -t ${SESSION_NAME} Enter

É claro que você pode anexar a ("abrir") uma sessão em andamento para ver o que está acontecendo lá:

tmux attach-session -t ${SESSION_NAME}

E, em seguida, deixe-o sem fechar, pressionando Ctrl + B , em seguida, D .

    
por 10.08.2015 / 18:14
0

Você pode iniciar seu programa como um trabalho lote , por exemplo usando um documento aqui :

batch << EOJ
  ./yourprogram some $ARGUMENTS
EOJ

Se o programa já foi iniciado de forma interativa, não vejo nenhuma solução geral à prova de falhas; por exemplo. porque esse programa pode mais tarde começar a usar o sistema (3) (por exemplo, system("$EDITOR /tmp/somefile.txt"); ....) alguma aplicação cliente X11, ou alguma aplicação interativa usando o tty (4)

Se você puder melhorar esse programa, você pode considerar ter alguns argumentos do programa ativando uma chamada para o daemon (3)

Você também pode usar algum gerenciador de terminal como a tela (1) etc. .

    
por 10.08.2015 / 17:55