Linux process "Killed" with no error: find the OOM killer and stop it happening again
A process that just prints "Killed" (exit code 137) was usually stopped by the Linux OOM killer. Find it in the kernel log, see what used the memory, and fix it.
by OhSudo ··
Not sure this is your cause?Find it step by step: Disk full or out of memory →
Part of a learning path:Linux: from zero to fixing a server
A script or a service stops in the middle of its work. No stack trace, no error message of its own — just:
$ python3 build_report.pyKilled$ echo $?137Killed is what the shell prints when a program receives SIGKILL, and 137 is 128 + 9, the number of that signal. Nobody typed kill -9: in most cases it was the kernel’s OOM killer (“out of memory”). When the machine runs out of RAM and swap, the kernel picks a process — usually the biggest — and kills it to save the rest of the system. It writes down what it did in the kernel log.
- RAM and swaprun out(breaks here)kernel steps in(fails)
- OOM killerpicks a processsends
- KilledSIGKILL, exit code 137
TL;DR
1. Confirm it was the OOM killer
[ 3290.902355] Out of memory: Killed process 1874 (python3) total-vm:3412880kB, anon-rss:3021440kB, file-rss:4kB, shmem-rss:0kB, UID:998 pgtables:6040kB oom_score_adj:0Killed process 1874 (python3)— the victim.anon-rss:3021440kB— the memory it really used when it was killed: about 2.9 GB.
dmesg only keeps recent messages, and only since the last boot. The journal keeps more, with real dates:
The line oom-kill:constraint=… tells you which kind of OOM it was:
global_oom— the whole machine ran out of memory.CONSTRAINT_MEMCG, and the log saysMemory cgroup out of memory— the process hit its own limit (a container’s memory limit, orMemoryMax=of a systemd service), even if the machine had memory left. Docker and Kubernetes then report the container asOOMKilled— see Docker exited with code 137.
For a systemd service, systemctl status says it too:
× report-worker.service - Nightly report worker Active: failed (Result: oom-kill) since …2. Why the machine ran out
total used free shared buff/cache availableMem: 3.8Gi 3.3Gi 189Mi 12Mi 342Mi 483MiSwap: 0B 0B 0BLook at available (not “free” — the cache can be given back) and at Swap. No swap at all means the kernel has nowhere to move rarely used memory, so it reaches the OOM killer sooner. See what uses memory right now:
ps aux --sort=-%mem | headThen decide which case it is:
- One program grows until it’s killed — a memory leak, or a job that loads too much at once (a whole file, a whole table). Fix the program: process data in chunks, stream instead of loading everything.
- Everything together doesn’t fit — too many workers, a database cache sized for a bigger machine, several apps that each assume they’re alone.
- A short spike — a build, a backup, a big query. Swap usually absorbs it.
3. Fixes
Add swap (a modest amount, as a safety net — not as extra RAM):
sudo fallocate -l 2G /swapfilesudo chmod 600 /swapfilesudo mkswap /swapfilesudo swapon /swapfileecho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabLimit the program, so it’s the one that dies — not your database. For a systemd service, a memory limit makes the kernel stop that service when it goes too far, instead of choosing any process on the machine:
sudo systemctl edit report-worker[Service]MemoryMax=1GRestart=on-failureProtect what must survive. OOMScoreAdjust=-500 in a service’s unit makes the OOM killer much less likely to pick it (-1000 means never — use it only for something truly essential, like sshd).
Size things to the machine: fewer workers, a smaller database cache, Java’s -XX:MaxRAMPercentage, Node.js’s --max-old-space-size. And if the work really needs more memory, the honest fix is a bigger machine.
Note
On desktops with systemd-oomd (Ubuntu desktop since 22.04, Fedora), processes can be stopped before the kernel runs out, when memory pressure stays high. Then the kernel log is empty, and the journal has the reason: journalctl -u systemd-oomd.
Shell, we have a problem!
Similar, but different: Segmentation fault (exit code 139) — the program crashed by itself. Terminated (exit code 143) — someone or something sent SIGTERM, often a systemctl stop, a timeout or a deploy. Cannot allocate memory as an error message (not a kill) — a single allocation or fork was refused; see the fork section in Redis MISCONF. fork: retry: Resource temporarily unavailable is a process limit, not memory.
$ ./practice.sh
Practice this in the terminal
Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.