Processes, signals and exit codes
Every running program is a process with a number. Ask one to stop, force one that won't, and learn to read the exit code it leaves behind - the same 137 you'll meet in Kubernetes.
A program on disk is just a file. Start it and you get a process: a running copy with its own number, the PID, and an owner. Your shell is a process. So is every command you type, for as long as it runs. ps lists them.
Processes don’t get told what to do by being edited. They get sent signals: small numbered messages, delivered by the kernel. Four matter most:
| Signal | Number | Meaning | Can the program ignore it? |
|---|---|---|---|
SIGTERM |
15 | “Please stop.” What kill sends by default. |
Yes - and good programs catch it, save their work and exit |
SIGINT |
2 | What Ctrl+C sends to the program in front of you. | Yes |
SIGHUP |
1 | “Your terminal went away.” | Yes |
SIGKILL |
9 | Not a message to the program at all. The kernel ends it. | No. It can’t be caught, blocked or ignored |
- kill with no options sends SIGTERM: a request, delivered to the process itself.
- A well-written program catches it, finishes or saves what it was doing, and exits cleanly.
- kill -9 sends SIGKILL. The process is never told: the kernel removes it, and none of its code runs again.
- Whatever it was writing stays half-written. Your shell reports 137: 128 plus the signal number, 9.
Exit codes: the number every process leaves behind
When a process ends it leaves an exit status, and your shell keeps the last one in $?. Zero means success. Anything else is some kind of failure, and a few values are worth knowing by sight:
- 127: command not found. 126: found, but not allowed to run.
- 128 + N: killed by signal N. So 143 is SIGTERM (128 + 15), 130 is SIGINT (Ctrl+C) and 137 is SIGKILL.
Stop two programs
Two processes are running on this machine. orders is holding three orders it hasn’t saved yet. stuck was written to ignore polite requests. The process table on the right updates as you go.
A process was ended and your shell shows exit status 137. What does that tell you?
Bash reports a process killed by signal N as 128 + N. 137 means SIGKILL: something ended it from outside, and the program had no say.
The same numbers in Kubernetes
A container is a process too, and Kubernetes stops one the way you just did. To shut a pod down, the kubelet has the container runtime send SIGTERM to process 1 in each container, then waits a grace period - 30 seconds unless the pod says otherwise. Anything still running after that gets SIGKILL.
So when the restarts lesson shows a container with exit code 137, you now know what happened, if not yet why. Something sent signal 9: the kernel’s out-of-memory killer, or Kubernetes itself after the process ignored SIGTERM or ran out of grace period. Exit code 143 means it ended because of SIGTERM - either it didn’t handle it, or (like the JVM) it cleaned up and then reported the signal.
Your app needs 45 seconds to finish its in-flight work after SIGTERM, and runs with the default settings in Kubernetes. What happens on every deploy?
The default grace period is 30 seconds. After that the kubelet sends SIGKILL, so the last 15 seconds of work are lost on every rollout. Either finish faster after SIGTERM, or raise terminationGracePeriodSeconds.
Everything above ran in your browser. Now try it in a real terminal: any Linux machine, a Mac's Terminal app, or Windows with WSL. Nothing to install beyond that.
Watch the numbers for yourself. In bash or zsh:
sleep 300 &
kill %1 # SIGTERM
wait %1; echo $? # 143
sleep 300 &
kill -9 %1 # SIGKILL
wait %1; echo $? # 137Then write a program that catches SIGTERM. trap runs a command when a signal arrives:
bash -c 'trap "echo saving...; exit 0" TERM; while true; do sleep 1; done' &
sleep 1 # give it a moment to set the trap, or the signal can beat it
kill %1 # prints "saving..."
wait %1; echo $? # 0: it handled the signalSources
Missions and quizzes above earn their own XP. This marks the lesson done.