85

I think I may have a memory leak in my LAMP application (memory gets used up, swap starts getting used, etc.). If I could see how much memory the various processes are using, it might help me resolve my problem. Is there a way for me to see this information in *nix?

StackOverflowNewbie
  • 39,403
  • 111
  • 277
  • 441
  • Can you update the question to indicate the OS that you were using at the time? The selected answer doesn't seem to work 11 years later. Ah, nevermind. – PatS May 04 '22 at 00:56

13 Answers13

100

Getting right memory usage is trickier than one may think. The best way I could find is:

echo 0 $(awk '/TYPE/ {print "+", $2}' /proc/`pidof PROCESS`/smaps) | bc

Where "PROCESS" is the name of the process you want to inspect and "TYPE" is one of:

  • Rss: resident memory usage, all memory the process uses, including all memory this process shares with other processes. It does not include swap;
  • Shared: memory that this process shares with other processes;
  • Private: private memory used by this process, you can look for memory leaks here;
  • Swap: swap memory used by the process;
  • Pss: Proportional Set Size, a good overall memory indicator. It is the Rss adjusted for sharing: if a process has 1MiB private and 20MiB shared between other 10 processes, Pss is 1 + 20/10 = 3MiB

Other valid values are Size (i.e. virtual size, which is almost meaningless) and Referenced (the amount of memory currently marked as referenced or accessed).

You can use watch or some other bash-script-fu to keep an eye on those values for processes that you want to monitor.

For more informations about smaps: http://www.kernel.org/doc/Documentation/filesystems/proc.txt.

Giuseppe Cardone
  • 5,323
  • 2
  • 24
  • 30
  • This is terrific, however it looks like it returns memory in KB (for Rss and Private anyway). Do you know how to get memory in bytes? – Matt Phillips Jun 20 '13 at 01:56
  • 5
    Ages later and probably not relevant anymore, but: actual memory allocation is always a multiple of the physical page size, which on modern systems is always a small multiple of 1024 bytes. So just multiply the size in KB by 1024 for bytes; there is no rounding error. (The kernel has mostly not caught the iB disease: unless there is clear evidence to the contrary, assume K = 1024 not 1000.) – zwol Sep 17 '13 at 16:44
  • What would be the "total" memory consumed for a scenario such as this: https://gist.github.com/9bbd0ce953143b67c038 ? – ylluminate Jun 13 '14 at 22:39
  • 1
    You can do the cat+grep+awk+sed with just awk: `echo 0 $(sudo awk '/TYPE/ {print "+", $2}' /proc/PID/smaps) | bc` – Bryan Mar 09 '15 at 15:38
  • It does not work when multiple instances of the same program (eg. chrome) are running. – Calmarius Aug 28 '15 at 17:42
  • If you substitute: `\`pidof PROCESS\`` with the actual PID, it will review a single process's RAM usage. – UtahJarhead Feb 08 '16 at 21:44
  • An enhancement top `ps -ef | grep -i $NAME_OF_PROCESS | grep -v grep | gawk '{print "-p "$2 }'` – Anup Ash Oct 21 '16 at 15:38
  • You do not need to sum it up in most cases its summed up for you /proc/[pid]/status – A. Binzxxxxxx Jul 11 '17 at 09:41
  • 4
    Why not do it all in `awk` instead of passing to `bc`? `awk 'BEGIN { used=0 }; /TYPE/ { used += $2 } END { print used }' /proc/PID/smaps` will give you the size in KB. – Glen Solsberry Nov 28 '17 at 16:43
  • If this doesn't work for you, try the answer the defines the `mem` shell function. That is the answer that worked for me. See https://stackoverflow.com/a/20277787/3281336 – PatS May 04 '22 at 16:27
73

I don't know why the answer seem so complicated... It seems pretty simple to do this with ps:

mem()
{                                                                                                      
    ps -eo rss,pid,euser,args:100 --sort %mem | grep -v grep | grep -i $@ | awk '{printf $1/1024 "MB"; $1=""; print }'
}

Example usage:

$ mem mysql
0.511719MB 781 root /bin/sh /usr/bin/mysqld_safe
0.511719MB 1124 root logger -t mysqld -p daemon.error
2.53516MB 1123 mysql /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
Greg Slepak
  • 1,613
  • 16
  • 17
  • 3
    Awesome use of a function. Added this one to my `.zshrc` – watzon Oct 21 '17 at 00:01
  • Handy function. It's worth noting that the `rss` column used for the calculation (Resident Set Size) includes memory from shared libraries, so will throw the numbers off. In my case, the processes were using more memory than the system had available. – AlexT Feb 16 '18 at 05:13
  • 1
    this is the answer, dunno why the other was marked as correct, all I get from it is the result "0", this one show exactly what I need ... **Thank YOU** – THESorcerer Feb 27 '18 at 21:04
  • 1
    This is the right answer, works flawlessly on Linux – LnxSlck Dec 29 '20 at 21:08
  • For MacOS, I had to use the following (removing the `args:100` and `--sort %mem` options): ```# utiltiy function to get memory usage mem() { ps -ef -o rss,pid,user | grep -v grep | grep -i "$@" | awk '{printf $1/1024 "MB"; $1=""; print }' }``` – Bryan Apr 28 '21 at 10:44
  • 1
    I modified it to include **virtual memory size in KiB. Also format numbers in fixed width so results are easier to compare. I also truncate the line length to 110 chars but you can pass a 2nd argument to make line longer (shows more of arguments). The solution is: `mem() { maxLineLen=${2:-110} ps -eo rss,vsz,pid,euser,args --sort %mem | grep -v grep | grep -i $1 | cut -c -$maxLineLen | awk '{printf("%9.2fMB %9.2fMB", $1/1024, $2/1024); $1=""; $2=""; print }' } ` – PatS May 04 '22 at 16:34
42

Use ps to find the process id for the application, then use top -p1010 (substitute 1010 for the real process id). The RES column is the used physical memory and the VIRT column is the used virtual memory - including libraries and swapped memory.

More info can be found using "man top"

Zaz
  • 3,017
  • 2
  • 21
  • 28
  • 1
    by the time I can execute top -pXXXX, the process is already done. So, I get nothing. Suggestions? – StackOverflowNewbie Oct 04 '10 at 08:56
  • 3
    Regarding "VIRT": For almost all practical purposes, the size of the virtual image tells you nothing - almost every linux system is configured to allow overcomitting of memory and a lot of apps actually do heavy overcommit. – Gunther Piez Oct 04 '10 at 10:15
  • Here's a one liner that allows you to specify the name of the process (assumes there is only one process that matches the name): `top -p\`ps -ef | grep -i $NAME_OF_PROCESS | grep -v grep | gawk '{print $2}'\`` – Trevor Boyd Smith Aug 06 '13 at 15:28
  • $ top -p $(pgrep | xargs | tr ' ' ',') – AAAfarmclub Aug 22 '15 at 21:50
20

First get the pid:

ps ax | grep [process name]

And then:

top -p PID

You can watch various processes in the same time:

top -p PID1 -p PID2 
Peter
  • 5,138
  • 5
  • 29
  • 38
14

You can use pmap to report memory usage.

Synopsis:

pmap [ -x | -d ] [ -q ] pids... 
Chuck Vose
  • 4,560
  • 24
  • 31
Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
  • 2
    Nice one, here is an example usage: `pmap $(pgrep -f -u username /usr/bin/gnome-shell) | sed -n -e 's/ total \+//p' | numfmt --from=iec` 1724678144 – TiCPU Feb 28 '16 at 21:42
10

In case you don't have a current or long running process to track, you can use /usr/bin/time.

This is not the same as Bash time (as you will see).

Eg

# /usr/bin/time -f "%M" echo

2028

This is "Maximum resident set size of the process during its lifetime, in Kilobytes" (quoted from the man page). That is, the same as RES in top et al.

There are a lot more you can get from /usr/bin/time.

# /usr/bin/time -v echo

Command being timed: "echo"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 1988
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 77
Voluntary context switches: 1
Involuntary context switches: 0
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
Bell
  • 445
  • 4
  • 13
  • 2
    The macos /usr/bin/time is not capable of this level of analysis, but homebrew does provide the correct utility through the `gnu-time` package. It installs a utility called `gtime` which does what you talk about. – voxobscuro Jul 16 '18 at 16:09
8

More elegant approach:

echo "Memory usage for PID <>:"; for mem in {Private,Rss,Shared,Swap,Pss};do grep $mem /proc/<pid>/smaps | awk -v mem_type="$mem" '{i=i+$2} END {print mem_type,"memory usage:"i}' ;done
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
user3707180
  • 81
  • 1
  • 1
6

Use top or htop and pay attention to the "RES" (resident memory size) column.

Gunther Piez
  • 29,760
  • 6
  • 71
  • 103
  • I see the RES, but I don't think I need that. My used Mem and used Swap keeps going up. I need to know what's making those go up. Ideas? – StackOverflowNewbie Oct 04 '10 at 08:57
  • Resident memory is the memory used by your processes. If none of the processes seems to be using much memory in spite of your total memory usage increasing, the memory could only be used by the kernel. Try sorting after the RES column. Another point maybe too high swappiness when you have heavy disk IO. – Gunther Piez Oct 04 '10 at 10:12
  • htop -t shows processes in tree view, so you can see the RES memory in tree view. – oml Jun 16 '20 at 20:45
6

Thanks. I used this to create this simple bash script that can be used to watch a process and its memory usage:

$ watch watchmypid.sh

#!/bin/bash
#

PROCESSNAME=changethistoyourprocessname
MYPID=`pidof $PROCESSNAME`

echo "=======";
echo PID:$MYPID
echo "--------"
Rss=`echo 0 $(cat /proc/$MYPID/smaps  | grep Rss | awk '{print $2}' | sed 's#^#+#') | bc;`
Shared=`echo 0 $(cat /proc/$MYPID/smaps  | grep Shared | awk '{print $2}' | sed 's#^#+#') | bc;`
Private=`echo 0 $(cat /proc/$MYPID/smaps  | grep Private | awk '{print $2}' | sed 's#^#+#') | bc;`
Swap=`echo 0 $(cat /proc/$MYPID/smaps  | grep Swap | awk '{print $2}' | sed 's#^#+#') | bc;`
Pss=`echo 0 $(cat /proc/$MYPID/smaps  | grep Pss | awk '{print $2}' | sed 's#^#+#') | bc;`

Mem=`echo "$Rss + $Shared + $Private + $Swap + $Pss"|bc -l`

echo "Rss     " $Rss
echo "Shared  " $Shared
echo "Private " $Private
echo "Swap    " $Swap
echo "Pss     " $Pss
echo "=================";
echo "Mem     " $Mem
echo "=================";
  • likely because the script computes the data with 5 passes through of the smaps file. It should be reasonably easy to have awk do parsing and computation in one pass. – Timothée Groleau Jun 24 '13 at 03:47
  • @TimothéeGroleau Agree with awk to performance, anyway the script looks cool and someone can learn a bit from it. Maybe Paul Rubenstein wanna update their script :D. Thanks. – m3nda May 22 '15 at 07:10
5

The tool you want is ps. To get information about what java programs are doing:

ps -F -C java 

To get information about http:

ps -F -C httpd

If your program is ending before you get a chance to run these, open another terminal and run:

while true; do ps -F -C myCoolCode ; sleep 0.5s ; done
Brian C.
  • 6,455
  • 3
  • 32
  • 42
4

You can use pmap + awk.

Most likely, we're interested in the RSS memory which is the 3rd column in the last line of the example pmap output below (82564).

$ pmap -x <pid>

Address           Kbytes     RSS   Dirty Mode   Mapping

....

00007f9caf3e7000       4       4       4 r----  ld-2.17.so
00007f9caf3e8000       8       8       8 rw---  ld-2.17.so
00007fffe8931000     132      12      12 rw---    [ stack ]
00007fffe89fe000       8       8       0 r-x--    [ anon ]
ffffffffff600000       4       0       0 r-x--    [ anon ]
----------------  ------  ------  ------
total kB          688584   82564    9592

Awk is then used to extract that value.

$ pmap -x <pid> | awk '/total/ { print $4 "K" }'

The pmap values are in kilobytes. If we wanted it in megabytes, we could do something like this.

$ pmap -x <pid> | awk '/total/ { print $4 / 1024 "M" }'
Ilia Choly
  • 18,070
  • 14
  • 92
  • 160
2

Why all these complicated answers with various shell scripts? Use htop, it automatically changes the sizes and you can select which info you want shown and it works in the terminal, so it does not require a desktop. Example: htop -d8

  • Most people using the command line are interested in figuring it out programmatically. In some cases, they simply want to learn how to figure it out using the kernel instead of a prebuild process. – UtahJarhead Feb 08 '16 at 21:45
1

Use

  • ps u `pidof $TASKS_LIST` or ps u -C $TASK
  • ps xu --sort %mem
  • ps h -o pmem -C $TASK

Example:

ps-of()
{
 ps u `pidof "$@"`
}

$ ps-of firefox
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
const    18464  5.9  9.4 1190224 372496 ?      Sl   11:28   0:33 /usr/lib/firefox/firefox

$ alias ps-mem="ps xu --sort %mem | sed -e :a -e '1p;\$q;N;6,\$D;ba'"
$ ps-mem 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
const     3656  0.0  0.4 565728 18648 ?        Sl   Nov21   0:56 /usr/bin/python /usr/lib/ubuntuone-client/ubuntuone-syncdaemon
const    11361  0.3  0.5 1054156 20372 ?       Sl   Nov25  43:50 /usr/bin/python /usr/bin/ubuntuone-control-panel-qt
const     3402  0.0  0.5 1415848 23328 ?       Sl   Nov21   1:16 nautilus -n
const     3577  2.3  2.0 1534020 79844 ?       Sl   Nov21 410:02 konsole
const    18464  6.6 12.7 1317832 501580 ?      Sl   11:28   1:34 /usr/lib/firefox/firefox

$ ps h -o pmem -C firefox
12.7
Costa
  • 461
  • 7
  • 13