Nohup e disown

Quando efetuamos log out ou digitamos exit em um terminal, um sinal hangup é enviado para o shell, finalizando todos os seus child processes.

O termo utilizado é hungup, pois os computeiros do século passado usavam modems para conectar seus terminais a mainframes. Quando eles colocavam o “telefone no gancho” (tradução de hung up) um SIGHUP era enviado e a conexão era finalizada.

Porém muitas vezes queremos iniciar um programa e deixá-lo rodando mesmo após fazermos logout ou fecharmos a janela do emulador de terminal.
Algo parecido pode feito com o GNU Screen ou Tmux, mas abrir esses programas só para isso parece um exagero, além de que alguns computadores não possuem o Screen instalado e essa não é uma opção válida para usar em scripts.

Nohup

Para estes casos existe o nohup ("no hangup"), que torna o processo imune ao SIGHUP.

No meu bash basta preceder o comando com nohup e jogar para o background (&) que já podemos fechar o terminal sem problemas:

julio@julio-acer ~ $ nohup dropboxd &

Mas o mesmo não funciona no ZSH:

julio@julio-acer ~> nohup dropboxd &
  [1] 13434
  nohup: ignoring input and appending output to ‘nohup.out’
julio@julio-acer ~> exit
  zsh: you have running jobs.

Tentar dar exit novamente fará o programa ser terminado abruptamente.

Isso acontece porque ainda existem conexões com o stdin, stdout e stderr. Se as redirecionarmos para /dev/null (ou outro arquivo) poderemos sair do shell (exit ou logout) sem problemas:

julio@julio-acer ~> nohup dropboxd &> /dev/null < /dev/null &!
julio@julio-acer ~> exit

Disown

Mas e se você iniciou um programa sem o nohup e quer fazer logout sem ter que finalizá-lo?

No Bash e ZSH exite o comando disown, que desassocia um job do shell atual (remove ele da job list). Isto permite fechar o shell sem que o job seja interrompido.

julio@julio-acer ~> dropboxd
^Z
[1]  + 23042 suspended  dropboxd
julio@julio-acer ~> bg %1
[1]  + 23042 continued  dropboxd
julio@julio-acer ~> jobs
[1]  + running    dropboxd
julio@julio-acer ~> disown %dropboxd
julio@julio-acer ~> jobs
julio@julio-acer ~> ps 23042
  PID   TTY      STAT   TIME  COMMAND
  23042 pts/7    SNl    0:02  /opt/dropbox/dropbox

julio@julio-acer ~> exit

De man bash, temos:

disown [-ar] [-h] [jobspec …]
Without options, each jobspec is removed from the table of active jobs. If jobspec is not present, and neither -a nor -r is supplied, the shell’s notion of the current job is used. If the -h option is given, each jobspec is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. If no jobspec is present, and neither the -a nor the -r option is supplied, the current job is used. If no jobspec is supplied, the -a option means to remove or mark all jobs; the -r option without a jobspec argument restricts operation to running jobs. The return value is 0 unless a jobspec does not specify a valid job.

Uma opção interessante é o -h, que faz com que o disown se comporte exatamente como o nohup. Porém esta opção é exclusiva para o disown do Bash e não funciona no ZSH.

Também podemos chamar o disown junto com o programa. A funcionalidade é praticamente a mesma do nohup e, como eu não preciso me preocupar em redirecionar os streams (stdin, stdout, stderr), quase sempre uso o disown em vez do nohup:

julio@julio-acer ~> dropboxd& disown && exit
Julio Batista Silva
Julio Batista Silva
Engenheiro de Dados

Eu sou um engenheiro de computação apaixonado por ciência, tecnologia, fotografia e idiomas. Atualmente trabalhando como Engenheiro de Dados na Alemanha.

comments powered by Disqus