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 você vai conseguir fazer

  • Pausar um comando em execução com `Ctrl+Z` e recuperar o terminal
  • Mover o trabalho entre primeiro plano e segundo plano com `fg` e `bg`
  • Distinguir vários jobs com `jobs` e escolher um com `%n`

Pré-requisitos (leia estes primeiro)

O Que Você Vai Aprender

  • Usar Ctrl+Z para pausar um comando em execução e recuperar seu terminalUm programa interativo que interpreta os comandos digitados e os executa.
  • 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 início adicionando &
  • Superar armadilhas comuns como "perdi meu trabalho" ou "isso não vai embora"

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

Introdução: O Dia em que Lina Matou Sua Sessão do Vim

Lina: Senpai, escuta! Eu estava editando um arquivo de configuração longo no vim, e precisei executar ls em outro terminal. Não sabia como abrir um novo, então simplesmente apertei Ctrl+C - e matou toda a sessão do vim. Perdi todas as alterações não salvas.
Veterano Linny: Isso dói. Mas a combinação de teclas que você realmente queria existe. É Ctrl+Z (Control-Z).
Lina: Z, não C?
Veterano Linny: Isso. Ctrl+C mata o comando em execução. Ctrl+Z apenas pausa e coloca de lado.
Veterano Linny: Pausar devolve o terminal para você, então dá para executar outros comandos. Quando terminar, fg te leva de volta ao trabalho pausado.
Lina: Isso parece mágica! Então eu poderia ter mantido o vim vivo.
Veterano Linny: Chama-se "controle de jobs" - um recurso básico que todo shell POSIX (bash, zsh) oferece. Hoje você só precisa de quatro coisas: Ctrl+Z (pausar), bg (retomar em segundo plano), fg (retornar ao primeiro plano), jobs (listar).

O Padrão Prático

  • 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 está executando? -> jobs

Aprenda primeiro a rota de fuga: quando a tela parece travada

No controle de jobs há momentos em que a tela parece parada. Siga esta tabela e você sempre consegue sair.

O que você vê Como sair
Comando rodando e nenhum promptUm símbolo (como $ ou #) exibido quando o shell está esperando sua entrada. aparece Pressione Ctrl+Z para pausar - o prompt volta
Acabou de apertar Ctrl+Z e não sabe o que fazer fg traz de volta para a frente, bg manda para trás. Ambos são reversíveis
Não sabe o que está pausado Execute jobs para listar tudo e escolha um com fg %1
Quer mesmo encerrar Confira o número com jobs e execute kill %1 (nunca esqueça o %)

Ctrl+Z não mata nada. Apertar essa tecla nunca descarta seu trabalho, então experimente sem medo.

O que é um terminal

O terminal é a janela onde você digita texto e recebe texto de volta. "Terminal" e "console" são dois nomes para quase a mesma coisa.

Neste artigo, "o terminal volta" significa "o prompt $ reaparece e você pode digitar o próximo comando". Esse símbolo $ se chama prompt.

Ambiente Assumido

  • bash / zsh (controle de jobs é um recurso padrão do shell POSIX; o dash também tem jobs / fg / bg)
  • Desligado por padrão em shells não interativos (sh -c '...' e dentro de scripts)
  • Todos os exemplos de teclas assumem uma sessão de terminal interativa

1. "Job" vs. "Processo" - Qual a Diferença?

Conclusão: Um processo é um programa no nível do SO; um job é um comando do shell, referenciado por %n.

Lina: O que exatamente é um "job"? É diferente de um "processo"?
Veterano Linny: A mesma coisa, perspectivas diferentes. Um processo é o que o SO vê: cada programa em execução. Um job é o que seu shell vê: um comando que você digitou, como uma única unidade.
Lina: Então um job é do lado do shell, um processo é do lado do SO?
Veterano Linny: Exatamente. Se você digitar ls | grep .txt | sort, o SO cria três processos, mas o shell trata como um job. Quando você aperta Ctrl+Z, o shell pausa o job inteiro - todos os três processos - de uma vez.

Primeiro plano e segundo plano

  • Primeiro plano (foreground): o lado que recebe suas teclas. Enquanto ele roda, o terminal não volta
  • Segundo plano (background): o lado que roda fora de vista. O terminal fica livre para você

Pense na fila de um caixa. O job em primeiro plano é a pessoa que está no balcão. Um job em segundo plano é a pessoa com uma senha, esperando em outro lugar.

Número do Job vs. PID

Tipo Exemplo Atribuído por Usado para
Número do job %1 O shell fg %1, kill %1, etc.
PID 12345 O kernelO programa central de um sistema operacional. Faz a ponte entre hardware e software. kill 12345, saída do ps

Dica de memorização: Números de job sempre levam um % na frente. É fg %1 (não fg 1), kill %1 (não kill 1).

kill 1 não significa "job 1" - ele mira o processo de PID 1, que é o systemd, o pai de todo o sistema. Um usuário comum recebe "Operation not permitted". De qualquer forma, o job que você queria parar continua rodando.

2. Ctrl+Z: Pause Agora Mesmo

Conclusão: Ctrl+Z pausa um job em execução sem matá-lo, devolvendo seu terminal.

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

Experimente

$ sleep 100

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

Agora pressione Ctrl+Z.

^Z
[1]+  Stopped                 sleep 100
$

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

Lendo [1]+

  • [1] = número do job 1
  • + = o job mais recentemente tocado (o alvo padrão para fg / bg)
  • Stopped = pausado (sem consumir CPU)

Agora Você Pode Executar Outros Comandos

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

sleep fica congelado em segundo plano enquanto você faz o que quiser. Essa é a mágica do Ctrl+Z.

3. fg: Trazer de Volta / bg: Retomar Atrás

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

Lina: Como eu despauso um job parado?
Veterano Linny: Duas opções. fg (de foreground) traz de volta para a frente e retoma. bg (de background) retoma fora de vista.
Lina: Como escolho entre os dois?
Veterano Linny: Use fg quando quiser encarar o job de novo. Use bg quando quiser continuar em outra tarefa.

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 você quer que continue executando mas não 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 você faz outras coisas.

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

4. Adicionar &: Segundo Plano Desde o Início

Conclusão: Adicione & para executar em segundo plano desde o início; redirecione a saída para um arquivo.

Veterano Linny: Se você sabe de antemão "isso precisa executar em segundo plano", adicione & ao iniciar.
Lina: Então em vez de Ctrl+Z -> bg em dois passos, faz em um?
Veterano Linny: Isso, mesmo resultado final. Ctrl+Z -> bg é "comecei e mudei de ideia", & é "mande para o fundo desde o início."

Usando &

$ sleep 100 &
[1] 12345
$

[1] é o número do job, 12345 é o PID. O prompt retorna imediatamente.

$ jobs
[1]+  Running                 sleep 100 &

O status é Running, não 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 clássico.

Com & sozinho, a saída vaza no seu terminal: A saída padrão (os resultados normais de um comando) ainda imprime no seu terminal por padrão, e a saída de erro (as mensagens de erro) também. Se for barulhento, redirecione com > file 2>&1 para enviar a saída para um arquivo (ou > /dev/null 2>&1 para descartar).

5. jobs: Veja o Que Está Executando

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

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

Uso Básico: 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

Três jobs visíveis.

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

Direcionar um Job Específico: %n

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

Confira antes de usar o kill

Diferente de fechar uma janela em uma interface gráfica, o kill nunca pergunta se você quer salvar. O que estiver sem salvar em um editor simplesmente se perde.

  • Execute jobs antes e confirme que escolheu o job certo
  • Para um editor ou qualquer job com trabalho em andamento, use fg para voltar a ele e salve direito, em vez de matar
  • Pratique com sleep. Ele não guarda nada que você possa perder, então dá para testar à vontade

Não esqueça o %

kill 1 mira o PID 1 (systemd), não o job 1. Um usuário comum é bloqueado por permissões. Mesmo como rootA conta de administrador especial que pode fazer qualquer coisa no sistema., isso apenas faz o systemd reler sua configuração - o job que você mirou continua intacto. Faça do % um hábito muscular sempre que referenciar jobs.

Opções Úteis do jobs

Opção Efeito
jobs -l Também mostra PIDs
jobs -p Apenas PIDs (útil para scripting)
jobs -r Apenas jobs em execução
jobs -s Apenas jobs parados

6. O Que Acontece Quando Você Fecha o Terminal?

Conclusão: Por padrão, 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 você fecha a janela do terminal ou a conexão SSH cai, o shell recebe SIGHUP (hangup) e repassa isso aos jobs filhos.
Lina: O que é um sinal?
Veterano Linny: Um sinal é uma mensagem curta enviada a um processo. Ele leva algo como "por favor termine" ou "pare agora", identificado por um nome e um número.
Lina: Então um job longo que deixei em segundo plano pode simplesmente desaparecer quando fecho o terminal?
Veterano Linny: Sim. É para isso que servem nohup e disown. E para a solução mais robusta, tmux.

nohup: Ignorar SIGHUP Desde o Início

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

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

disown: Desanexar do Shell Após Iniciar

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

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

tmux é mais à prova de balas

nohup / disown apenas mantêm o job vivo após a desconexão - mas você perde a saída da tela. Com tmux toda a sessão é salva no servidor, e você pode depois usar tmux attach para voltar a saída ao vivo. Para jobs longos onde você quer ver o que aconteceu, tmux vence. -> Primeiros Passos com tmux

7. Armadilhas Comuns

Conclusão: As armadilhas clássicas: Ctrl+C vs Ctrl+Z, kill 1, saída perdida e bg no vim.

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

Armadilha 1: Confundir Ctrl+C e Ctrl+Z

Sintoma: Você queria pausar mas o job morreu.

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

Solução: Lembre-se "C = Cancelar, Z = Zzz (dormir)." Ctrl+Z é não destrutivo - seu trabalho no vim está seguro.

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

Sintoma: kill 1 diz "Operation not permitted", e o job que você queria parar continua rodando.

Causa: Você confundiu número do job com PID e esqueceu o %. kill 1 envia um sinal de encerramento para o PID 1 (init / systemd).

Solução: Sempre prefixe referências de job com %. Na dúvida, execute jobs -l primeiro para ver o PID - ou use kill %% para direcionar o job mais recente.

Armadilha 3: Saída em Segundo Plano Invadindo Seu Prompt

Sintoma: A saída de um comando em segundo plano se espalha no meio do que você está digitando.

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

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

Armadilha 4: vim Não Funciona Após bg

Sintoma: Você 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 não consegue, então o shell o pausa automaticamente.

Solução: 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

Conclusão: 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 é 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 é 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

Conclusão: Pratique o ciclo Ctrl+Z/fg, três jobs paralelos e saída para arquivo.

Veterano Linny: O conhecimento fixa quando seus dedos se movem. Tente estes três.

Onde testar estes desafios: o controle de jobs é um recurso do shell, então ele não roda no terminal virtual deste site. Use um terminal do seu próprio Linux, do WSL ou do macOS. Os desafios usam sleep, então nada quebra se você errar.

Desafio 1: Ciclo Ctrl+Z <-> fg

Tarefa: Execute sleep 30. Pause no meio, rode outro comando e depois traga de volta.

Ver dica 1 (direção)

Use a tecla que pausa, não a que encerra. Depois de pausar, confira o estado em uma lista antes de voltar.

Ver dica 2 (nome do comando)

Pause com Ctrl+Z. Confira com jobs. Volte com fg.

Ver resposta
$ 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: Três Jobs Paralelos

Tarefa: Inicie três comandos já em segundo plano. Depois encerre apenas o do meio.

Ver dica 1 (direção)

Existe um jeito de mandar um comando para segundo plano já na hora de iniciar. Antes de encerrar um deles, confirme o número na lista de jobs.

Ver dica 2 (nome do comando)

Mande para segundo plano com & no final. Liste com jobs. Encerre com kill %2 - o % é obrigatório.

Ver resposta
$ 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 Saída Para Arquivo

Tarefa: Execute em segundo plano um comando que produz saída. Junte a saída em um arquivo, para que ela nunca se misture com a de outros comandos.

Ver dica 1 (direção)

Só mandar para segundo plano ainda deixa a saída invadir o prompt. Lembre da sintaxe que muda o destino da saída.

Ver dica 2 (nome do comando)

Redirecione com > arquivo 2>&1. Mande para segundo plano com & no final. Leia o resultado com cat.

Ver resposta
$ ls -R / > result.log 2>&1 &
[1] 12345

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

# Quando o job terminar, voce vera algo como:
# [1]+  Done    ls -R / > result.log 2>&1

Por causa do 2>&1, os erros de "permission denied" das pastas ilegíveis também vão para o arquivo. Sua tela continua limpa.

Lina: Entendi! A segurança do Ctrl+Z é enorme - nunca mais vou matar o vim com Ctrl+C.
Veterano Linny: Essa é a experiência de "aprender controle de jobs." Cada dia no shell fica um pouco mais fluido a partir daqui.

Resumo em Três Linhas

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

Próximas Leituras