Comando timeout: Limitando o Tempo de Execução de Comandos

Comando timeout: Limitando o Tempo de Execução de Comandos

O que você vai conseguir fazer

  • Limitar quanto tempo um comando pode rodar e evitar que ele fique travado
  • Ler o status de saída `124` para distinguir um timeout de uma falha
  • Usar `-k` para parar um processo que ignora o SIGTERM

Pré-requisitos (leia estes primeiro)

O Que Você Vai Aprender

  • Como limitar quanto tempo um comando executa com timeout
  • Como parar automaticamente um comando que "trava e nunca retorna"
  • Como detectar um timeout usando o status de saída 124
  • Como forçar o encerramento de um processo teimoso que ignora SIGTERM com -k

Resumo Rápido (os padrões para memorizar primeiro)

  • Executar com limite de tempo -> timeout 10 command (para após 10 segundos)
  • Adicionar unidade se preferir -> timeout 30s / timeout 5m / timeout 1h
  • Detectar um timeout -> status de saída 124 significa que expirou
  • Ainda não para -> timeout -k 5 10 command (kill forçado após período de graça)

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

Um comando que nunca retorna faz a tela parecer quebrada. Na maioria dos casos, estes passos resolvem.

O que você vê Como sair
Comando não termina e o promptUm símbolo (como $ ou #) exibido quando o shell está esperando sua entrada. não volta Pressione Ctrl+C para cancelar
Ctrl+C não para Pressione Ctrl+Z para pausar, veja o número com jobs e execute kill %1
Quer evitar essa situação sempre Já inicie com um limite: timeout 10 comando

O timeout é a medida preventiva, para que nada fique travado desde o início. Assim você aperta Ctrl+C muito menos.

1. O Que é o Comando timeout?

Conclusão: timeout encerra automaticamente um comando quando ele excede o limite de tempo que você definiu. É a ferramenta ideal para prevenir travamentos.

Lina: Senpai, executei um comando de download e ele simplesmente nunca terminou. A tela congelou e tive que apertar Ctrl+C. Essa é a única forma de parar?
Veterano Linny: É exatamente aí que o timeout ajuda. Ele permite definir um limite de tempo: "execute este comando por no máximo N segundos, e pare automaticamente se ultrapassar."
Lina: Então eu não preciso apertar Ctrl+C eu mesma? Ele para sozinho?
Veterano Linny: Exato. Isso evita que um comando fique "travado e executando." Isso importa especialmente para o cron - o mecanismo que executa comandos automaticamente em horários definidos, também chamado de execução agendada ou periódica. Um comando travado que fica ativo bloqueia todos os passos seguintes.
Lina: Então o timeout é a rede de segurança para isso.

O que significa "travar"

Travar é quando um comando para de avançar e parece parado. "Congelar", "preso" e "sem resposta" descrevem a mesma coisa. Isso nem sempre significa que o programa está quebrado. Muitas vezes ele só espera uma resposta que nunca chega.

A ideia básica do timeout

timeout 10 command
        |   |
        |   o comando que voce quer executar
        limite de tempo (segundos)

"Terminar dentro de 10 segundos e ele encerra normalmente; ultrapassar e ele é forçadamente parado."

2. Por Que Você Precisa do timeout?

Conclusão: Um comando que trava esperando rede ou em um loop infinito pode congelar todo seu script. timeout previne isso.

Lina: Mas se um comando funciona corretamente, você não precisa realmente de um limite de tempo, certo?
Veterano Linny: Normalmente, não. O problema são comandos onde você não sabe quando vão terminar - conectar a um servidor que não responde, pingar um host que sumiu, ou um loop que você escreveu errado. Esses podem nunca retornar.
Lina: É exatamente o que aconteceu com meu download...
Veterano Linny: Se um humano está observando, ele pode apertar Ctrl+C. Mas um cron job ou script de automação não tem ninguém observando.
Veterano Linny: O processo travado fica ali e o próximo passo nunca começa. Com timeout você define um limite superior, então no pior caso ele "desiste após N segundos e segue em frente."

Um comando travado deixado sozinho pode consumir memória ou slots de processo, ou causar execuções sobrepostas de cron. "Colocar um limite de tempo em qualquer coisa que pode não terminar" é a forma segura de operar.

3. Uso Básico (Especificando o Tempo)

Conclusão: A forma é timeout DURACAO comando. Um número simples significa segundos; adicione s/m/h/d para unidades.

A forma mais básica é:

$ timeout 10 sleep 30

sleep 30 normalmente espera 30 segundos. Mas com timeout 10, ele é parado após 10 segundos.

Lina: Terminou em 10 segundos mesmo sendo sleep 30. Parou antes dos 30 segundos prometidos.
Veterano Linny: Exato, é o limite de tempo em ação. Um número simples significa segundos. Você também pode adicionar uma unidade para ficar mais claro.

Você pode anexar uma unidade (sufixo) à duração.

$ timeout 30s command    # 30 segundos
$ timeout 5m command     # 5 minutos
$ timeout 1h command     # 1 hora
$ timeout 2d command     # 2 dias

Unidades de duração (sufixos)

Forma Significado
10 10 segundos (sem unidade = segundos)
30s 30 segundos
5m 5 minutos
1h 1 hora
2d 2 dias

Decimais também funcionam (timeout 0.5 command para 0,5 segundos).

4. Detectando Timeouts com Status de Saída 124

Conclusão: Quando timeout interrompe um comando, o status de saída é 124. Se echo $? mostrar 124, houve timeout.

O que é um status de saída

O status de saída é o número que um comando deixa ao terminar. "Código de saída" e "código de retorno" são outros nomes para a mesma coisa. 0 significa sucesso. Qualquer valor diferente de 0 significa que algo fora do normal aconteceu. O valor do último comando fica em $?.

Quando timeout para um comando porque o tempo expirou, o status de saída se torna 124. Verificar isso permite detectar um timeout mecanicamente.

$ timeout 1 sleep 10
$ echo $?
124
Lina: O número 124 apareceu. Então esse é o sinal de um timeout.
Veterano Linny: Exatamente. Por outro lado, se o comando termina normalmente dentro do tempo, seu próprio status de saída é retornado - 0 para sucesso, por exemplo.
Veterano Linny: Então verificar 124 diz se foi "cortado no meio" ou "terminou corretamente."

Se terminar a tempo, o próprio status do comando é retornado.

$ timeout 10 sleep 1
$ echo $?
0

Status de saída que valem conhecer

Valor Significado
124 Cortado por um timeout
125 O próprio comando timeout falhou
126 Comando encontrado mas não conseguiu executar
127 Comando não encontrado
137 Morto forcadamente pelo sinal KILL (-k) (128 + 9)

Por agora, apenas lembre "124 = timeout."

Em casos raros, um comando retorna 124 por conta própria. Quando for preciso distinguir, use --preserve-status.

5. Forçando o Encerramento de Processos Teimosos com -k

Conclusão: timeout envia SIGTERM por padrão. Se isso for ignorado, use -k DURACAO para enviar SIGKILL após um período de graça e parar com certeza.

O que é um processo

Um processo é um programa em execução dentro do computador. Um comando que você digita também vira um processo assim que começa a rodar.

O que é um sinal

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. Três deles cobrem quase tudo.

  • SIGTERM: um pedido para encerrar. O programa consegue fazer a limpeza antes de sair
  • SIGINT: o sinal enviado quando você pressiona Ctrl+C
  • SIGKILL: uma parada forçada. O programa não pode recusar
Lina: Ouvi dizer que às vezes um comando não para mesmo após timeout. Por quê?
Veterano Linny: Boa pergunta. Quando o tempo expira, timeout primeiro envia um SIGTERM (um pedido educado para encerrar) ao comando. Mas alguns programas ignoram esse pedido, então não param.
Lina: Então mesmo quando você pede para "por favor parar," ele não obedece... O que fazer então?
Veterano Linny: É aí que você usa -k (kill-after). Você configura uma abordagem em duas etapas: "se ainda não parou N segundos após o primeiro pedido, encerre à força."
$ timeout -k 5 10 command

Isso significa:

  • Primeiro, após 10 segundos, enviar SIGTERM (o pedido educado) ao comando
  • Se ainda não parou após mais 5 segundos, enviar SIGKILL (kill forçado)

Como -k (kill-after) funciona

timeout -k 5 10 command
         |  |
         |  o limite real de tempo (10s) -> SIGTERM
         graca extra (5s) -> SIGKILL se ainda estiver executando

Um programa não pode recusar SIGKILL. É o último recurso quando você precisa pará-lo com certeza.

SIGKILL (kill forçado) para o processo sem dar chance de limpar. Um arquivo sendo gravado pode ficar corrompido. Tente um timeout simples (SIGTERM) primeiro e deixe o -k como backup para quando ele não parar.

6. Especificando o Sinal (-s)

Conclusão: Use -s para alterar o sinal enviado. Se quiser que o status do próprio comando seja retornado no timeout, use --preserve-status.

Por padrão SIGTERM é enviado, mas você pode especificar um sinal diferente com -s (--signal).

$ timeout -s SIGINT 10 command

Isso envia SIGINT, o mesmo que Ctrl+C. Alguns comandos encerram mais graciosamente com isso do que com SIGTERM.

Lina: Sinais - são coisas como SIGTERM e SIGKILL, certo? Existem tipos diferentes?
Veterano Linny: Muitos. Os que você mais usa com timeout são três: o educado SIGTERM (padrão), SIGINT (como Ctrl+C), e o último recurso SIGKILL.
Veterano Linny: Sinais em si vão um pouco mais fundo. Vamos cobri-los adequadamente em outro artigo (fundamentos do trap).

Quando você quer que o timeout não reescreva o status para 124, use --preserve-status.

$ timeout --preserve-status 10 command

Com --preserve-status, um comando parado por SIGTERM retorna 143 (128 + 15). Ele não retorna "o valor que uma execução bem-sucedida teria produzido". Use quando você quer saber que o comando foi parado por um sinal. Normalmente é mais simples deixar desligado e verificar 124.

7. Erros Comuns de Iniciantes

Conclusão: É fácil confundir a ordem de duração e comando, o significado de 124 e a ordem de argumentos do -k.

7-1. Invertendo a ordem de duração e comando

# NG: o comando vem primeiro
$ timeout sleep 30 10

# OK: duracao -> comando
$ timeout 10 sleep 30

A duração deve sempre vir logo após timeout. Depois escreva o comando que quer executar. Inverta a ordem e timeout dá erro.

7-2. Confundir 124 com um "erro"

Lina: Senpai, socorro! Meu script acabou de retornar 124. Eu quebrei o comando?
Veterano Linny: Respira. 124 é prova de que o timeout fez seu trabalho conforme planejado.
Lina: Espera, não é um sinal de falha?
Veterano Linny: Não. Não é um defeito no comando. Significa "não terminou a tempo, então cortei como planejado."
Lina: Ah, era só isso...! Então quando eu ver 124, devo ler como "o limite foi atingido". Que alívio.

7-3. Pensar que limitou todo o pipeline quando apenas parte foi limitada

# Isto nao limita todo o pipeline
$ timeout 10 grep pattern file | sort

Um pipe (|) passa o resultado do comando da esquerda para o comando da direita. Mesmo assim, apenas a parte timeout 10 grep pattern file é limitada; | sort é tratado separadamente.

Para envolver um pipeline inteiro de uma vez, use bash -c 'comandos', que faz o shellUm programa interativo que interpreta os comandos digitados e os executa. tratar a linha toda como um único comando.

$ timeout 10 bash -c 'grep pattern file | sort'

8. Mini Exercícios: Tente Você Mesmo

Conclusão: Três tarefas - cortar, verificar status de saída, kill forçado - para sentir o timeout na prática.

Lina: Entendi os conceitos. Quero tentar na prática.
Veterano Linny: Ótimo, preparei três tarefas. Todas usam sleep, que não guarda nada que você possa perder, então nada quebra se você errar.

Exercício 1: Corte sleep 30 Após 3 Segundos

Tarefa: Faça um comando que normalmente leva 30 segundos terminar em 3.

Ver dica 1 (direção)

Escreva primeiro o limite de tempo e depois o comando que quer executar. Lembre qual unidade um número simples representa.

Ver dica 2 (nome do comando)

Use timeout. A forma é timeout DURACAO comando. Um número simples significa segundos.

Ver resposta
$ timeout 3 sleep 30

O prompt volta depois de 3 segundos. Você nunca espera os 30 completos.

Exercício 2: Confirme Que Houve Timeout

Tarefa: Logo após o Exercício 1, imprima o status de saída e confirme que é 124.

Ver dica 1 (direção)

O resultado do comando anterior fica guardado em uma variável especial. Imprima essa variável.

Ver dica 2 (nome do comando)

O resultado anterior está em $?. Imprima com echo $?.

Ver resposta
$ timeout 3 sleep 30
$ echo $?

Ver 124 significa que o timeout funcionou.

Exercício 3: Encerre à Força Quando Não Parar

Tarefa: Escreva um comando que pare sleep 30 com "SIGTERM em 5 segundos, depois SIGKILL se ainda estiver executando 2 segundos depois."

Ver dica 1 (direção)

Existe uma opção para a abordagem em duas etapas. Ela recebe o período de graça e o limite real, escritos lado a lado.

Ver dica 2 (nome do comando)

Use -k. A ordem é -k GRACA LIMITE comando.

Ver resposta
$ timeout -k 2 5 sleep 30

O sleep para direitinho com SIGTERM, então ele termina em 5 segundos e nunca chega ao SIGKILL.

Lina: Consegui! Duração primeiro, comando depois - e o resultado se lê pelo 124. Esses dois são o essencial.
Veterano Linny: Exatamente. O -k entra só para os que se recusam a parar. Com esses três, quase nada fica travado por aí.

9. Templates para Copiar e Colar

Conclusão: Tenha os padrões comuns à mão - básico, com unidades, detecção, kill forçado, pipeline.

Padrões comuns para ter à mão

# Basico: parar apos 10 segundos
timeout 10 command

# Adicionar unidade (segundos / minutos)
timeout 30s command
timeout 5m command

# Detectar timeout (124 significa timeout)
timeout 10 command
echo $?

# Kill forcado se nao parar (10s + 5s de graca, depois SIGKILL)
timeout -k 5 10 command

# Limitar um pipeline inteiro
timeout 10 bash -c 'commandA | commandB'

# Parar com SIGINT (como Ctrl+C)
timeout -s SIGINT 10 command

Resumo em Três Linhas

  • timeout DURACAO comando limita quanto tempo um comando pode rodar. A ordem é duração primeiro, comando depois
  • O status de saída 124 é o sinal de timeout, não um erro. Significa "cortado exatamente como planejado"
  • Para um processo que ignora o SIGTERM, use duas etapas com -k GRACA LIMITE. O SIGKILL é o último recurso

Próximas Leituras