Controle de jobs
Nesta aula, você aprenderá a gerenciar processos em execução no shell Bash, incluindo como executar comandos em segundo plano, alternar entre processos, pausar e retomar tarefas, e como garantir que processos continuem rodando mesmo após o logout. O controle de jobs é essencial para administradores de sistemas e desenvolvedores que precisam gerenciar múltiplas tarefas simultaneamente em um terminal.
No ambiente Linux, o shell Bash oferece recursos poderosos para gerenciar processos em execução. O controle de jobs permite que você execute comandos em segundo plano, pause tarefas, retome-as e até mesmo as mantenha rodando após fechar o terminal. Nesta aula, vamos explorar os conceitos de foreground e background, os comandos jobs, fg, bg, o atalho Ctrl+Z, e ferramentas como nohup e disown. Esses conhecimentos são fundamentais para otimizar seu fluxo de trabalho no terminal e gerenciar processos de forma eficiente.
Vamos começar entendendo a diferença entre processos em primeiro plano (foreground) e em segundo plano (background), e depois mergulhar nas ferramentas que o Bash oferece para controlá-los.
Foreground e background (&)
Quando você executa um comando no terminal, ele normalmente roda em foreground (primeiro plano), ocupando o terminal até que termine. Durante esse tempo, você não pode digitar outros comandos. Por exemplo, ao executar um script longo ou um comando que demora, o terminal fica bloqueado.
Para executar um comando em background (segundo plano), basta adicionar um & ao final do comando. O shell então inicia o processo e retorna imediatamente o prompt, permitindo que você continue trabalhando. O processo em background continua rodando independentemente, mas ainda está associado ao terminal (job).
Exemplo: executar um comando sleep em background.
sleep 30 &Ao executar, o shell imprime algo como [1] 12345, onde [1] é o job ID e 12345 é o PID (Process ID). O comando roda em background e você pode digitar outros comandos imediatamente.
É importante notar que, mesmo em background, o processo pode enviar saída para o terminal, o que pode poluir sua tela. Você pode redirecionar a saída para um arquivo para evitar isso:
script_ longo.sh > saida.log 2>&1 &jobs, fg, bg
O comando jobs lista todos os jobs (processos) associados ao terminal atual, mostrando o job ID, o estado (em execução, parado, etc.) e o comando executado. É a ferramenta principal para visualizar o que está rodando em background.
$ sleep 100 &
[1] 12345
$ sleep 200 &
[2] 12346
$ jobs
[1]- Running sleep 100 &
[2]+ Running sleep 200 &O símbolo + indica o job atual (o mais recente em background), e - indica o job anterior.
Os comandos fg e bg permitem alternar um job entre foreground e background. Para trazer um job para o foreground, use fg %N (onde N é o job ID) ou fg %comando (parte do comando). Sem argumento, fg traz o job atual. Para colocar um job em background, use bg %N. Isso é útil para retomar um job que foi pausado com Ctrl+Z (veremos a seguir).
$ sleep 100 &
[1] 12345
$ fg %1
sleep 100
# (o terminal fica bloqueado até o sleep terminar)
^Z
[1]+ Stopped sleep 100
$ bg %1
[1]+ sleep 100 &
$ jobs
[1]+ Running sleep 100 &Ctrl+Z
O atalho Ctrl+Z envia o sinal SIGTSTP ao processo em foreground, pausando-o (stopped). O job é colocado em background e fica parado, mas ainda existe. Isso é útil quando você está executando um comando longo e precisa interromper temporariamente para fazer outra coisa, sem matar o processo.
Após pausar, você pode usar bg para continuar a execução em background ou fg para retomá-lo em foreground. O comando jobs mostrará o estado Stopped.
$ find / -name "*.conf"
^Z
[1]+ Stopped find / -name "*.conf"
$ jobs
[1]+ Stopped find / -name "*.conf"
$ bg %1
[1]+ find / -name "*.conf" &
$ jobs
[1]+ Running find / -name "*.conf" &Note que Ctrl+Z só funciona em processos que estão em foreground. Se você tiver um processo em background, ele não será afetado, pois não está associado ao terminal de forma interativa.
nohup e disown
Por padrão, quando você fecha o terminal, o shell envia o sinal SIGHUP para todos os jobs associados, causando sua terminação. Para evitar isso, você pode usar o comando nohup ou o comando disown.
nohup (no hang up) executa um comando ignorando o sinal SIGHUP, permitindo que ele continue rodando mesmo após o logout. A saída é redirecionada para o arquivo nohup.out se não for redirecionada explicitamente.
nohup script_ longo.sh &
# ou
nohup script_ longo.sh > saida.log 2>&1 &O comando disown remove um job da lista de jobs do shell, fazendo com que ele não receba SIGHUP quando o terminal fechar. Você pode usar disown %N (job ID) ou disown -a para todos os jobs. Após o disown, o processo fica órfão, mas continua rodando.
$ sleep 1000 &
[1] 12345
$ disown %1
$ jobs
# nenhum job listado, mas o processo continua rodandoUma diferença importante: nohup deve ser usado no momento da execução, enquanto disown pode ser aplicado a um job já em execução. Além disso, nohup redireciona a saída automaticamente, enquanto disown não altera a saída.
Boas práticas
- Sempre redirecione a saída de processos em background para arquivos ou
/dev/null, para evitar poluição do terminal. - Use
jobsregularmente para monitorar o estado dos seus processos. - Combine
nohupcom¶ iniciar processos que devem sobreviver ao logout. - Lembre-se de que processos em background ainda consomem recursos; monitore com
topoups. - Use
Ctrl+Zpara pausar temporariamente, em vez de matar o processo, quando quiser retomar depois.
Referências
- Bash Reference Manual: Job Control
- jobs - POSIX man page
- nohup(1) - Linux man page
- disown - POSIX man page
- Bash Reference Manual: Signals
- Advanced Bash-Scripting Guide: Job Control
Exercícios
- Exercício 1: Execute o comando
sleep 60em segundo plano. Verifique se ele está rodando usandojobs. Em seguida, traga-o para o primeiro plano e interrompa com Ctrl+C. - Exercício 2: Inicie um comando longo (ex.:
find / -name "*.log") em foreground, pause com Ctrl+Z, depois coloque-o em background e verifique comjobs. - Exercício 3: Use
nohuppara executarping -c 10 google.comem segundo plano, redirecionando a saída para um arquivo. Verifique se o processo continua após fechar o terminal (simule comexite reabra). - Exercício 4: Inicie um job em background, use
disownpara removê-lo da lista, e verifique que ele não aparece emjobs. - Exercício 5: Explique a diferença entre
nohupedisownem termos de quando usar cada um.
$ sleep 60 &
[1] 12345
$ jobs
[1]+ Running sleep 60 &
$ fg %1
sleep 60
^C
$$ find / -name "*.log"
^Z
[1]+ Stopped find / -name "*.log"
$ bg %1
[1]+ find / -name "*.log" &
$ jobs
[1]+ Running find / -name "*.log" &$ nohup ping -c 10 google.com > ping.log 2>&1 &
[1] 12345
$ exit
# reabra o terminal e verifique o arquivo ping.log ou o processo com ps
$ cat ping.log$ sleep 500 &
[1] 12345
$ disown %1
$ jobs
# nenhum job listado
$ ps -p 12345
# o processo ainda está rodandonohup é usado no início da execução para ignorar o sinal SIGHUP, garantindo que o processo sobreviva ao logout. disown é usado em um job já em execução para removê-lo da lista de jobs do shell, impedindo que o shell envie SIGHUP ao fechar. Use nohup quando você sabe que o processo deve continuar após sair; use disown quando você já iniciou o processo e decide que ele deve continuar.