Estou usando `&`: por que o processo não está sendo executado em segundo plano?

24

Eu sei que posso acrescentar &a um comando para executar o processo em segundo plano.

Estou fazendo o SSH em uma caixa do Ubuntu 12.04 e executando um programa python $python program.py &- mas quando vou fechar a janela do terminal, recebo uma mensagem dizendo que fechar o terminal matará o processo em execução.

Por que é isso? Estou usando o e comercial para executar o processo em segundo plano. Como posso executá-lo, independentemente de estar com SSH?

bernie2436
fonte
Duplicado de unix.stackexchange.com/q/4004/69080
Joshua Huber
apt-get install tela, tela homem
captcha

Respostas:

51

Quando você fecha uma janela do terminal, o emulador de terminal envia um SIGHUP para o processo em execução, seu shell. Seu shell então encaminha o SIGHUP para tudo o que está sendo executado. No seu sistema local, este é o ssh. O ssh então encaminha o SIGHUP para o que está executando, o shell remoto. Portanto, seu shell remoto envia um SIGHUP para todos os seus processos, seu programa em segundo plano.

Existem duas maneiras de contornar isso.

  1. Desassocie o programa em segundo plano do seu shell.
    1. Use o disowncomando após o processo em segundo plano. Isso fará com que o shell o esqueça.
    2. Prefixe seu comando com nohup( nohup $python program.py &). Isso realiza a mesma coisa, mas usando um processo intermediário. Basicamente, ele ignora o sinal SIGHUP e, em seguida, bifurca e executa o programa que herda a configuração e sai. Por ter sido bifurcado, o programa que está sendo lançado não é filho do shell, e o shell não sabe sobre isso. E, a menos que instale um manipulador de sinal para SIGHUP, ele mantém a ação de ignorar de qualquer maneira.
  2. Use em logoutvez de fechar a janela do terminal. Quando você usa logout, este não é um SIGHUP e, portanto, o shell não envia um SIGHUP para nenhum de seus filhos.

Além disso, você deve garantir que seu programa não grave no terminal através de STDOUT ou STDERR, pois esses dois não existirão mais assim que o terminal sair. Se você não redirecioná-los para algo como /dev/null, o programa ainda será executado, mas se tentar gravá-los, obterá um SIGPIPE, e a ação padrão do SIGPIPE é interromper o processo).

Patrick
fonte
4
Tecnicamente, sshmorrer faz com que a conexão caia, a conexão cai causa sshdna outra extremidade a morrer. Esse sshd que controla o lado mestre do pseudo-terminal que o shell remoto executa, quando morre, é um desligamento (é como puxar o plugue de um terminal real), para que o sistema envie um SIGHUP para o shell remoto.
Stéphane Chazelas
@ StéphaneChazelas Essa é uma coisa que eu nunca cavei. Se é o kernel fazendo isso, como ele determina qual processo usar para o SIGHUP? Obviamente, não SIGHUP tudo com um descritor de arquivo aberto para esse TTY, pois os programas permanecerão em execução enquanto eles não tentarem usá-lo. Então, ele escolhe o programa que está lendo no STDIN (já que apenas um pode ler no STDIN por vez)?
6604 Patrick
4
Não importa, respondeu minha própria pergunta. POSIX IEEE 1003.1, capítulo 11, Se uma desconexão do modem for detectada pela interface do terminal para um terminal de controle ... o sinal SIGHUP deve ser enviado ao processo de controle .
Patrick
2
Observe também que nohupgera um nohup.outarquivo com a saída do programa que você inicia com ele. Pode ser irritante excluir esse arquivo toda vez que você usa o nohup para iniciar um aplicativo dessa maneira (ou você precisa redirecionar sua saída para /dev/null).
Ruslan
1
Em vez de nohup python program.py &eu recomendo usar o setsid python program.pyque imediatamente rejeita o programa.
Hitechcomputergeek 26/08/16
14

O processo está sendo executado em segundo plano no terminal, mas a saída de stdout(e stderr) ainda está sendo enviada para o terminal. Para interromper isso, adicione > /dev/null 2>&1antes &de redirecionar as duas saídas para /dev/null- adicionando disowntambém garante que o processo não seja interrompido depois que você fechar o terminal:

COMMAND > /dev/null 2>&1 & disown

No seu caso, isso seria:

python program.py > /dev/null 2>&1 & disown
Wilf
fonte
3

O &operador separa comandos para executar em paralelo, assim como ;separa comandos para executar em série. Os dois tipos de comandos ainda serão executados como um filho do processo do shell .

Então, quando você fechar a concha que iniciou esses filhos, eles também serão fechados.

O que você parece querer é um processo de daemon , que é significativamente mais complicado porque precisa se dissociar totalmente do processo pai. O shell geralmente não tem uma maneira simples de fazer isso.

nariz grande
fonte
1

Quando você efetua logout, os processos em segundo plano associados à sessão de logon normalmente também são eliminados. Se você deseja que eles sejam desconectados da sessão, execute-os com nohup.

nohup python program.py &
Barmar
fonte
1

Após o comando terminar com "e comercial" ( &), no prompt de comando, execute o comando bg:

bash> python program.py &  
bash> bg  

Isso colocará o comando "&" em segundo plano

bash> jobs  

Isso listará os trabalhos em execução em segundo plano

bash> fg 1   

Isso trará o trabalho nº 1 para o primeiro plano

Outra maneira (para conseguir sair)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

Várias linhas pode ser submetido ao atcomando, antes de o ^ d (Controlo-D)
ver man at.

Martin
fonte