/proc: Explanation & Insights
/proc is a virtual filesystem that presents the Linux kernel's live view of running processes and overall system state as readable text files.
What It Is
/proc is a directory full of files that aren't there.
That sounds like a riddle, and it's the one thing to understand before anything else, so let's take it slowly. Every other directory you've met holds files that sit on a disk: /etc keeps its config on the platter, /var/log keeps its logs, and if you pull the drive and read it in another machine, the bytes are right there where you left them. /proc is not like that. Pull the drive, search it end to end, and you will not find a single byte of /proc anywhere on it. Nothing under here is stored. It is a virtual — or synthetic — filesystem: a window the kernel holds open onto its own insides, dressed up to look exactly like ordinary files so that ordinary tools can read it.
Here is the part that gives the game away. Ask the size of one of these files and the system swears it's empty:
$ ls -l /proc/meminfo
-r--r--r-- 1 root root 0 Jul 7 15:12 /proc/meminfo
That's zero bytes. Now read it:
$ cat /proc/meminfo
MemTotal: 32444008 kB
MemFree: 554640 kB
MemAvailable: 8946940 kB
Buffers: 253872 kB
Cached: 16233080 kB
...
A full page of content out of a file that measures nothing. There's no contradiction once you see what's happening: the kernel doesn't know how big /proc/meminfo is because there is no /proc/meminfo until you ask for it. The instant you cat it, the kernel wakes up, reads its own live memory counters, formats them into text, and hands them over — cooked to order, then thrown away. It can't tell you the size in advance any more than a kitchen can tell you the weight of a dish it hasn't made yet. The menu lists nothing because the food doesn't exist until you point at it.
So /proc isn't a place where data is kept. It's a place where data is generated, on read. Every file here is really a tiny question you put to the kernel, and the "contents" are its freshly-computed answer.
Why It Matters
Because this is how your whole toolbox actually works, and almost nobody tells you.
When you run top to see what's eating the CPU, or free to check memory, or ps to list processes, or uptime to see how long the box has been up — none of those programs has a secret hotline to the kernel. They open text files in /proc and read them, exactly the way you'd read your own notes. top, for all its blinking authority, is at heart a program that reads a stack of files under /proc a few times a second and redraws the screen. You could write a shabby version of it yourself with cat and a loop. Run strace on ps and you'll catch it in the act, opening one numbered directory after another. The moment that clicks, a whole shelf of commands stops being magic and turns into what it always was: convenient front-ends over these plain files.
That's also why /proc is the beating heart of every monitoring tool on Linux, this one included. When something reports your load, your free memory, or your busiest process, the number came from here first — there is nowhere else on the machine to get it. Learn to read /proc directly and you've learned to take the machine's pulse with your fingers instead of through a gadget. On the day a tool hands you a number you don't believe, you can walk straight to the source and read the same raw file it read.
The Name Lies a Little: Two Halves Under One Roof
/proc is short for processes, and that name causes a genuine, predictable confusion, so let's clear it up now. /proc holds two quite different kinds of thing, and only one of them is about processes.
List the directory and the split jumps out at you:
$ ls /proc
1 107 cpuinfo meminfo mounts uptime
10 10398 loadavg net sys version
...
- The numbered entries —
1,10,107, and dozens more — are one directory per running process, named after its PID (its process ID, the number the system uses to tell one running program from another). This is the half the name promises: a folder for every living process, holding everything the kernel knows about it. - The named entries —
meminfo,loadavg,cpuinfo,uptime,version,mounts, and the rest — have nothing to do with any one process. They're system-wide readouts: total memory, load average, CPU details, kernel version, what's mounted. This half is where the whole machine reports on itself.
So half of /proc is a filing cabinet with a drawer per process, and the other half is the machine's own dashboard. They share a roof for a good historical reason we'll get to — but if you came expecting /proc to be only about processes, that's the name setting you up, and now you know better.
There's a wrinkle worth naming while we're here: a few of those entries are big enough to be their own worlds, with their own pages for the full depth — /proc/sys, the live tree of kernel tuning knobs (the sysctl settings, and the one corner of /proc you can actually write to and change the running kernel); /proc/bus and /proc/bus/pci, the hardware buses; and /proc/pressure, the pressure stall information that tells you how hard tasks are queuing for CPU, memory, and disk.
The Per-Process Directories
Pick any process and step into its directory — say a running bash shell with PID 273793, at /proc/273793. Inside is a small library of files, each one answering a single question about that single process. Here are the ones you'll actually reach for.
status is the human-readable summary, and the first door I open every time. Name, state, the user and group it runs as, how much memory it's holding, how many threads it's juggling — all in plain text:
$ cat /proc/273793/status
Name: bash
State: S (sleeping)
Tgid: 273793
Pid: 273793
PPid: 259457
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 64
...
Give that State: S (sleeping) a second look, because it worries people who don't need worrying. It doesn't mean the shell is broken. It means the shell is doing the most ordinary thing a program ever does: nothing, on purpose. A shell spends nearly its whole life asleep, parked patiently until you press a key — and the same is true of most of the processes on any healthy machine. PPid is the parent, the process that launched this one, so you can walk the family tree upward by hand, PID by PID, until you arrive back at the very first process the kernel ever started.
cmdline is the exact command line the process was born with. A small trap lives here: the arguments are separated by invisible null bytes, not spaces, so a plain cat welds them into one run-on smear. Pipe it through tr '\0' ' ' to make it legible. And there's a quiet cleverness in that choice of separator — the kernel picks the null byte, the one character that can never legally appear inside a filename or an argument, precisely because it's the one divider nothing in the string could ever be mistaken for.
environ is every environment variable the process was handed at birth, null-separated the same way. This is how you settle an argument with a mystery daemon: instead of guessing what it thinks its settings are, you read its own environ and let it tell you.
fd/ is a directory of symlinks, one per open file descriptor — every open file, socket, and pipe a process holds gets a small integer, and these are those integers made visible. It shows you, live, exactly what the process has its hands on right now:
$ ls -l /proc/273793/fd
lr-x------ 0 -> /dev/null
l-wx------ 1 -> pipe:[7356177]
lrwx------ 3 -> /var/log/app.log
maps is the full memory map: every range of virtual memory the process holds, which library or file is mapped into each stretch, and whether that stretch is readable, writable, or executable. It's dense reading, but it is the ground truth of a program's address space — nothing in a process's memory is hidden from it.
Pro Tip
Here's a save-the-day trick that falls straight out of
fd/. Someone deletes a log or a config that a running service still has open — the file is gone from its directory, but the process never noticed and kept reading and writing it, so its bytes are still very much alive. Look in/proc/<pid>/fd/, find the symlink still pointing at the (now-deleted) file, andcatit straight back out:cat /proc/1234/fd/3 > recovered.log. The name is gone; the data is still there, held open, waiting to be claimed. As long as one process has it open, the file isn't really deleted yet — it's just lost its label.
One more small piece of magic before we leave the per-process half. There's a symlink called /proc/self, and it always points at the directory of whoever is reading it this very instant. Two programs can open the exact same path at the exact same moment and each be led to its own, different, entirely correct answer. It is the filesystem's "You Are Here" dot — one fixed sign, planted once, that quietly means something different for every single person standing in front of it.
The System-Wide Files
Cross the roof to the other half and the named files are the machine's own vital signs. The load-bearing few, in the order I tend to read them:
loadavg is the system load, with a little something extra tacked on the end:
$ cat /proc/loadavg
0.26 0.31 0.39 3/2021 273813
The first three numbers are the load average over the last 1, 5, and 15 minutes — roughly, how many tasks were runnable or waiting, averaged across each window. Then 3/2021: three tasks runnable this instant out of 2021 the kernel is currently keeping track of. And that last number, 273813, is the PID the kernel handed out most recently — a quiet odometer that clicks over once for every process the machine has started since it booted, climbing into the hundreds of thousands on a busy box while nobody's watching it.
meminfo is the memory picture in full: total RAM, what's free, and the one number that actually earns its keep, MemAvailable — the kernel's honest estimate of how much a new program could grab without shoving the machine into swap. When free tells you your memory situation, this file is where it read it; free just tidies the numbers into columns.
uptime is two numbers, and it's the second one that catches people out:
$ cat /proc/uptime
297999.66 1889267.33
The first is seconds since boot — a hair under three and a half days. The second is total idle time — and it is larger than the machine has even been switched on. That's not a bug and it's not a rounding error: this box has 8 CPU cores, and the idle figure quietly adds up the idle seconds of every one of them. Eight cores loafing for three and a half days pile up far more idle time than the wall clock has had a chance to tick. It's just the honest arithmetic of counting eight bored workers at once, and adding all their yawns together.
version is the exact kernel, compiler, and build date, all on one line — the machine cheerfully telling you which compiler assembled its own kernel, and on what afternoon:
$ cat /proc/version
Linux version 6.12.95+deb13-amd64 (debian-kernel@lists.debian.org)
(gcc-14 ...) #1 SMP PREEMPT_DYNAMIC Debian 6.12.95-1 (2026-07-04)
cpuinfo is a block per logical CPU: model name, clock speed, cache size, and a long list of feature flags spelling out exactly what tricks the silicon knows. It's the closest thing your processor has to a résumé.
mounts is every filesystem actually mounted right now, and how. This one comes with a companion worth keeping straight: /etc/fstab is the list of what you meant to mount at boot; mounts is what the machine actually did about it. When they disagree — a disk that quietly failed to come up, a share someone mounted by hand at 2 a.m. and forgot all about — /etc/fstab will still swear blind to the plan, while mounts reports what really happened. Believe mounts.
How I Inspect It
No special tool — /proc was built precisely so the everyday ones would just work. The moves I make without thinking:
# The whole machine's pulse in three files
cat /proc/loadavg
cat /proc/meminfo
cat /proc/uptime
# What is this mystery process, really?
cat /proc/<pid>/status
cat /proc/<pid>/cmdline | tr '\0' ' '; echo
ls -l /proc/<pid>/fd
# Which kernel am I actually on?
cat /proc/version
# What's genuinely mounted (not just what fstab wishes)?
cat /proc/mounts
Note
Don't be alarmed that everything under
/procshows a size of0in a listing, or that timestamps look odd, or that a process directory vanishes the instant its program exits. All of that is by design — these aren't stored files, they're live answers, and an answer has no size until someone asks the question. Runls/proctwice in a row and the numbered directories won't match: you're photographing a moving crowd, and people keep arriving and leaving between shots.
Cheat Sheet
| Command | What it tells you |
|---|---|
cat /proc/loadavg |
Load over 1/5/15 min, runnable tasks, last PID issued |
cat /proc/meminfo |
Full memory breakdown (what free reads) |
cat /proc/uptime |
Seconds since boot, and summed idle across all cores |
cat /proc/version |
Kernel version, compiler, build date |
cat /proc/cpuinfo |
Per-core model, speed, cache, feature flags |
cat /proc/mounts |
Filesystems mounted right now |
cat /proc/<pid>/status |
A process's state, owner, memory, threads |
cat /proc/<pid>/cmdline \| tr '\0' ' ' |
How a process was actually launched |
ls -l /proc/<pid>/fd |
Every file, socket, and pipe it has open |
cat /proc/self/status |
The status of whatever process is asking |
History and Philosophy
The idea is older and stranger than Linux, and it begins with a frustration every debugger author knew in his bones. To peer inside a running program you called ptrace — the one system call built for the job — and it let you read the target's memory a single machine word at a time, through a cramped little interface that felt like reading a novel through a keyhole. In 1984, a Bell Labs researcher named Tom Killian, working on the eighth edition of Research Unix, asked a wonderfully innocent question: what if a process were just a file? Then a debugger could open it and read its memory with the same plain read every other program already used — no keyhole, no special call, just a file you open and read like any other. He wrote it up in a paper whose title is the whole idea, sanded down until nothing was left to remove: Processes as Files. That was /proc.
The notion caught, because it landed squarely on the oldest principle in Unix: everything is a file. Your disk is a file, your terminal is a file, /dev/null — the bottomless bin — is a file. Killian's move was to take that principle, which everyone claimed to believe, and aim it at the one thing nobody had thought to point it at: the running programs themselves. Plan 9 — the operating system Bell Labs built as Unix's intended successor — later pushed the same idea about as far as it can go, turning very nearly every service in the system into a file you read and write. /proc is the piece of that radical vision that made it all the way home into everyday Linux.
Linux picked it up early — process directories arrived in 1992, in a kernel version well shy of 1.0 — and then did something the original authors hadn't: it kept adding to it. Where classic /proc was strictly about processes, Linux began hanging system-wide readouts off the same tree, and within months meminfo, cpuinfo, loadavg and the rest had moved in. /proc predates Linux's other virtual filesystem, /sys, by more than a decade — which is exactly why so much lives in /proc that, by a tidier design, would have been filed elsewhere. It grew like a well-loved house with rooms added on over the years: never perfectly planned, but every corner earning its keep, and nobody who lives there would dream of tearing it down.
Gotchas
- Nothing here is stored, so nothing here survives. You can't back up
/proc, and copying it makes no sense — you'd be saving the answers to questions nobody's asking anymore. It is rebuilt from live kernel state at every boot, empty until the machine wakes and starts answering again. - The size is always
0, and that's correct. Any tool that trusts the reported size of a/procfile — allocating a buffer to match, say — will read nothing at all. You have to just keep reading until the kernel stops handing you bytes. cmdlineandenvironare null-separated, not space-separated. A rawcatmashes the fields into one run-on smear. Pipe throughtr '\0' '\n'(or' ') to make them legible — a first-timer trap, and it catches everyone exactly once.- Process directories disappear the instant their process exits. Read
/proc/<pid>/statusfor a program that just died and you'll get "No such file or directory." The directory was never a thing sitting on a disk; it was only the kernel's willingness to answer questions about that process — and the process is gone, so there's nothing left to answer. /proc/mountsis the truth;/etc/fstabis only the intention. When they disagree — a disk that failed to mount, a filesystem someone mounted by hand — believe/proc/mounts. It reports what is, never what was merely planned.
See Also
/sys— the younger virtual filesystem/procoverflowed into, for devices and hardware/proc/sys— the live kernel tuning knobs, the writable corner of/proc/proc/bus— the hardware buses, including/proc/bus/pci/proc/pressure— how hard tasks are queuing for CPU, memory, and disk/dev— hardware presented as files, the same "everything is a file" idea one step over- The root directory — where
/prochangs, and the tree it all descends from - process — what each numbered directory under
/procdescribes - load average — the three numbers at the front of
/proc/loadavg - file descriptor — the open handles listed under
/proc/<pid>/fd top,ps, andfree— the everyday tools that are really just readers of/proc
Every tool that reports your server's health reads it from /proc first — so who's reading it while you sleep?
CleverUptime watches the vital signs that live behind these files — load, memory, the busiest processes, kernel and uptime — and tells you in plain words when one of them starts to slip, before it becomes the reason you're awake at 3 a.m.
Want to see your own server's health right now? One command, no signup, no install.