Sinais e exit codes
Sinais mais comuns
Seção intitulada “Sinais mais comuns”| Sinal | Nº | O que é | Pode ser capturado? |
|---|---|---|---|
SIGHUP |
1 | Terminal fechou; por convenção, recarregar config | sim |
SIGINT |
2 | Ctrl+C | sim |
SIGQUIT |
3 | Ctrl+, gera core dump | sim |
SIGKILL |
9 | Encerramento imediato | não |
SIGSEGV |
11 | Violação de memória | sim (raramente útil) |
SIGPIPE |
13 | Escreveu em pipe fechado | sim |
SIGTERM |
15 | Pedido educado de encerramento | sim |
SIGSTOP |
19 | Suspende | não |
SIGCONT |
18 | Retoma | sim |
SIGTERM é o que o Docker e o Kubernetes enviam primeiro. SIGKILL vem depois, se o
processo não sair no prazo.
kill -TERM <pid> # peça primeirokill -9 <pid> # force só se não houver saídakill -l # lista todos os sinaistrap 'echo saindo; limpar' TERM INT # capture em shell scriptExit codes e a aritmética 128+N
Seção intitulada “Exit codes e a aritmética 128+N”Quando o processo termina por causa de um sinal, o código de saída é 128 + número do sinal. Daí os valores que aparecem em log de container:
| Código | Sinal | Causa usual |
|---|---|---|
| 0 | — | Terminou normalmente |
| 1 | — | Erro genérico da aplicação |
| 2 | — | Uso incorreto do comando (convenção) |
| 126 | — | Arquivo encontrado, sem permissão de execução |
| 127 | — | Comando não encontrado |
| 129 | SIGHUP | Terminal encerrado |
| 130 | SIGINT | Ctrl+C |
| 137 | SIGKILL | Quase sempre OOM, ou grace period estourado |
| 139 | SIGSEGV | Segfault: arquitetura errada, libc incompatível, bug nativo |
| 143 | SIGTERM | Encerramento pedido (deploy, escala, drenagem) |
Distinguindo 137, 139 e 143
Seção intitulada “Distinguindo 137, 139 e 143”137 — o mais comum e o mais mal interpretado. Duas causas:
# foi OOM?docker inspect <ct> --format '{{.State.OOMKilled}}'kubectl describe pod <pod> -n <ns> | grep -i -A2 'last state'dmesg -T | grep -i 'killed process'Se OOMKilled for verdadeiro, aumente o limite de memória ou reduza o consumo. Se for
falso, o processo ignorou o SIGTERM e foi morto ao fim do terminationGracePeriodSeconds
— corrija o encerramento gracioso.
139 — o binário quebrou. Em container, a causa número um é imagem de arquitetura
errada (arm64 em host amd64) ou binário dinâmico rodando em base sem a libc esperada
(o caso Alpine/musl).
143 — normalmente não é erro: o orquestrador pediu para sair, em deploy, escala ou drenagem de nó. Só investigue se estiver acontecendo fora desses momentos.
Encerramento gracioso
Seção intitulada “Encerramento gracioso”A sequência no Kubernetes, e onde cada coisa quebra:
1. Pod marcado para remoção2. Em paralelo: a. Removido dos EndpointSlices (para de receber tráfego novo) b. preStop executa c. SIGTERM enviado ao processo3. Espera terminationGracePeriodSeconds (padrão 30s)4. SIGKILL, se ainda estiver vivo → exit 137lifecycle: preStop: exec: { command: ["sh", "-c", "sleep 10"] } # deixa o balanceador perceber a saídaterminationGracePeriodSeconds: 45 # > preStop + requisição mais longaDo lado da aplicação, capture o sinal e encerre limpo:
import signal, sysdef encerrar(sig, frame): servidor.parar_de_aceitar() # não aceite requisição nova servidor.aguardar_em_andamento(timeout=25) sys.exit(0)signal.signal(signal.SIGTERM, encerrar)A armadilha do PID 1
Seção intitulada “A armadilha do PID 1”Em container, o processo principal é o PID 1 — e o PID 1 não recebe os handlers padrão de
sinal. Se a aplicação não trata SIGTERM explicitamente, ela simplesmente ignora e morre
com 137 ao fim do prazo.
Outro caso: ENTRYPOINT ["sh", "-c", "meu-app"] faz o shell ser o PID 1, e ele pode não
repassar o sinal ao filho.
ENTRYPOINT ["/bin/app"] # forma exec: o app é o PID 1 e recebe o sinal# se precisar de shell ou de reaping de zumbis:# ENTRYPOINT ["tini", "--", "/bin/app"]Use a forma exec (lista JSON), não a forma shell (string).
Depuração
Seção intitulada “Depuração”docker inspect <ct> --format '{{.State.ExitCode}} {{.State.OOMKilled}} {{.State.Error}}'kubectl get pod <pod> -n <ns> -o jsonpath='{.status.containerStatuses[0].lastState}' | jqkubectl describe pod <pod> -n <ns> | sed -n '/Last State/,/Ready/p'journalctl -k | grep -i 'out of memory'