在Linux中,如何确定进程正在使用多少内存?

85

我认为我的LAMP应用程序可能存在内存泄漏问题(内存被占用、开始使用交换空间等)。如果我可以看到各个进程正在使用多少内存,这可能有助于解决我的问题。在*nix系统中,有没有一种方法可以让我查看这些信息?


你能否更新问题,指明当时使用的操作系统?所选答案似乎在11年后不起作用了。啊,没事了。 - PatS
13个回答

100

获取正确的内存使用情况比人们想象的更加棘手。我所能找到的最好方法是:链接

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

在这里,“PROCESS”是你想要检查的进程名称,“TYPE”是以下之一:

  • Rss:常驻内存使用情况,包括该进程使用的所有内存以及与其他进程共享的所有内存。不包括交换空间;
  • Shared:该进程与其他进程共享的内存;
  • Private:该进程使用的私有内存,可以在此处查找内存泄漏;
  • Swap:该进程使用的交换内存;
  • Pss:比例集大小,是一个很好的总体内存指标。它是Rss调整后的共享值:如果一个进程具有1MiB的私有内存和20MiB共享内存,则Pss为1 + 20/10 = 3MiB

其他有效的值包括Size(即虚拟大小,几乎没有意义)和Referenced(当前标记或访问的内存量)。

您可以使用watch或其他bash脚本工具来监视您想要监视的进程的这些值。

有关smaps的更多信息,请参见:http://www.kernel.org/doc/Documentation/filesystems/proc.txt


这很棒,但它似乎以KB为单位返回内存(至少对于Rss和Private而言)。你知道如何以字节为单位获取内存吗? - Matt Phillips
5
可能已经过了很久并且不再相关,但是:实际的内存分配总是物理页面大小的倍数,在现代系统上,物理页面大小始终是1024字节的小倍数。因此,只需将KB大小乘以1024即可得到字节数;没有舍入误差。(内核大多数情况下没有受到iB疾病的影响:除非有明确的证据表明相反,否则假设K = 1024而不是1000。) - zwol
1
你可以只用 awk 命令来实现 cat+grep+awk+sed 操作: echo 0 $(sudo awk '/TYPE/ {print "+", $2}' /proc/PID/smaps) | bc - Bryan
同一程序(例如Chrome)有多个实例运行时,它将无法正常工作。 - Calmarius
4
为什么不直接使用awk来代替传递给bc呢?在/proc/PID/smaps文件中执行如下命令awk 'BEGIN { used=0 }; /TYPE/ { used += $2 } END { print used }' 将会以KB为单位输出所需的大小。请注意,此翻译已经尽可能简化和通俗易懂,但保留了原始意思,没有提供任何额外的解释或信息。 - Glen Solsberry
显示剩余5条评论

73
我不知道为什么答案看起来这么复杂...使用ps似乎很简单:
mem()
{                                                                                                      
    ps -eo rss,pid,euser,args:100 --sort %mem | grep -v grep | grep -i $@ | awk '{printf $1/1024 "MB"; $1=""; print }'
}

示例用法:

$ 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

3
很棒的函数使用。我已将其添加到我的.zshrc文件中。 - watzon
方便的函数。值得注意的是,用于计算(Resident Set Size)的“rss”列包括共享库中的内存,因此会使数字偏离。在我的情况下,进程使用的内存超过了系统可用的内存。 - AlexT
1
这是答案,不知道为什么其他的被标记为正确,我从中得到的结果只有“0”,而这个则完全展示了我所需要的... 谢谢你 - THESorcerer
1
这是正确的答案,在Linux上完美运行。 - LnxSlck
对于MacOS,我不得不使用以下内容(删除args:100--sort %mem选项):mem() { ps -ef -o rss,pid,user | grep -v grep | grep -i "$@" | awk '{printf $1/1024 "MB"; $1=""; print }' }``` - Bryan
1
我进行了修改以包括以千字节为单位的虚拟内存大小。还将数字格式化为固定宽度,因此结果更容易比较。我还将行长度截断为110个字符,但您可以传递第二个参数以使行更长(显示更多参数)。解决方案是:`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

42
使用ps命令查找应用程序的进程ID,然后使用top -p1010(将1010替换为实际的进程ID)。 RES列是已使用的物理内存,VIRT列是已使用的虚拟内存-包括库和交换内存。
更多信息可以使用"man top"找到。

1
当我执行 top -pXXXX 时,进程已经完成了。所以我什么也得不到。有什么建议吗? - StackOverflowNewbie
3
关于"VIRT": 对于几乎所有实际目的来说,虚拟镜像的大小并不能告诉你什么 - 几乎每个Linux系统都配置为允许过度提交内存,很多应用程序实际上会进行重度过度提交。 - Gunther Piez
这是一个一行代码,允许您指定进程的名称(假设只有一个进程与该名称匹配):top -p\ps -ef | grep -i $NAME_OF_PROCESS | grep -v grep | gawk '{print $2}'``。 - Trevor Boyd Smith
$ top -p $(pgrep <您的进程名称> | xargs | tr ' ' ',') - AAAfarmclub

20

首先获取pid:

ps ax | grep [process name]

然后:

top -p PID
你可以同时观看多个进程:
top -p PID1 -p PID2 

14

您可以使用 pmap 命令来报告内存使用情况。

概要:

pmap [ -x | -d ] [ -q ] pids... 

2
不错,这里是一个使用示例: pmap $(pgrep -f -u username /usr/bin/gnome-shell)| sed -n -e 's/ total \+//p' | numfmt --from=iec 1724678144 - TiCPU

10

如果您没有需要跟踪的当前或长时间运行的进程,您可以使用/usr/bin/time

这与Bash的time不同(如您所见)。

例如:

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

2028

这是“进程在其生命周期中的最大常驻集大小,以千字节为单位”(引自手册页)。也就是说,与top等中的RES相同。

/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

2
macOS的/usr/bin/time不支持这个级别的分析,但是通过gnu-time软件包,Homebrew提供了正确的工具。它安装了一个叫做gtime的实用程序,可以完成你所说的功能。 - voxobscuro

8

更优雅的方法:

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

6
感谢您。我使用这个来创建一个简单的bash脚本,可以用来监视一个进程及其内存使用情况: $ 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 "=================";

很可能是因为该脚本通过5次对smaps文件的遍历来计算数据。使用awk进行解析和计算一次遍历应该相对容易。 - Timothée Groleau
@TimothéeGroleau 赞同 awk 的性能。总之脚本看起来很赞,对此可以学到一些东西。也许Paul Rubenstein想更新他们的脚本:D. 谢谢。 - m3nda

6

使用 tophtop 命令,并关注 "RES" (驻留内存大小) 列。


我看到了RES,但我不认为我需要它。我的已用内存和已用交换空间一直在增加。我需要知道是什么导致了这些增加。有什么想法吗? - StackOverflowNewbie
驻留内存是您的进程使用的内存。如果您的总内存使用量增加,但似乎没有任何进程使用太多内存,则该内存可能仅由内核使用。尝试按RES列进行排序。另一个可能是当您有大量磁盘IO时交换过高的点。 - Gunther Piez
htop -t 显示树形视图中的进程,因此您可以在树形视图中查看 RES 内存。 - oml

5
你需要的工具是 ps。 获取有关 Java 程序正在执行的信息:
ps -F -C java 

获取有关http的信息:

ps -F -C httpd

如果您的程序在运行这些命令之前就结束了,请打开另一个终端并运行:

while true; do ps -F -C myCoolCode ; sleep 0.5s ; done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接