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