## 24.9. The /proc Filesystem

In Unix, it seems almost everything can be treated like a file (Section 1.19). On many modern Unix systems, even processes are files -- well, sort of. A special filesystem named /proc doesn't actually "contain" processes, but it lets you interact with them. Almost all of the "files" in /proc are plain text, so you can access them from scripts and programs, as well as from the command line. Of the systems I've checked, my Red Hat Linux 6.2 box (kernel version 2.2) seems to have the most in /proc, so I'll cover it. Please check your documentation -- a proc(5) manual page, for instance -- for the story on your system.

All /proc filesystems have one subdirectory for each process currently running on the system. Each of those process subdirectories is named for its PID (Section 24.3). Some versions of /proc also have other named files and subdirectories -- and my system has a lot of them. Here's a partial listing of my /proc filesystem at the moment; I've left out a lot of the numbered subdirectories:

`-F` Section 8.10

>     $ ls -F /proc
>     1/        17415/    467/      cmdline      ksyms        pci
>     1047/     2/        482/      cpuinfo      loadavg      rtc
>     1052/     3/        5/        devices      locks        scsi/
>     1057/     345/      553/      dma          mdstat       self@
>     1287/     370/      593/      fb           meminfo      slabinfo
>     1289/     379/      594/      filesystems  misc         stat
>     14288/    393/      595/      fs/          modules      swaps
>     14289/    4/        596/      ide/         mounts       sys/
>     17409/    4017/     597/      interrupts   mtrr         tty/
>     17412/    407/      6/        ioports      net/         uptime
>     17413/    425/      apm       kcore        partitions   version
>     17414/    439/      bus/      kmsg

Linux system utilities like ps and pidof use information from /proc. Your programs can use it, too; there are some examples below. But it's also useful when you want to know something about your system. The "files" in /proc are most useful there. Let's look at a series of examples. We'll end with the numbered per-process "directories."

### 24.9.1. Memory Information

The Linux free(1) utility shows your memory status. It simply reads the file /proc/meminfo and reformats the information. If you want an alias (Section 29.2) that simply shows how much memory is free, it's probably simpler to read the meminfo file directly. For example:

`grep` Section 13.1

>     $ cat /proc/meminfo
>             total:    used:    free:  shared: buffers:  cached:
>     Mem:  263929856 253022208 10907648 79675392 30797824 57868288
>     Swap: 394784768 14585856 380198912
>     MemTotal:    257744 kB
>     MemFree:      10652 kB
>     MemShared:    77808 kB
>     Buffers:      30076 kB
>     Cached:       56512 kB
>     BigTotal:         0 kB
>     BigFree:          0 kB
>     SwapTotal:   385532 kB
>     SwapFree:    371288 kB
>     $ alias memfree='grep Free: /proc/meminfo'
>     $ memfree
>     MemFree:      10616 kB
>     BigFree:          0 kB
>     SwapFree:    371288 kB

(The free RAM decreased a bit while I was writing the alias.)

### 24.9.2. Kernel and System Statistics

The /proc/stat file has statistics on the kernel and system. As with most of the rest of /proc, it's updated constantly. For example, we can grep for the CPU statistics. The four fields on the `cpu` line show the number of jiffies (hundredths of a second) since the system was last rebooted: time spent in normal-priority user mode, niced user mode (Section 26.5), system (kernel) mode, and the idle task, respectively. You might want to use this information from a script that monitors your system's utilization. Here's an example: grepping for the CPU ststistics, then the start of an awk (Section 20.10) script that could watch the CPU usage:

`!!` Section 30.8

>     $ grep cpu /proc/stat
>     cpu  14693561 48135949 638573 4031301
>     $ awk '/^cpu/ { print $5 / 100 " seconds idle" }' /proc/stat
>     40318.7 seconds idle
>     $ !!
>     awk '/^cpu/ { print $5 / 100 " seconds idle" }' /proc/stat
>     40323.8 seconds idle

### 24.9.3. Statistics of the Current Process

The sections below describe per-process subdirectories in /proc. One special directory is /proc/self. It has the unusual property of giving a different answer for every process that examines it: information about the current process. (This "directory" is actually a symbolic link (Section 10.4) to the directory numbered for the process' PID.)

For instance, a process can check its /proc/self/fd directory to see which files its file descriptors (Section 36.15) are currently pointing to. This isn't just what type of file (disk file, tty (Section 2.7), pipe, etc.) but the actual full pathname of the file. If you're new to Unix, this may not seem too earth-shaking, but it's actually pretty amazing.

For a simple example, here's a shell script that lists its input and outputs. It then redirects its standard input (file descriptor 0) from /dev/null (Section 43.12) and lists again.

>     $ pwd
>     /tmp
>     $ tty
>     /dev/pts/5
>     $ cat showfds
>     #!/bin/sh
>     cd /proc/self/fd
>     ls -l
>     exec 0</dev/null
>     ls -l
>     $ ./showfds < somefile
>     total 0
>     lr-x------    1 jpeek    jpeek     64 Dec  2 09:03 0 -> /tmp/somefile
>     lrwx------    1 jpeek    jpeek     64 Dec  2 09:03 1 -> /dev/pts/5
>     lrwx------    1 jpeek    jpeek     64 Dec  2 09:03 2 -> /dev/pts/5
>     lr-x------    1 jpeek    jpeek     64 Dec  2 09:03 3 -> /tmp/showfds
>     total 0
>     lr-x------    1 jpeek    jpeek     64 Dec  2 09:03 0 -> /dev/null
>     lrwx------    1 jpeek    jpeek     64 Dec  2 09:03 1 -> /dev/pts/5
>     lrwx------    1 jpeek    jpeek     64 Dec  2 09:03 2 -> /dev/pts/5
>     lr-x------    1 jpeek    jpeek     64 Dec  2 09:03 3 -> /tmp/showfds

### 24.9.4. Statistics of Processes by PID

All versions of /proc that I've seen have subdirectories named for each process currently running on the system. Each subdirectory is named for the process PID (Section 24.3). Here are a series of examples of the useful info on my Linux system:

Go to http://examples.oreilly.com/upt3 for more information on: showenv

- You can use printenv or env (Section 35.3) to find the environment of your current process. How about the environment of another process? Here's a shell script called showenv that works like printenv:

  >     #!/bin/sh
  >     # showenv - show environment of a process, by PID
  >     # If second argument given, show just that one environment variable.

  >     f=/proc/$1/environ

  >     if [ ! -r "$f" ]; then
  >         echo "`basename $0`: can't access process $1" 1>&2
  >         exit 1
  >     fi

  >     case $# in
  >     1) tr '\000' '\012' < $f | sort ;;
  >     2) tr '\000' '\012' < $f | grep "^$2=" ;;
  >     *) echo "Usage: `basename $0` pid [envariable-name]" 1>&2; exit 1 ;;
  >     esac

  The tr (Section 21.11) command translates the NUL-separated entries from the environ file into newline-separated lines. With one argument, the whole environment is shown. With two arguments, the script greps for the environment variable named in the second argument. Maybe you'd like to know what the EXINIT (Section 17.27) environment variable was set to in a vi process with PID 8984:

  >     $ showenv 8984
  >     DISPLAY=:0.0
  >     ECIINI=/usr/lib/ViaVoiceTTS/eci.ini
  >     EDITOR=vi
  >     EXINIT=so ~/.lib/vi/exrc8
  >     HISTFILESIZE=1000
  >       ...
  >     $ showenv 8984 EXINIT
  >     EXINIT=so ~/.lib/vi/exrc8

- The status file gives status information about the process. A lot of this information is available in ps (Section 24.5) output, but it's broken out nicely here. For instance, maybe you're wondering what group access process 918 has, or what process started it (its parent PID (Section 24.3)):

  >     % cd /proc/918
  >     % grep PPid status
  >     PPid:   916
  >     % grep Groups status
  >     Groups: 1000 501 103

  The PPID is 916. The process has the group numbers (can access resources with the group permissions of) GIDs 1000, 501, and 103.

- The command-line arguments of a process are in the cmdline file, separated by NUL characters. Hmmm, what files is that tail -f job, process 861, watching? Let's see...using echo (Section 27.5) to add a final newline:

`;` Section 28.16

>     $ tr '\000' ' ' < /proc/861/cmdline; echo
>     tail -f /var/log/messages /var/log/maillog /u/jerry/tmp/startx.log

### 24.9.5. A Glimpse at Hardware

If you are curious about your system's hardware, a quick look at /proc/cpuinfo, /proc/interrupts, and /proc/ioports will help you size up the system. All the following examples came from a Red Hat Linux box, but you will find these proc files on most Linux and BSD systems. For instance, /proc/cpuinfo looks like this (on my system):

>     processor: 0
>     vendor_id: GenuineIntel
>     cpu family: 6
>     model: 6
>     model name: Celeron (Mendocino)
>     stepping: 0
>     cpu MHz: 400.918
>     cache size: 128 KB
>     fdiv_bug: no
>     hlt_bug: no
>     f00f_bug: no
>     coma_bug: no
>     fpu: yes
>     fpu_exception: yes
>     cpuid level: 2
>     wp: yes
>     flags: fpu vme de pse tsc msr pae mce cx8 sep mtrr pat pse36 mmx fxsr
>     bogomips: 799.53

The most important fields to notice are `processor`, `model name`, and `cpu MHz` since these identify how many CPUs are in the system, the model name (although this isn't always so clear in older Pentium models), and the CPU speed of your machine.

The other three proc files are important if you are installing hardware or trying to configuring recently installed hardware. /proc/interrupts lists the hardware interrupt numbers and shows which devices are using which interrupt. On my machine, this looks like:

>                CPU0
>       0:   92887036          XT-PIC  timer
>       1:     910141          XT-PIC  keyboard
>       2:          0          XT-PIC  cascade
>       3:          4          XT-PIC  serial
>       5:    4794267          XT-PIC  eth0
>       8:   11642728          XT-PIC  rtc
>      10:   65248789          XT-PIC  es1371
>      11:          0          XT-PIC  usb-uhci
>      12:    5109157          XT-PIC  PS/2 Mouse
>      14:     560048          XT-PIC  ide0
>      15:     408739          XT-PIC  ide1
>     NMI:          0
>     ERR:          0

/proc/ioports lists the hardware I/O port ranges that all your systems devices use. This is a good file to examine if recently installed hardware can't be found in your drivers. Here's an abbreviated sample of my system's /proc/ioports.

>     03f6-03f6 : ide0
>     03f8-03ff : serial(auto)
>     0cf8-0cff : PCI conf1
>     4000-403f : Intel Corporation 82371AB PIIX4 ACPI
>     5000-501f : Intel Corporation 82371AB PIIX4 ACPI
>     c000-cfff : PCI Bus #01
>     d000-d01f : Intel Corporation 82371AB PIIX4 USB
>     d400-d43f : Ensoniq ES1371 [AudioPCI-97]
>     d800-d807 : Lucent Microelectronics 56k WinModem
>     dc00-dcff : Lucent Microelectronics 56k WinModem
>     e000-e0ff : PCI device 1186:1300 (D-Link System Inc)
>     f000-f00f : Intel Corporation 82371AB PIIX4 IDE

This file makes it easy to diagnosis hardware conflicts. However, if your system is working well, you probably won't be looking at any of these files much.

-- JP

Copyright © 2003 O'Reilly & Associates. All rights reserved.