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 rodando

Uma 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 jobs regularmente para monitorar o estado dos seus processos.
  • Combine nohup com & para iniciar processos que devem sobreviver ao logout.
  • Lembre-se de que processos em background ainda consomem recursos; monitore com top ou ps.
  • Use Ctrl+Z para pausar temporariamente, em vez de matar o processo, quando quiser retomar depois.

Referências

Exercícios

  1. Exercício 1: Execute o comando sleep 60 em segundo plano. Verifique se ele está rodando usando jobs. Em seguida, traga-o para o primeiro plano e interrompa com Ctrl+C.
  2. ✓ Resposta:
    $ sleep 60 &
    [1] 12345
    $ jobs
    [1]+  Running                 sleep 60 &
    $ fg %1
    sleep 60
    ^C
    $
  3. Exercício 2: Inicie um comando longo (ex.: find / -name "*.log") em foreground, pause com Ctrl+Z, depois coloque-o em background e verifique com jobs.
  4. ✓ Resposta:
    $ find / -name "*.log"
    ^Z
    [1]+  Stopped                 find / -name "*.log"
    $ bg %1
    [1]+ find / -name "*.log" &
    $ jobs
    [1]+  Running                 find / -name "*.log" &
  5. Exercício 3: Use nohup para executar ping -c 10 google.com em segundo plano, redirecionando a saída para um arquivo. Verifique se o processo continua após fechar o terminal (simule com exit e reabra).
  6. ✓ Resposta:
    $ 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
  7. Exercício 4: Inicie um job em background, use disown para removê-lo da lista, e verifique que ele não aparece em jobs.
  8. ✓ Resposta:
    $ sleep 500 &
    [1] 12345
    $ disown %1
    $ jobs
    # nenhum job listado
    $ ps -p 12345
    # o processo ainda está rodando
  9. Exercício 5: Explique a diferença entre nohup e disown em termos de quando usar cada um.
  10. ✓ Resposta: nohup é 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.