free -m: Read Real Memory Headroom on a Runner
free -m reports memory in mebibytes, and the column that matters is "available", the memory a new process can actually use.
After an OOM kill, free confirms whether the runner was genuinely out of memory. The trap is reading the "free" column instead of "available".
What it does
free shows total, used, free, shared, buff/cache, and available memory plus the swap line. Linux uses otherwise-free RAM as disk cache, so "free" looks small while "available" (free plus reclaimable cache) shows the true headroom a new allocation has.
Common usage
free -m
free -h # human units (Gi/Mi)
free -m -s 2 # refresh every 2 seconds
awk '/MemAvailable/{print $2/1024" MB"}' /proc/meminfoOptions
| Flag / column | What it does |
|---|---|
| -m / -g / -h | Show in MiB / GiB / human-readable units |
| -s <sec> | Repeat every N seconds |
| -t | Add a total line combining RAM and swap |
| available | Memory usable without swapping (the real number) |
| buff/cache | Reclaimable cache, counts toward available |
In CI
When a build fails with OOM, free -m near the failure should show "available" near zero and likely swap fully used. If "available" is comfortable but the job still OOMs, the limit is a cgroup/Docker --memory cap, not the host; check the container memory limit instead of the host free output.
Common errors in CI
Concluding "the runner is out of memory" from a small "free" column is the classic mistake; "available" is the correct figure. Inside a container, free reports the host’s memory, not the container’s cgroup limit, so it can look fine while the container is being throttled or killed. Read /sys/fs/cgroup/memory.max (cgroup v2) for the real limit.