Primeiros Passos com Controle de Jobs - jobs, fg, bg e Ctrl+Z

Primeiros Passos com Controle de Jobs - jobs, fg, bg e Ctrl+Z

O Que Voce Vai Aprender

  • Usar Ctrl+Z para pausar um comando em execucao e recuperar seu terminal
  • Alternar livremente entre primeiro plano e segundo plano com fg / bg
  • Listar jobs atuais com jobs e direcionar jobs individuais com %n
  • Executar um comando em segundo plano desde o inicio adicionando &
  • Superar armadilhas comuns como "perdi meu trabalho" ou "isso nao vai embora"

Publico-alvo: Qualquer pessoa que estava editando um arquivo no vim ou executando um comando longo e queria "so verificar uma coisa" no mesmo terminal - e acidentalmente matou tudo com Ctrl+C.

Introducao: O Dia em que Lina Matou Sua Sessao do Vim

Lina: Senpai, escuta! Eu estava editando um arquivo de configuracao longo no vim, e precisei executar ls em outro terminal. Nao sabia como abrir um novo, entao simplesmente apertei Ctrl+C - e matou toda a sessao do vim. Perdi todas as alteracoes nao salvas.
Veterano Linny: Isso doi. Mas a combinacao de teclas que voce realmente queria existe. E Ctrl+Z (Control-Z).
Lina: Z, nao C?
Veterano Linny: Isso. Ctrl+C mata o comando em execucao, mas Ctrl+Z pausa e coloca de lado. Seu terminal volta para que voce possa executar outros comandos, e quando terminar, chame fg para retornar ao trabalho pausado.
Lina: Isso parece magica!
Veterano Linny: Chama-se "controle de jobs" - um recurso basico que todo shell POSIX (bash, zsh) oferece. Hoje voce so precisa de quatro coisas: Ctrl+Z (pausar), bg (retomar em segundo plano), fg (retornar ao primeiro plano), jobs (listar).

O Padrao Pratico

  • Quer seu terminal de volta? -> Ctrl+Z -> bg (continua executando em segundo plano)
  • Quer pausar e deixar parado? -> Ctrl+Z sozinho (fica pausado)
  • Quer voltar a ele? -> fg
  • Esqueceu o que esta executando? -> jobs

Ambiente Assumido

  • bash / zsh (controle de jobs e um recurso padrao do shell POSIX)
  • Nao funciona em dash ou shells nao interativos (/bin/sh -c)
  • Todos os exemplos de teclas assumem uma sessao de terminal interativa

1. "Job" vs. "Processo" - Qual a Diferenca?

Conclusao: Um processo e um programa no nivel do SO; um job e um comando do shell, referenciado por %n.

Lina: O que exatamente e um "job"? E diferente de um "processo"?
Veterano Linny: A mesma coisa, perspectivas diferentes. Um processo e o que o SO ve: cada programa em execucao. Um job e o que seu shell ve: um comando que voce digitou, como uma unica unidade.
Lina: Entao um job e do lado do shell, um processo e do lado do SO?
Veterano Linny: Exatamente. Se voce digitar ls | grep .txt | sort, o SO cria tres processos, mas o shell trata como um job. Quando voce aperta Ctrl+Z, o shell pausa o job inteiro - todos os tres processos - de uma vez.

Numero do Job vs. PID

Tipo Exemplo Atribuido por Usado para
Numero do job %1 O shell fg %1, kill %1, etc.
PID 12345 O kernel kill 12345, saida do ps

Dica de memorizacao: Numeros de job sempre levam um % na frente. E fg %1 (nao fg 1), kill %1 (nao kill 1). O ultimo - kill 1 - envia o sinal kill para o PID 1 (init), que e um comando perigoso se voce tiver permissao.

2. Ctrl+Z: Pause Agora Mesmo

Conclusao: Ctrl+Z pausa um job em execucao sem mata-lo, devolvendo seu terminal.

Veterano Linny: Esta e a tecla mais importante. Abra vim, tail -f, python interativo - qualquer coisa que trave seu terminal - e pressione Ctrl+Z.
Lina: Nao vai congelar? Posso realmente trazer de volta?
Veterano Linny: Pode. "Pausado" nao e "morto." Pense nisso como colocar o programa no congelador. fg descongela e retoma como se nada tivesse acontecido.

Experimente

$ sleep 100

sleep 100 nao faz nada por 100 segundos. Seu terminal fica travado o tempo todo.

Agora pressione Ctrl+Z.

^Z
[1]+  Stopped                 sleep 100
$

Se voce ver [1]+ Stopped, funcionou. Observe que o prompt $ voltou - o terminal e seu novamente.

Lendo [1]+

  • [1] = numero do job 1
  • + = o job mais recentemente tocado (o alvo padrao para fg / bg)
  • Stopped = pausado (sem consumir CPU)

Agora Voce Pode Executar Outros Comandos

$ ls
$ pwd
$ echo "livre para fazer outras coisas"

sleep fica congelado em segundo plano enquanto voce faz o que quiser. Essa e a magica do Ctrl+Z.

3. fg: Trazer de Volta / bg: Retomar Atras

Conclusao: fg traz um job parado para a frente; bg o retoma em segundo plano.

Lina: Como eu despauso um job parado?
Veterano Linny: Duas opcoes. fg = traz de volta para a frente e retoma. bg = retoma em segundo plano enquanto voce continua usando o terminal. O primeiro coloca sua atencao de volta no job; o segundo te deixa livre para outro trabalho.

fg: De Volta ao Primeiro Plano

Vamos trazer de volta o sleep 100 de antes.

$ fg
sleep 100

sleep continua de onde parou, e o terminal fica travado novamente. Espere terminar, aperte Ctrl+Z de novo ou Ctrl+C para matar.

bg: Retomar em Segundo Plano

Se voce quer que continue executando mas nao quer esperar:

$ sleep 100
^Z
[1]+  Stopped                 sleep 100
$ bg
[1]+ sleep 100 &
$

Muda de Stopped para & (executando em segundo plano). sleep continua contando enquanto voce faz outras coisas.

Nem todos os comandos funcionam com bg: Aplicativos interativos de tela cheia como vim nao conseguem "esperar entrada em segundo plano", entao usar bg neles apenas os envia de volta ao estado parado (Stopped (tty input)). Para vim, o ritmo certo e Ctrl+Z para pausar -> fg para retornar - nao tente usar bg.

4. Adicionar &: Segundo Plano Desde o Inicio

Conclusao: Adicione & para executar em segundo plano desde o inicio; redirecione a saida para um arquivo.

Veterano Linny: Se voce sabe de antemao "isso precisa executar em segundo plano", adicione & ao iniciar.
Lina: Entao em vez de Ctrl+Z -> bg em dois passos, faz em um?
Veterano Linny: Isso, mesmo resultado final. Ctrl+Z -> bg e "comecei e mudei de ideia", & e "mande para o fundo desde o inicio."

Usando &

$ sleep 100 &
[1] 12345
$

[1] e o numero do job, 12345 e o PID. O prompt retorna imediatamente.

$ jobs
[1]+  Running                 sleep 100 &

O status e Running, nao Stopped.

Exemplo Real: Coleta de Logs em Segundo Plano

$ tail -f /var/log/syslog > mylog.txt &
[1] 23456
$ # faca outras coisas enquanto executa
$ vim config.txt

Execute tail -f em segundo plano enquanto edita um arquivo com vim. Fluxo de trabalho paralelo classico.

Com & sozinho, a saida vaza no seu terminal: A saida stdout de um comando em segundo plano ainda imprime no seu terminal por padrao. Se for barulhento, redirecione com > file 2>&1 para enviar a saida para um arquivo (ou > /dev/null 2>&1 para descartar).

5. jobs: Veja o Que Esta Executando

Conclusao: jobs lista todos os jobs que o shell gerencia; direcione um com %n, sempre com %.

Lina: Com varios jobs executando, vou perder o controle do que esta onde.
Veterano Linny: Um comando resolve isso: jobs. Lista todos os jobs que seu shell atual esta gerenciando.

Uso Basico: jobs

$ sleep 100 &
[1] 12345
$ sleep 200 &
[2] 12346
$ vim notes.txt
# Ctrl+Z para pausar
$ jobs
[1]   Running                 sleep 100 &
[2]-  Running                 sleep 200 &
[3]+  Stopped                 vim notes.txt

Tres jobs visiveis.

  • + = mais recente (alvo padrao de fg / bg - vim aqui)
  • - = anterior (sleep 200)

Direcionar um Job Especifico: %n

$ fg %1     # trazer sleep 100 para a frente
$ bg %3     # enviar vim para segundo plano (fica pausado)
$ kill %2   # encerrar sleep 200

Nao esqueca o %

kill 1 e o comando que envia um sinal kill para o PID 1 (init). Um usuario comum e bloqueado por permissoes, mas root pode derrubar o sistema inteiro. Faca do % um habito muscular sempre que referenciar jobs.

Opcoes Uteis do jobs

Opcao Efeito
jobs -l Tambem mostra PIDs
jobs -p Apenas PIDs (util para scripting)
jobs -r Apenas jobs em execucao
jobs -s Apenas jobs parados

6. O Que Acontece Quando Voce Fecha o Terminal?

Conclusao: Por padrao, SIGHUP mata jobs ao sair; use nohup, disown ou tmux para sobreviver.

Lina: Se eu deixei jobs em segundo plano executando e fechei o terminal, o que acontece?
Veterano Linny: Eles geralmente morrem. Quando o shell sai, ele envia SIGHUP (hangup) para seus jobs filhos por padrao.
Lina: Entao um job longo que deixei em segundo plano pode simplesmente desaparecer quando fecho o terminal?
Veterano Linny: Sim. E para isso que servem nohup e disown. E para a solucao mais robusta, tmux.

nohup: Ignorar SIGHUP Desde o Inicio

$ nohup ./long_script.sh > output.log 2>&1 &
[1] 34567

Prefixe com nohup e o job ignora SIGHUP quando o shell sai. Faca logout e ele continua executando.

disown: Desanexar do Shell Apos Iniciar

$ ./long_script.sh &
[1] 45678
$ disown %1
$ exit   # fechar o terminal nao mata %1

Se voce iniciou um job com & e depois percebeu que quer que ele sobreviva ao logout, disown e sua ferramenta.

tmux e mais a prova de balas

nohup / disown apenas mantem o job vivo apos a desconexao - mas voce perde a saida da tela. Com tmux toda a sessao e salva no servidor, e voce pode depois usar tmux attach para voltar a saida ao vivo. Para jobs longos onde voce quer ver o que aconteceu, tmux vence. -> Primeiros Passos com tmux

7. Armadilhas Comuns

Conclusao: As armadilhas classicas: Ctrl+C vs Ctrl+Z, kill 1, saida perdida e bg no vim.

Lina: Senpai, quais erros os iniciantes normalmente cometem?
Veterano Linny: Quatro. Estes cobrem a maioria das minas do primeiro mes.

Armadilha 1: Confundir Ctrl+C e Ctrl+Z

Sintoma: Voce queria pausar mas o job morreu.

Causa: Confundir Ctrl+C (SIGINT - encerra) com Ctrl+Z (SIGTSTP - pausa).

Solucao: Lembre-se "C = Cancelar, Z = Zzz (dormir)." Ctrl+Z e nao destrutivo - seu trabalho no vim esta seguro.

Armadilha 2: Digitar kill 1 Em Vez de kill %1

Sintoma: kill 1 diz "Operation not permitted" (ou pior, como root, o sistema cambaleia).

Causa: Voce confundiu numero do job com PID e esqueceu o %. kill 1 envia um sinal de encerramento para o PID 1 (init / systemd).

Solucao: Sempre prefixe referencias de job com %. Na duvida, execute jobs -l primeiro para ver o PID - ou use kill %% para direcionar o job mais recente.

Armadilha 3: Saida em Segundo Plano Invadindo Seu Prompt

Sintoma: A saida de um comando em segundo plano se espalha no meio do que voce esta digitando.

Causa: Stdout e stderr ainda vao para o terminal em segundo plano.

Solucao: Redirecione com > file 2>&1 & (para um arquivo de log) ou > /dev/null 2>&1 & (para descartar).

Armadilha 4: vim Nao Funciona Apos bg

Sintoma: Voce fez Ctrl+Z depois bg no vim, mas jobs mostra Stopped (tty input) para sempre.

Causa: vim precisa ler do terminal. Em segundo plano ele nao consegue, entao o shell o pausa automaticamente.

Solucao: Para aplicativos interativos de tela cheia (vim, top, nano, etc.), use Ctrl+Z para pausar -> fg para retomar. Nunca use bg neles.

8. Templates: Controle de Jobs Sem Acidentes

Conclusao: vim alterna via Ctrl+Z e fg; jobs longos usam &; sobreviva ao logout com tmux.

Copiar e colar: Executar um comando enquanto edita no vim

# 1. Editando no vim
$ vim config.txt
# Ctrl+Z para pausar

# 2. Terminal de volta - faca outras coisas
$ ls /etc/
$ grep "error" /var/log/syslog

# 3. Retomar vim
$ fg

O objetivo e alternar sem fechar o vim. Construa o ritmo: Ctrl+Z -> tarefa lateral -> fg.

Copiar e colar: Executar um job longo em segundo plano

# Envie a saida para um arquivo para nao baguncar seu terminal
$ ./long_script.sh > output.log 2>&1 &
[1] 12345

# Verifique o progresso
$ jobs
$ tail -f output.log

# Encerre se necessario
$ kill %1

Esquecer > output.log 2>&1 e o erro mais comum. Mantenha-os juntos.

Copiar e colar: Sobreviver ao logout

# nohup desde o inicio
$ nohup ./long_script.sh > output.log 2>&1 &
[1] 12345

# Ou disown apos o fato
$ ./long_script.sh > output.log 2>&1 &
[1] 12345
$ disown %1

# A abordagem mais robusta - tmux preserva toda a tela (recomendado)
$ tmux
$ ./long_script.sh
# Ctrl+b -> d para desanexar, tmux attach depois para voltar

Mini Desafios

Conclusao: Pratique o ciclo Ctrl+Z/fg, tres jobs paralelos e saida para arquivo.

Veterano Linny: O conhecimento fixa quando seus dedos se movem. Tente estes tres.

Desafio 1: Ciclo Ctrl+Z <-> fg

$ sleep 30
# Cerca de 5 segundos depois, pressione Ctrl+Z

$ jobs
# -> Deve mostrar [1]+ Stopped sleep 30

$ ls    # tente outro comando

$ fg    # retorne ao sleep, termine o tempo restante

Desafio 2: Tres Jobs Paralelos

$ sleep 100 &
$ sleep 200 &
$ sleep 300 &

$ jobs    # -> todos os tres [1] [2] [3] devem aparecer

$ kill %2 # mate apenas o do meio

$ jobs    # -> [2] agora deve ter sumido

Desafio 3: Segundo Plano Com Saida Para Arquivo

$ (for i in 1 2 3 4 5; do echo "step $i"; sleep 1; done) > result.log 2>&1 &

$ jobs    # Running
$ cat result.log   # saida se acumula no arquivo

# Quando o job terminar, voce vera algo como:
# [1]+  Done    ( for i in 1 2 3 4 5; ...) > result.log 2>&1
Lina: Entendi! A seguranca do Ctrl+Z e enorme - nunca mais vou matar o vim com Ctrl+C.
Veterano Linny: Essa e a experiencia de "aprender controle de jobs." Cada dia no shell fica um pouco mais fluido a partir daqui.

Resumo em Tres Linhas

  • Ctrl+Z pausa e libera o terminal, fg traz de volta, bg mantem executando atras - nunca mais mate o vim acidentalmente com Ctrl+C
  • Sempre referencie jobs com % (kill %1 != kill 1) - confundir PID e numero do job pode derrubar o init
  • Para tarefas longas em segundo plano, torne & + > file 2>&1 um habito, e recorra a nohup / disown / tmux quando precisar sobreviver ao logout

Proximas Leituras