Nohup e disown
Quando efetuamos log out ou digitamos exit
em um terminal, um [sinal
hangup][sighup] é 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. [sighup]: https://en.wikipedia.org/wiki/SIGHUP
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