GICT knowledge base
Linux /proc: The Hidden Dashboard Every Server Admin Should Know
Published
A server feels sluggish. You open top and CPU looks fine. You run free -m and RAM is not maxed out. Nothing obvious. So what is holding things up?
The answer lives in /proc — a directory that looks like ordinary files but is actually a live window into your running kernel. Every number in it is real-time telemetry. No installation, no agents, no extra tools. This article opens that window and reads it.
What /proc Actually Is
On a typical Linux server, /proc is the first clue that something unusual is happening with filesystems. It contains entries like meminfo, loadavg, and numbered directories such as 1, 1234, 5678. It sits alongside your regular directories in the root filesystem.
Here is the first thing that surprises people: those files are not on disk. The kernel generates their content dynamically every time you read them. There is no /proc/meminfo blob sitting on an SSD somewhere. When you run cat /proc/meminfo, the kernel assembles the output from its own internal data structures and streams it to you.
There are two distinct kinds of entries in /proc:
- System-wide entries — files like
meminfo,loadavg, anduptimethat describe the kernel state across the entire machine - Per-process entries — numbered directories like
/proc/1/where each number is a running process ID
Everything in /proc is real-time. The moment you read it, you are reading the current state of the kernel.
The Sluggish Server Scenario
You log into a VPS via SSH. The shell is responsive but something feels slow. Here is where you start.
$ cat /proc/loadavg
0.20 0.23 0.19 1/525 2008309
loadavg shows three numbers: the load average over the last 1, 5, and 15 minutes. The fourth field (1/525) tells you how many processes are running compared to total processes on the run queue. The fifth number is the last PID assigned. In this case, the load average of 0.20 means the system has been mostly idle.
Now check how long the server has been running:
$ cat /proc/uptime
4949843.40 9014224.84
Two numbers. The first is total uptime in seconds (this machine has been running for about 57 days). The second is the sum of all cores idle time. Divide the second by the first and you get a rough picture of overall CPU idleness.
Memory Pressure
When memory seems fine but something is swapping or reclaiming pages, /proc/meminfo tells the real story. This is the raw source that the free command parses into human-readable output.
$ cat /proc/meminfo
MemTotal: 3905932 kB
MemFree: 275636 kB
MemAvailable: 752408 kB
Buffers: 19132 kB
Cached: 644088 kB
SwapCached: 0 kB
Active: 2250688 kB
Inactive: 943608 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Ignore MemFree. The field you want is MemAvailable. This is the kernel is estimate of how much memory is available for starting new applications without forcing them into swap. On this machine, about 752 MB is available out of 3.9 GB total.
If you want to know whether the OOM killer has fired at any point, check /proc/vmstat:
$ grep -i oom /proc/vmstat
oom_kill 10
Ten OOM kills since boot. That number is cumulative. If it is climbing, your system is repeatedly running out of memory and the kernel is killing processes to stay alive.
Per-Process Inspection
The numbered directories in /proc correspond to running processes. /proc/1 is always the init or systemd process.
$ ls /proc/1/
arch_status attr autogroup auxv cgroup clear_refs cmdline comm
coredump_filter cpu_resctrl_groups cpuset cwd environ exe fd fdinfo
gid_map io ksm_merging_pages ksm_stat loginuid map_files maps mem
mm mountinfo net ns numa_maps oom_adj oom_score oom_score_adj pagemap
personality projid_map root sched schedstat sessionid setgroups smaps
smaps_rollup stack stat statm status syscall timens_offsets uid_map wchan
Each of these files exposes something about process 1. Two are particularly useful when you are debugging:
/proc/[PID]/cmdline holds the commands arguments, separated by null bytes:
$ cat /proc/1/cmdline | tr '\0' ' '
/usr/lib/systemd/systemd --system --deserialize=118
/proc/[PID]/status gives a human-readable summary of everything important about a process:
$ cat /proc/self/status
Name: cat
Umask: 0022
State: R (running)
Tgid: 2008313
Pid: 2008313
PPid: 2008307
VmRSS: 5828 kB
Threads: 1
VmRSS is the resident set size — the amount of memory actually held in RAM. State shows the process state: R is running, S is sleeping, D is uninterruptible disk sleep, and Z is zombie.
To see what files a process has open, look at its file descriptors:
$ ls -la /proc/self/fd
total 0
lrwx------ 1 root root 64 Jul 8 23:17 0 -> /dev/null
l-wx------ 1 root root 64 Jul 8 23:17 1 -> pipe:[83488113]
l-wx------ 1 root root 64 Jul 8 23:17 2 -> pipe:[83487321]
lr-x------ 1 root root 64 Jul 8 23:17 3 -> /proc/2008357/fd
File descriptor 0 is stdin, 1 is stdout, 2 is stderr. Everything beyond that is what the process actually has open — log files, sockets, pipes, or in this case another process file descriptor.
Real-Time Without Installing Anything
The /proc filesystem lets you build live monitoring on the spot, no tools required.
Watch disk I/O in real time:
$ watch -n 1 'cat /proc/diskstats'
Watch network interface counters:
$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier
eth0: 21530295868 16634716 0 0 0 0 0 0 9430640269 12836024 0 0 0 0
The eth0 line shows total bytes received and transmitted. Run it twice with a pause in between and you can calculate throughput manually.
Find which process is hogging the most file descriptors:
$ ls /proc/*/fd 2>/dev/null | wc -l
Replace wc -l with a loop over /proc/PID/fd and readlink to get a sorted list of the top consumers.
Conclusion
The /proc filesystem is always there. It needs no installation and reveals what external monitoring tools sometimes miss. Every time a process reads a file, writes to disk, allocates memory, or communicates over the network, the kernel updates something in /proc.
Next time a server misbehaves and the usual logs do not help, crack open /proc before you open a support ticket. The kernel is already watching itself. You just have to look.
Related guides
How to Collect Nginx Logs with Vector
Collect Nginx logs with Vector, parse structured fields and verify fresh events. Understand checkpoints, rotation and delivery limitations.
monitoringHow to Monitor VPS Resources with Beszel: A Complete Guide
Install Beszel with Docker, connect its hub and agent, and verify CPU, memory, disk, and container metrics through a private dashboard.
monitoringCreating custom system monitoring dashboards with watch and tmux
Build powerful system monitoring dashboards with watch and tmux commands. Step-by-step guide covering fundamentals, use cases, and best practices for Linux admins.
monitoringSelf-Hosted Website Monitoring with Uptime Kuma on Ubuntu 22.04
Learn how to set up Uptime Kuma on Ubuntu 22.04 to monitor your sites with features like protocol support, alerts, and SSL tracking. Easy step-by-step guide!
