Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

proc Filesystem for Observability

Introduction

The /proc filesystem is a pseudo-filesystem that provides a window into the kernel’s internal data structures. It doesn’t exist on disk—it’s generated dynamically by the kernel when accessed. /proc is the foundation of Linux observability: every monitoring tool (top, free, iostat, vmstat, ps) reads from /proc under the hood.

Understanding /proc gives you direct access to kernel information without any additional tools. When top shows CPU usage, it’s reading /proc/stat. When free shows memory, it’s reading /proc/meminfo. When ps lists processes, it’s reading /proc/<pid>/status. Knowing this lets you write custom monitoring scripts, debug issues that standard tools can’t capture, and understand exactly what your system is doing.

/proc Overview

ls /proc/
# 1  2  3  ...  self  cpuinfo  meminfo  stat  version  ...

The entries in /proc fall into two categories:

  • Numeric directories (1, 2, 3, …) — one per running process, containing per-process information
  • Named files (cpuinfo, meminfo, stat, …) — system-wide kernel information

System-Wide Files

ls /proc/ | grep -v '^[0-9]' | sort
# acpi         bus/       cmdline    cpuinfo    crypto     devices
# diskstats    dma        driver/    execdomains  fb        filesystems
# fs/          interrupts  iomem     ioports    irq/       kallsyms
# kcore        keys       key-users  kmsg       kpagecount kpageflags
# loadavg      locks      mdstat     meminfo    misc       modules
# mounts       mtrr       net/       pagetypeinfo  partitions  sched_debug
# schedstat    scsi/      self       slabinfo   softirqs   stat
# swaps        sys/       sysrq-trigger  thread-self  timer_list  tty/
# uptime       version    vmallocinfo  vmstat     zoneinfo

Per-Process Directories

# Each process has a directory /proc/<pid>/
ls /proc/1/
# attr/    cgroup   comm     cpu      cwd@     environ  exe@     fd/
# fdinfo/  io       limits   maps     mem      mountinfo mounts   net/
# ns/      oom_score  oom_score_adj  pagemap  personality  root@
# sched    sessionid  smaps    smaps_rollup   stat     statm    status
# syscall  task/    timers   wchan

# The 'self' symlink points to the current process's directory
ls -la /proc/self
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 /proc/self -> 12345

Process Information (/proc/[pid]/)

Process Identity

# Process ID and parent
cat /proc/1/status | head -10
# Name:   systemd
# Umask:  0000
# State:  S (sleeping)
# Tgid:   1
# Ngid:   0
# Pid:    1
# PPid:   0
# TracerPid:  0
# Uid:    0   0   0   0
# Gid:    0   0   0   0

# Command line (null-separated)
cat /proc/1/cmdline | tr '\0' ' '
# /sbin/init

# Current working directory
ls -la /proc/1/cwd
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 /proc/1/cwd -> /

# Executable path
ls -la /proc/1/exe
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 /proc/1/exe -> /lib/systemd/systemd

# Process environment (null-separated, requires root)
cat /proc/1/environ | tr '\0' '\n' | head -5
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
# LANG=en_US.UTF-8
# TERM=xterm-256color

Process Status

cat /proc/1/status
# Name:   systemd
# Umask:  0000
# State:  S (sleeping)
# Tgid:   1
# Ngid:   0
# Pid:    1
# PPid:   0
# TracerPid:  0
# Uid:    0   0   0   0
# Gid:    0   0   0   0
# FDSize: 256
# Groups:
# NStgid: 1
# NSpid:  1
# NSpgid: 1
# NSsid:  1
# VmPeak:  12345678 kB
# VmSize:  12345678 kB
# VmLck:         0 kB
# VmPin:         0 kB
# VmHWM:    8234567 kB
# VmRSS:    8234567 kB
# RssAnon:   8234567 kB
# RssFile:    123456 kB
# RssShmem:    56789 kB
# VmData:   8234567 kB
# VmStk:       136 kB
# VmExe:    1234567 kB
# VmLib:     234567 kB
# VmPTE:      3456 kB
# VmSwap:        0 kB
# Threads: 42
# SigQ:   0/123456
# SigPnd: 0000000000000000
# ShdPnd: 0000000000000000
# SigBlk: 0000000000000000
# SigIgn: 0000000000000000
# SigCgt: 0000000000000000
# CapInh: 0000000000000000
# CapPrm: 0000003fffffffff
# CapEff: 0000003fffffffff
# CapBnd: 0000003fffffffff
# CapAmb: 0000000000000000
# NoNewPrivs: 0
# Seccomp:    0
# Seccomp_filters:    0
# Speculation_Store_Bypass:   vulnerable
# SpeculationIndirectBranch:  vulnerable
# Cpus_allowed:   ffffffff
# Cpus_allowed_list:  0-31
# Mems_allowed:   00000000,00000000,00000000,00000001
# Mems_allowed_list:  0
# voluntary_ctxt_switches:    123456
# nonvoluntary_ctxt_switches: 789

Key Status Fields Explained

FieldDescriptionTroubleshooting Use
VmPeakPeak virtual memory sizeDetect memory leaks
VmRSSResident Set Size (physical memory)Current memory usage
RssAnonAnonymous memory (heap, mmap)Heap memory usage
RssFileFile-backed memory (shared libs)Library memory
RssShmemShared memory (tmpfs, shmem)Shared memory usage
VmSwapSwapped-out memoryDetect swapping
ThreadsNumber of threadsThread leak detection
voluntary_ctxt_switchesVoluntary context switchesI/O waiting
nonvoluntary_ctxt_switchesInvoluntary switchesCPU contention
SeccompSeccomp filter modeSecurity policy
Speculation_Store_BypassSpectre mitigationVulnerability status

Process I/O Statistics

cat /proc/1/io
# rchar: 1234567890
# wchar: 2345678901
# syscr: 1234567
# syscw: 2345678
# read_bytes: 1234567890
# write_bytes: 2345678901
# cancelled_write_bytes: 123456789

# Fields:
# rchar: bytes read (including from cache)
# wchar: bytes written (including to cache)
# syscr: read syscalls
# syscw: write syscalls
# read_bytes: bytes actually read from storage
# write_bytes: bytes actually written to storage
# cancelled_write_bytes: bytes cancelled before write

Process Memory Map

# Memory mappings
cat /proc/1/maps | head -10
# 7f1234000-7f1256000 r-xp 00000000 08:01 1234567  /lib/libc-2.31.so
# 7f1256000-7f1278000 ---p 00022000 08:01 1234567  /lib/libc-2.31.so
# 7f1278000-7f127a000 r--p 00022000 08:01 1234567  /lib/libc-2.31.so
# 7f127a000-7f127c000 rw-p 00024000 08:01 1234567  /lib/libc-2.31.so
# 7f127c000-7f1282000 rw-p 00000000 00:00 0
# 7ffc123000-7ffc145000 rw-p 00000000 00:00 0      [stack]

# Format: address perms offset dev inode pathname
# perms: r=read, w=write, x=execute, p=private, s=shared

# Detailed memory map with page info
cat /proc/1/smaps | head -30
# 7f1234000-7f1256000 r-xp 00000000 08:01 1234567  /lib/libc-2.31.so
# Size:               136 kB
# KernelPageSize:        4 kB
# MMUPageSize:           4 kB
# Rss:                 136 kB
# Pss:                 136 kB
# Shared_Clean:          0 kB
# Shared_Dirty:          0 kB
# Private_Clean:       136 kB
# Private_Dirty:         0 kB
# Referenced:          136 kB
# Anonymous:             0 kB
# LazyFree:              0 kB
# AnonHugePages:         0 kB
# ShmemPmdMapped:        0 kB
# Shared_Hugetlb:        0 kB
# Private_Hugetlb:       0 kB
# Swap:                  0 kB
# SwapPss:               0 kB
# Locked:                0 kB

Process File Descriptors

# List open file descriptors
ls -la /proc/1/fd/
# lrwx------ 1 root root 64 Jul 22 10:00 0 -> /dev/null
# lrwx------ 1 root root 64 Jul 22 10:00 1 -> /dev/null
# lrwx------ 1 root root 64 Jul 22 10:00 2 -> /dev/null
# lrwx------ 1 root root 64 Jul 22 10:00 3 -> socket:[12345]
# lrwx------ 1 root root 64 Jul 22 10:00 4 -> /var/log/syslog

# File descriptor info
cat /proc/1/fdinfo/3
# pos:    0
# flags:  02000002
# mnt_id: 12

# Count open files per process
ls /proc/1/fd/ | wc -l
# 42

# Find which process has a file open
ls -la /proc/*/fd/ 2>/dev/null | grep "deleted"
# Shows deleted files still held open

Process Limits

cat /proc/1/limits
# Limit                     Soft Limit           Hard Limit           Units
# Max cpu time              unlimited            unlimited            seconds
# Max file size             unlimited            unlimited            bytes
# Max data size             unlimited            unlimited            bytes
# Max stack size            8388608              unlimited            bytes
# Max core file size        0                    unlimited            bytes
# Max resident set          unlimited            unlimited            bytes
# Max processes             123456               123456               processes
# Max open files            1024                 1048576              files
# Max locked memory         67108864             67108864             bytes
# Max address space         unlimited            unlimited            bytes
# Max file locks            unlimited            unlimited            locks
# Max pending signals       123456               123456               signals
# Max msgqueue size         819200               819200               bytes
# Max nice priority         0                    0
# Max realtime priority     0                    0
# Max realtime timeout      unlimited            unlimited            us

Process Scheduling

# Scheduling information
cat /proc/1/sched
# systemd (1, #threads: 42)
# -------------------------------------------------------------------
# se.exec_start                      :    12345678.123456
# se.vruntime                        :    23456789.234567
# se.sum_exec_runtime                :    34567.890123
# nr_switches                        :    123456
# nr_voluntary_switches              :    123450
# nr_involuntary_switches            :    6
# se.statistics.wait_sum             :    1234.567890
# se.statistics.wait_max             :    45.678901
# se.statistics.wait_count           :    123450
# se.statistics.iowait_sum           :    0.000000
# se.statistics.iowait_count         :    0

/proc/stat: CPU Statistics

cat /proc/stat
# cpu  123456789 7890 23456789 8901234567 67890 0 12345 0 0 0
# cpu0 30864197 1972 5864197 2225308641 16972 0 3136 0 0 0
# cpu1 30864197 1972 5864197 2225308641 16972 0 3136 0 0 0
# cpu2 30864197 1972 5864197 2225308641 16972 0 3136 0 0 0
# cpu3 30864197 1972 5864197 2225308641 16972 0 3136 0 0 0
# intr 1234567890 123 456 789 ...
# ctxt 12345678901
# btime 1626784800
# processes 1234567
# procs_running 4
# procs_blocked 0
# softirq 1234567890 123456 789012 345678 ...

Fields Explained

# cpu  user nice system idle iowait irq softirq steal guest guest_nice
# user:    normal processes executing in user mode
# nice:    niced processes executing in user mode
# system:  processes executing in kernel mode
# idle:    twiddling thumbs
# iowait:  waiting for I/O to complete
# irq:     servicing hardware interrupts
# softirq: servicing software interrupts
# steal:   involuntary wait (virtual machines)
# guest:   running a virtual CPU
# guest_nice: running a niced virtual CPU

CPU Utilization Calculation

#!/bin/bash
# Calculate CPU utilization from /proc/stat
# Read twice, 1 second apart, calculate difference

cpu1=$(head -1 /proc/stat)
sleep 1
cpu2=$(head -1 /proc/stat)

# Parse fields
read -r _ user1 nice1 sys1 idle1 iow1 irq1 sirq1 steal1 _ _ <<< "$cpu1"
read -r _ user2 nice2 sys2 idle2 iow2 irq2 sirq2 steal2 _ _ <<< "$cpu2"

# Calculate deltas
idle_delta=$((idle2 - idle1))
total_delta=$(( (user2+sys2+nice2+idle2+iow2+irq2+sirq2+steal2) -
                (user1+sys1+nice1+idle1+iow1+irq1+sirq1+steal1) ))

# Calculate utilization
cpu=$((100 * (total_delta - idle_delta) / total_delta))
echo "CPU: ${cpu}%"

# Per-CPU calculation
for i in $(seq 0 $(($(nproc) - 1))); do
    cpu1=$(grep "^cpu$i " /proc/stat)
    sleep 1
    cpu2=$(grep "^cpu$i " /proc/stat)
    # ... same calculation ...
done

/proc/meminfo: Memory Statistics

cat /proc/meminfo
# MemTotal:       32768000 kB
# MemFree:         2048576 kB
# MemAvailable:   19922944 kB
# Buffers:          654320 kB
# Cached:         18234560 kB
# SwapCached:            0 kB
# Active:         12345678 kB
# Inactive:       18765432 kB
# Active(anon):    8234567 kB
# Inactive(anon):  1234567 kB
# Active(file):   12345678 kB
# Inactive(file): 18765432 kB
# Unevictable:      123456 kB
# Mlocked:          123456 kB
# SwapTotal:       8388608 kB
# SwapFree:        8388608 kB
# Dirty:            123456 kB
# Writeback:          1234 kB
# AnonPages:       8234567 kB
# Mapped:          2345678 kB
# Shmem:            567890 kB
# Slab:            1567890 kB
# SReclaimable:    1234567 kB
# SUnreclaim:       333323 kB
# KernelStack:       12345 kB
# PageTables:        34567 kB
# CommitLimit:    24772608 kB
# Committed_AS:   16234567 kB
# HugePages_Total:    1024
# HugePages_Free:      512
# HugePages_Rsvd:      256
# Hugepagesize:       2048 kB

Key Memory Metrics

FieldDescriptionHow to Interpret
MemTotalTotal usable RAMPhysical memory minus reserved
MemFreeCompletely unused RAMDon’t panic if low — Linux caches aggressively
MemAvailableMemory available for allocationsThe number to watch — includes reclaimable cache
BuffersBlock device buffer cacheMetadata for block devices
CachedPage cache (file data in RAM)Reclaimable under memory pressure
ActiveRecently used memoryHot pages
InactiveCandidate for reclaimCold pages
DirtyWaiting to be written to diskHigh = I/O bottleneck
WritebackCurrently being writtenActive I/O
SlabKernel slab allocator memoryKernel data structures
SReclaimableSlab memory that can be freedAvailable under pressure
AnonPagesAnonymous memory (heap, stack)Process memory
MappedMemory-mapped filesLibraries, mmap’d files
ShmemShared memory (tmpfs, shmem)Shared between processes
HugePages_TotalAllocated huge pagesFor databases, VMs
HugePages_FreeUnused huge pagesAvailable for allocation

Memory Usage Calculation

# Used memory (excluding cache/buffers)
grep -E "MemTotal|MemAvailable" /proc/meminfo
# MemTotal:       32768000 kB
# MemAvailable:   19922944 kB

# Used = MemTotal - MemAvailable
used=$((32768000 - 19922944))
echo "Used: ${used} kB"

# Percentage
pct=$((100 * used / 32768000))
echo "Usage: ${pct}%"

# Cache usage
grep -E "Cached|Buffers|SReclaimable" /proc/meminfo
# Cached:         18234560 kB
# Buffers:          654320 kB
# SReclaimable:    1234567 kB

# Swap usage
grep -E "SwapTotal|SwapFree" /proc/meminfo
# SwapTotal:       8388608 kB
# SwapFree:        8388608 kB

/proc/diskstats: Disk I/O Statistics

cat /proc/diskstats | grep sda
#   8 0 sda 123456 789 12345678 9012 567890 123 45678901 2345 0 6789 11357

Fields (14 columns)

# 1  major: Major device number
# 2  minor: Minor device number
# 3  name: Device name
# 4  reads_completed: Total reads completed
# 5  reads_merged: Reads merged (adjacent)
# 6  sectors_read: Total sectors read (512 bytes each)
# 7  read_time_ms: Total read time (ms)
# 8  writes_completed: Total writes completed
# 9  writes_merged: Writes merged
# 10 sectors_written: Total sectors written
# 11 write_time_ms: Total write time (ms)
# 12 io_in_progress: I/Os currently in progress
# 13 io_time_ms: Time doing I/Os (ms)
# 14 weighted_io_time_ms: Weighted I/O time (ms)

Calculating I/O Metrics

#!/bin/bash
# Calculate I/O metrics from /proc/diskstats
DEVICE="sda"

get_disk_stats() {
    grep " $DEVICE " /proc/diskstats
}

# Read twice, 1 second apart
stats1=$(get_disk_stats)
sleep 1
stats2=$(get_disk_stats)

# Parse fields
read -r _ _ _ r1 rm1 rs1 rt1 w1 wm1 ws1 wt1 io1 iot1 wiot1 <<< "$stats1"
read -r _ _ _ r2 rm2 rs2 rt2 w2 wm2 ws2 wt2 io2 iot2 wiot2 <<< "$stats2"

# IOPS = delta(reads + writes) / delta(time)
iops=$(( (r2 - r1 + w2 - w1) ))

# Throughput = delta(sectors * 512) / delta(time) in KB/s
throughput=$(( (rs2 - rs1 + ws2 - ws1) * 512 / 1024 ))

# Read latency = delta(read_time) / delta(read_count)
if [ $((r2 - r1)) -gt 0 ]; then
    read_lat=$(( (rt2 - rt1) / (r2 - r1) ))
else
    read_lat=0
fi

# Utilization = delta(io_time) / delta(wall_time) * 100
util=$(( (iot2 - iot1) / 10 ))

echo "IOPS: $iops | Throughput: ${throughput}KB/s | Read Latency: ${read_lat}ms | Utilization: ${util}%"

/proc/net: Network Statistics

# Network interface statistics
cat /proc/net/dev
# Inter-|   Receive                                                |  Transmit
#  face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo frame compressed
#   lo: 123456789 1234567    0    0    0     0          0         0 123456789 1234567    0    0    0     0       0         0
#  eth0: 12345678901 12345678 0 1234 0     0          0    123456 23456789012 23456789 0 567 0     0       0         0

# TCP connections
cat /proc/net/tcp | head -5
# sl  local_address rem_address   st tx_queue rx_queue ...
#  0: 00000000:0050 00000000:0000 0A 00000000:00000000
#  1: 0100007F:0035 00000000:0000 0A 00000000:00000000

# Socket statistics
cat /proc/net/sockstat
# sockets: used 1234
# TCP: inuse 567 orphan 12 tw 234 alloc 789 mem 1234
# UDP: inuse 234 mem 567
# UDPLITE: inuse 0
# RAW: inuse 0
# FRAG: inuse 0 memory 0

# TCP extended statistics
cat /proc/net/netstat | head -10
# TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed ...
# TcpExt: 0 0 0 ...

# SNMP counters
cat /proc/net/snmp | head -10
# Ip: Forwarding DefaultTTL InReceives InHdrErrors ...
# Ip: 1 64 123456789 0 ...

Network Troubleshooting with /proc/net

# Count connections by state
awk '{print $4}' /proc/net/tcp | sort | uniq -c | sort -rn
#  3456 01  # ESTABLISHED
#   234 06  # TIME_WAIT
#    56 08  # CLOSE_WAIT
#    12 0A  # LISTEN

# Find connections to specific port (e.g., 80 = 0050)
grep ":0050" /proc/net/tcp

# Check for socket buffer overflows
grep -E "TcpExt:.*Overflows" /proc/net/netstat
# TcpExt: ... TCPBacklogDrop ListenOverflows ListenDrops ...
# TcpExt: ... 0 0 0 ...

# Check for retransmissions
grep "Tcp:" /proc/net/snmp | tail -1
# Tcp: ... RetransSegs ...

/proc/sys: Kernel Parameters

# View all sysctl parameters
ls /proc/sys/
# abi/  debug/  dev/  fs/  kernel/  net/  vm/

# VM parameters
ls /proc/sys/vm/
# dirty_background_bytes    dirty_expire_centisecs  min_free_kbytes
# dirty_background_ratio    dirty_ratio             nr_hugepages
# dirty_bytes               dirty_writeback_centisecs  overcommit_memory
# vfs_cache_pressure        swappiness              overcommit_ratio

# Network parameters
ls /proc/sys/net/core/
# netdev_budget  netdev_max_backlog  rmem_max  somaxconn  wmem_max

# Kernel parameters
ls /proc/sys/kernel/
# pid_max  sched_latency_ns  sched_min_granularity_ns  threads-max

Key sysctl Parameters

# ──── Memory Management ────
cat /proc/sys/vm/swappiness
# 60 (0-100, lower = less swapping)

cat /proc/sys/vm/dirty_ratio
# 20 (percentage of memory allowed dirty before writeback)

cat /proc/sys/vm/overcommit_memory
# 0 (0=heuristic, 1=always, 2=strict)

cat /proc/sys/vm/min_free_kbytes
# 67584 (minimum free memory in KB)

# ──── Network ────
cat /proc/sys/net/core/somaxconn
# 4096 (max listen queue backlog)

cat /proc/sys/net/core/rmem_max
# 212992 (max receive buffer size)

cat /proc/sys/net/ipv4/tcp_max_syn_backlog
# 4096 (max SYN backlog)

cat /proc/sys/net/ipv4/ip_local_port_range
# 32768    60999 (ephemeral port range)

# ──── Kernel ────
cat /proc/sys/kernel/pid_max
# 4194304 (max PID value)

cat /proc/sys/kernel/threads-max
# 123456 (max threads system-wide)

cat /proc/sys/kernel/sched_latency_ns
# 6000000 (target scheduling latency)

Modifying Parameters

# Temporary (until reboot)
echo 10 > /proc/sys/vm/swappiness
echo 4096 > /proc/sys/net/core/somaxconn

# Permanent (via sysctl.conf)
echo "vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p

# Check current values
sysctl -a | grep swappiness
# vm.swappiness = 10

/proc Load Average and Uptime

# Load average
cat /proc/loadavg
# 5.67 4.32 3.21 4/1234 5678
# 1-min 5-min 15-min running/total last_pid

# Uptime
cat /proc/uptime
# 3628800.45 29030400.36
# uptime_seconds idle_seconds (across all CPUs)

# System boot time
date -d "$(awk '{print $1}' /proc/stat | grep btime | cut -d' ' -f2)"
# Mon Jul 22 10:00:00 CST 2026

/proc Interrupts and Softirqs

# Hardware interrupts
cat /proc/interrupts | head -5
#            CPU0       CPU1       CPU2       CPU3
#   1:         42         0         0         0   IO-APIC   2-edge      timer
#   8:          0         0         0         1   IO-APIC   8-edge      rtc0
#  16:   12345678   23456789   34567890   45678901   PCI-MSI  524289-edge  eth0

# Soft interrupts
cat /proc/softirqs | head -5
#                     CPU0       CPU1       CPU2       CPU3
#          HI:          42         56         78         90
#       TIMER:    12345678   23456789   34567890   45678901
#      NET_TX:    12345678   23456789   34567890   45678901
#      NET_RX:    12345678   23456789   34567890   45678901

# Check for interrupt imbalance
awk 'NR>1 && $2+$3+$4+$5 > 0 {print $1, $2+$3+$4+$5}' /proc/interrupts | sort -k2 -rn | head
# Shows which interrupts are most active

# Check for softirq pressure
awk 'NR>1 {sum=0; for(i=2;i<=NF;i++) sum+=$i; print $1, sum}' /proc/softirqs | sort -k2 -rn

/proc CPU Information

cat /proc/cpuinfo | head -20
# processor	: 0
# vendor_id	: GenuineIntel
# cpu family	: 6
# model		: 85
# model name	: Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz
# stepping	: 7
# microcode	: 0x5003604
# cpu MHz		: 2500.000
# cache size	: 27648 KB
# physical id	: 0
# siblings	: 16
# core id		: 0
# cpu cores	: 8
# apicid		: 0
# initial apicid	: 0
# fpu		: yes
# fpu_exception	: yes
# cpuid level	: 22
# wp		: yes
# flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr ...

# Count CPUs
grep -c processor /proc/cpuinfo
# 16

# Check CPU flags (features)
grep flags /proc/cpuinfo | head -1
# flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr ...

# Check for specific features
grep -o "sse4_2\|avx2\|avx512\|aes" /proc/cpuinfo | sort -u
# aes
# avx2
# sse4_2

# Check CPU vulnerabilities
grep . /sys/devices/system/cpu/vulnerabilities/*
# /sys/devices/system/cpu/vulnerabilities/meltdown: Mitigation: PTI
# /sys/devices/system/cpu/vulnerabilities/spectre_v1: Mitigation: ...
# /sys/devices/system/cpu/vulnerabilities/spectre_v2: Mitigation: ...
# /sys/devices/system/cpu/vulnerabilities/retbleed: Mitigation: ...

Practical Monitoring Scripts

Real-Time CPU Monitor

#!/bin/bash
# Simple CPU monitor reading /proc/stat
while true; do
    cpu1=$(head -1 /proc/stat)
    sleep 1
    cpu2=$(head -1 /proc/stat)

    idle1=$(echo $cpu1 | awk '{print $5}')
    idle2=$(echo $cpu2 | awk '{print $5}')
    total1=$(echo $cpu1 | awk '{s=0; for(i=2;i<=NF;i++) s+=$i; print s}')
    total2=$(echo $cpu2 | awk '{s=0; for(i=2;i<=NF;i++) s+=$i; print s}')

    idle=$((idle2 - idle1))
    total=$((total2 - total1))
    cpu=$((100 * (total - idle) / total))

    echo "$(date +%H:%M:%S) CPU: ${cpu}%"
done

Process Memory Monitor

#!/bin/bash
# Monitor process memory via /proc
PID=$1
if [ -z "$PID" ]; then
    echo "Usage: $0 <pid>"
    exit 1
fi

while true; do
    if [ -f /proc/$PID/status ]; then
        rss=$(grep VmRSS /proc/$PID/status | awk '{print $2}')
        vmsize=$(grep VmSize /proc/$PID/status | awk '{print $2}')
        threads=$(grep Threads /proc/$PID/status | awk '{print $2}')
        fd_count=$(ls /proc/$PID/fd 2>/dev/null | wc -l)
        echo "$(date +%H:%M:%S) RSS: ${rss}kB VSZ: ${vmsize}kB Threads: ${threads} FDs: ${fd_count}"
    else
        echo "Process $PID not found"
        break
    fi
    sleep 1
done

System Health Dashboard

#!/bin/bash
# Quick system health check from /proc
echo "=== System Health ==="
echo ""

# Load average
read load1 load5 load15 _ _ < /proc/loadavg
echo "Load: $load1 (1m) $load5 (5m) $load15 (15m)"

# Memory
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
mem_pct=$((100 * (mem_total - mem_avail) / mem_total))
echo "Memory: ${mem_pct}% used ($(( mem_avail / 1024 ))MB available)"

# Swap
swap_total=$(grep SwapTotal /proc/meminfo | awk '{print $2}')
swap_free=$(grep SwapFree /proc/meminfo | awk '{print $2}')
if [ $swap_total -gt 0 ]; then
    swap_pct=$((100 * (swap_total - swap_free) / swap_total))
    echo "Swap: ${swap_pct}% used"
fi

# Disk I/O (sda)
read _ _ _ r1 _ _ _ w1 _ _ _ _ _ _ < <(grep " sda " /proc/diskstats)
sleep 1
read _ _ _ r2 _ _ _ w2 _ _ _ _ _ _ < <(grep " sda " /proc/diskstats)
iops=$(( r2 - r1 + w2 - w1 ))
echo "Disk IOPS: $iops (sda)"

# Network (eth0)
read _ rx1 _ _ _ _ _ _ tx1 _ < <(grep "eth0:" /proc/net/dev | tr ':' ' ')
sleep 1
read _ rx2 _ _ _ _ _ _ tx2 _ < <(grep "eth0:" /proc/net/dev | tr ':' ' ')
rx_kb=$(( (rx2 - rx1) / 1024 ))
tx_kb=$(( (tx2 - tx1) / 1024 ))
echo "Network: RX ${rx_kb}KB/s TX ${tx_kb}KB/s"

# Process count
echo "Processes: $(ls -d /proc/[0-9]* 2>/dev/null | wc -l)"

# Uptime
uptime_secs=$(awk '{print int($1)}' /proc/uptime)
echo "Uptime: $((uptime_secs / 86400))d $((uptime_secs % 86400 / 3600))h"

Top Processes by Memory

#!/bin/bash
# Top 10 processes by RSS
echo "Top 10 processes by memory (RSS):"
echo "PID      RSS(kB)  VSZ(kB)  COMMAND"
for pid in /proc/[0-9]*; do
    p=$(basename $pid)
    if [ -f "$pid/status" ]; then
        rss=$(grep VmRSS $pid/status 2>/dev/null | awk '{print $2}')
        vsz=$(grep VmSize $pid/status 2>/dev/null | awk '{print $2}')
        cmd=$(cat $pid/comm 2>/dev/null)
        if [ -n "$rss" ]; then
            echo "$p $rss $vsz $cmd"
        fi
    fi
done | sort -k2 -rn | head -10 | column -t

Finding Memory Leaks

#!/bin/bash
# Monitor RSS growth for a process
PID=$1
INTERVAL=5
echo "Monitoring PID $PID for memory growth (Ctrl-C to stop)"
echo "Time         RSS(kB)    Growth"

prev_rss=0
while true; do
    if [ -f /proc/$PID/status ]; then
        rss=$(grep VmRSS /proc/$PID/status | awk '{print $2}')
        growth=$((rss - prev_rss))
        echo "$(date +%H:%M:%S)    $rss    +${growth}kB"
        prev_rss=$rss
    else
        echo "Process $PID exited"
        break
    fi
    sleep $INTERVAL
done

How Monitoring Tools Use /proc

Tool/proc Files Used
top/proc/stat, /proc/[pid]/stat, /proc/[pid]/status, /proc/meminfo
free/proc/meminfo
ps/proc/[pid]/stat, /proc/[pid]/status, /proc/[pid]/cmdline
vmstat/proc/stat, /proc/meminfo, /proc/diskstats
iostat/proc/diskstats
sar/proc/stat, /proc/meminfo, /proc/diskstats, /proc/net/dev
netstat/proc/net/tcp, /proc/net/tcp6, /proc/net/unix
ss/proc/net/tcp, /proc/net/tcp6, /proc/net/unix
lsof/proc/[pid]/fd/
pmap/proc/[pid]/maps, /proc/[pid]/smaps
uptime/proc/loadavg, /proc/uptime
nproc/proc/cpuinfo
df/proc/mounts

/proc for Security and Auditing

# Check process capabilities
cat /proc/1/status | grep Cap
# CapInh: 0000000000000000
# CapPrm: 0000003fffffffff
# CapEff: 0000003fffffffff
# CapBnd: 0000003fffffffff
# CapAmb: 0000000000000000

# Decode capabilities
capsh --decode=0000003fffffffff

# Check seccomp status
cat /proc/1/status | grep Seccomp
# Seccomp:    0 (disabled)
# Seccomp_filters:    0

# Check namespaces
ls -la /proc/1/ns/
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 cgroup -> 'cgroup:[4026531835]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 ipc -> 'ipc:[4026531839]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 mnt -> 'mnt:[4026531840]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 net -> 'net:[4026531969]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 pid -> 'pid:[4026531836]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 user -> 'user:[4026531837]'
# lrwxrwxrwx 1 root root 0 Jul 22 10:00 uts -> 'uts:[4026531838]'

# Check OOM score
cat /proc/1/oom_score
# 0

# Check cgroup membership
cat /proc/1/cgroup
# 0::/init.scope

# Audit: find processes with elevated capabilities
for pid in /proc/[0-9]*; do
    cap=$(grep CapEff $pid/status 2>/dev/null | awk '{print $2}')
    if [ "$cap" != "0000000000000000" ] && [ -n "$cap" ]; then
        echo "$(basename $pid): $(cat $pid/comm 2>/dev/null) CapEff=$cap"
    fi
done

References

Further Reading