get swap usage for a process

I'm looking for a way, from a shell script, to get the swap usage for a particular process. Top can show this information, but only in interactive mode. Batch mode will only show customizations when a .toprc is present, but you can't specify a specific .toprc on the command-line. I found this script, but there are no swap entries in /proc/*/smaps on my server:

# find /proc/ -maxdepth 1 -type d -regex '^/proc/[0-9]+$' -exec grep -Hi swap '{}'/smaps \;
#

so the script just outputs 0 for every process.

Is there a way to find this information? I'm on RHEL5.1 2.6.18-53.el5 x86_64.

Edit:

To be clear, when I ask about "swap usage", I mean the amount of memory used by a process that has been paged out to the swap filesystem (what is not currently sitting in main memory). Assuming no better way, I'm going to default to calculating it with (virtual - rss) via the values from ps -o vsz,rss.


Solution 1:

An interesting question that had me scratching my head for a while.

First, why you have no Swap line: though in theory that was added in kernel 2.6.16, it didn't show up in RHEL until 5.3 or so (kernel 2.6.18-99.el5). Here is the commit (unfortunately not accessible in the RH Bugzilla; if you happen to have an account with appropriate privileges, the Bugzilla id is 443749). http://sophie2.aero.jussieu.fr/distrib/Scientific%20Linux/5x/i386/by-pkgid/351d529f9beeb4e5d936a6d5e3e7813a/files/645

Second, this implies that the top data is unreliable since it is not reading from the smaps (i.e. it is virt - res):

    case P_SWP:
       MKCOL(scale_num(PAGES_TO_KB(p->size - p->resident), w, s));

Third, I regret to say that the kernel is the One True Oracle on how much swap is used, and as far as I can tell the various patches to make the information available in smaps and status are the only way to expose that information. Unfortunately, I see updating your kernel as the only way to get accurate information; either by patching the source yourself (sample patch, no warranty) or updating to kernel 2.6.18-99.el5.

I wish there were an easier answer; blame Linus.

Solution 2:

Look in /proc/<pid>/status. You'll see a VmSwap line.