【问题标题】:In Linux, how to tell how much memory processes are using?在 Linux 中,如何判断进程正在使用多少内存?
【发布时间】:2011-04-20 16:47:28
【问题描述】:

我认为我的 LAMP 应用程序中可能存在内存泄漏(内存已用完,swap 开始使用等)。如果我能看到各种进程正在使用多少内存,它可能会帮助我解决我的问题。有没有办法让我在 *nix 中看到这些信息?

【问题讨论】:

    标签: linux unix memory-leaks memory-management


    【解决方案1】:

    正确使用内存比人们想象的要棘手。最好的办法我could find is

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

    其中“PROCESS”是您要检查的进程的名称,“TYPE”是以下之一:

    • Rss:常驻内存使用,进程使用的所有内存,包括该进程与其他进程共享的所有内存。它不包括交换;
    • Shared:该进程与其他进程共享的内存;
    • Private:该进程使用的私有内存,可以在这里查找内存泄漏;
    • Swap:进程使用的交换内存;
    • Pss:Proportional Set Size,一个很好的整体内存指标。为共享调整的 Rss:如果一个进程有 1MiB 私有和 20MiB 在其他 10 个进程之间共享,则 Pss 为 1 + 20/10 = 3MiB

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

    您可以使用watch 或其他一些 bash-script-fu 来关注您想要监控的进程的这些值。

    更多关于smaps的信息:http://www.kernel.org/doc/Documentation/filesystems/proc.txt

    【讨论】:

    • 这太棒了,但看起来它以 KB 为单位返回内存(无论如何对于 Rss 和 Private)。你知道如何以字节为单位获取内存吗?
    • 年代久远,可能不再相关,但是:实际内存分配始终是物理页面大小的倍数,在现代系统上始终是 1024 字节的小倍数。所以只需将 KB 的大小乘以 1024 字节即可;没有舍入误差。 (内核大多没有感染 iB 病:除非有明确的相反证据,否则假设 K = 1024 而不是 1000。)
    • 这样的场景消耗的“总”内存是多少:gist.github.com/9bbd0ce953143b67c038
    • 你可以只用 awk 执行 cat+grep+awk+sed:echo 0 $(sudo awk '/TYPE/ {print "+", $2}' /proc/PID/smaps) | bc
    • 为什么不在awk 中全部完成,而不是传递给bcawk 'BEGIN { used=0 }; /TYPE/ { used += $2 } END { print used }' /proc/PID/smaps 将为您提供以 KB 为单位的大小。
    【解决方案2】:

    我不知道为什么答案看起来如此复杂...用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
    

    【讨论】:

    • 一个很棒的功能使用。将此添加到我的.zshrc
    • 方便的功能。值得注意的是,用于计算的rss 列(驻留集大小)包括来自共享库的内存,因此会将数字丢弃。在我的情况下,进程使用的内存比系统可用的内存多。
    • 这是答案,不知道为什么另一个被标记为正确,我从中得到的只是结果“0”,这正是我需要的...... 谢谢
    • 这是正确的答案,在 Linux 上完美运行
    • 对于 MacOS,我必须使用以下内容(删除 args:100--sort %mem 选项):# 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 }' }
    【解决方案3】:

    使用ps 查找应用程序的进程ID,然后使用top -p1010(将1010 替换为真正的进程ID)。 RES 列是使用的物理内存,VIRT 列是使用的虚拟内存 - 包括库和交换内存。

    可以使用“man top”找到更多信息

    【讨论】:

    • 当我可以执行 top -pXXXX 时,该过程已经完成。所以,我什么也得不到。有什么建议吗?
    • 关于“VIRT”:对于几乎所有的实际目的,虚拟映像的大小什么都不会告诉你——几乎每个 linux 系统都配置为允许内存过度使用,并且许多应用程序实际上会过度使用。
    • 这是一个允许您指定进程名称的一行代码(假设只有一个与名称匹配的进程):top -p`ps -ef | grep -i $NAME_OF_PROCESS | grep -v grep | gawk '{print $2}'`
    • $ top -p $(pgrep | xargs | tr ' ' ',')
    【解决方案4】:

    首先获取pid:

    ps ax | grep [process name]
    

    然后:

    top -p PID
    

    可以同时观看各种进程:

    top -p PID1 -p PID2 
    

    【讨论】:

      【解决方案5】:

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

      简介:

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

      【讨论】:

      • 不错,这是一个示例用法:pmap $(pgrep -f -u username /usr/bin/gnome-shell) | sed -n -e 's/ total \+//p' | numfmt --from=iec1724678144
      【解决方案6】:

      更优雅的方法:

      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
      

      【讨论】:

        【解决方案7】:

        如果您没有要跟踪的当前或长期运行的进程,您可以使用/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
        

        【讨论】:

        • macos /usr/bin/time 无法进行这种级别的分析,但自制软件确实通过gnu-time 包提供了正确的实用程序。它安装了一个名为 gtime 的实用程序,它可以执行您所说的操作。
        【解决方案8】:

        使用tophtop 并注意“RES”(驻留内存大小)列。

        【讨论】:

        • 我看到了 RES,但我认为我不需要那个。我用过的 Mem 和用过的 Swap 一直在上涨。我需要知道是什么让这些上升。想法?
        • 常驻内存是您的进程使用的内存。如果尽管您的总内存使用量增加了,但似乎没有一个进程使用太多内存,则该内存只能由内核使用。尝试在 RES 列之后进行排序。当磁盘 IO 很重时,另一点可能是 swappiness 太高。
        • htop -t 在树视图中显示进程,因此您可以在树视图中看到 RES 内存。
        【解决方案9】:

        谢谢。我用它创建了这个简单的 bash 脚本,可以用来监视进程及其内存使用情况:

        $ 观看 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 "=================";
        

        【讨论】:

        • 可能是因为脚本通过 smaps 文件的 5 次传递来计算数据。让 awk 一次性完成解析和计算应该相当容易。
        • @TimothéeGroleau 同意 awk 的性能,无论如何脚本看起来很酷,有人可以从中学习一点。也许保罗鲁宾斯坦想更新他们的剧本:D。谢谢。
        【解决方案10】:

        你想要的工具是ps。 要获取有关 java 程序正在做什么的信息:

        ps -F -C java 
        

        获取有关http的信息:

        ps -F -C httpd
        

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

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

        【讨论】:

          【解决方案11】:

          您可以使用pmap + awk

          很可能,我们对 RSS 内存感兴趣,它是下面示例 pmap 输出 (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 提取该值。

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

          pmap 值以千字节为单位。如果我们想要它以兆字节为单位,我们可以这样做。

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

          【讨论】:

            【解决方案12】:

            为什么所有这些复杂的答案都有各种 shell 脚本? 使用 htop,它会自动更改大小,您可以选择要显示的信息,它可以在终端中使用,因此不需要桌面。 示例:htop -d8

            【讨论】:

            • 大多数使用命令行的人都对以编程方式解决它感兴趣。在某些情况下,他们只是想学习如何使用内核而不是预构建过程来解决这个问题。
            【解决方案13】:

            使用

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

            例子:

            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
            

            【讨论】:

              猜你喜欢
              • 2014-07-22
              • 2010-09-19
              • 2010-10-22
              • 1970-01-01
              • 2011-01-24
              • 2018-03-07
              • 2010-09-17
              • 2010-12-05
              相关资源
              最近更新 更多