如何使用shell获取Linux中fork多个子进程的总内存?

问题描述 投票:0回答:5

http 守护进程例如:

我用

ps aux|grep httpd|grep -v grep

USER     PID     RSS   COMMAND
root     14347   3220  /usr/sbin/httpd
apache   14348   2400  /usr/sbin/httpd
apache   14349   2400  /usr/sbin/httpd
apache   14350   2400  /usr/sbin/httpd

我可以简单地累加RSS字段来获得[httpd]的总内存使用量。 3220+2400+2400+2400 = 10420

但我知道,子进程具有共享内存。这里有一些冗余计算。实际上总内存使用量可能小于10420。

我的问题是如何获取实际的内存使用情况。

linux bash shell memory
5个回答
1
投票

如果您需要获取实际的内存使用情况,您需要在像 Valgrind 这样的分析器中运行它。

参考

http://kratos-wiki.cimne.upc.edu/index.php/Checking_memory_use_with_Valgrind


1
投票

Valgrind 可能是您最准确的选择,但使用起来可能有点尴尬,并且由于性能原因(几乎没有)对于生产系统来说是不合理的。

Smem (homepage) (manpage) 是一个不太复杂的替代方案。

PSS
流程集大小就是您正在寻找的。


0
投票

我在 Chrome 中使用了以下命令:

ps aux | grep chrome | grep -v grep | awk '{s+=$5} END {print s}'

请注意,$5 实际上可能会有所不同,具体取决于

ps aux
实际显示其输出的方式。这对您可能有用也可能没用,并且还会显示总使用量(以字节为单位)。


0
投票

我也在寻找这个答案。 我已经找到了一个有效的。 那就是在 Docker 这样的容器中运行服务。然后使用

docker container stats  $containerid

示例:

CONTAINER ID   NAME             CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O        PIDS
329f402b9f2e   test-apache2-1   0.15%     2.677GiB / 31.01GiB   8.63%     395MB / 159MB   77.9MB / 819kB   21

我不确定容器的哪个功能允许这样做。是cgroup吗?是命名空间吗? 有没有一种轻量级的方法可以测量多个进程的内存,而不需要像 Docker 或 LXC 这样的东西?

我确实知道的一件事是这里的数字是准确的。或者至少比将 ps 或 top 的所有内存加在一起更准确。


0
投票

有几种方法可以完成您在这里提出的要求。一种涉及解析

procfs
,它不需要“root”权限,另一种是使用 Taskstats(一个 Netlink 接口),它需要“root”权限。

如果您可以使用 Generic Netlink 套接字获得 root 权限,那么到目前为止在开销方面是最佳的。

我有一个使用第一个解析解决方案的工作解决方案

procfs

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import time


class ShMemMonitorProcess(object):

    def __init__(self, ppid):
        self.ppid = ppid
        # Create a Sub-Class for Thread module
        self.memory = {'kB':1024, 'mB':1024*1024, 'gB':1024*1024*1024}
        self.scrape_procfs
        
    def calculate_memory(self, vmrss):
        memory, size = vmrss.split()
        return int(memory) * self.memory[size]

    @property
    def scrape_procfs(self):
        rss = 0
        child_ps = dict()
        start = time.time()
        while (time.time() - start) < 100:
            for pid in filter(lambda p: p.isdigit(), os.listdir('/proc')):
                try:
                    # open /proc/PID/status but catch as some can be ephemeral
                    with open('/proc/{}/status'.format(pid)) as fh:
                        ppid = [i for i in fh.readlines() if i.startswith('PPid')]
                        if not ppid:
                            continue
                        ppid = ppid[0].split('\t')[1].strip('\n')
                        if ppid == self.ppid:
                            with open('/proc/{}/status'.format(pid)) as fh:
                                vmrss = fh.readlines()
                                vmrss = [i for i in vmrss if i.startswith('VmRSS')]
                            if not vmrss:
                                continue
                            vmrss = vmrss[0].split('\t')[1].strip('\n')
                            ps_rss = self.calculate_memory(vmrss)
                            if not child_ps.get(pid):
                                with open('/proc/{}/comm'.format(pid)) as fh:
                                    comm = fh.readlines()
                                    print('Found Child Process {}!'.format(pid))
                                    print(comm)
                                print('Adding Process to Hash...')
                                child_ps[pid] = ps_rss
                                rss += ps_rss
                                time.sleep(1)
                            else:
                                # re-calculate process memory
                                print('Process was already found running...')
                                print('Re-calculating memory usage...')
                                previous_rss_used = child_ps[pid]
                                if previous_rss_used > ps_rss:
                                    memory_adj = previous_rss_used - ps_rss
                                    rss -= memory_adj
                                elif previous_rss_used <= ps_rss:
                                    memory_adj = ps_rss - previous_rss_used
                                    rss += memory_adj
                                child_ps[pid] = ps_rss
                            print('Bytes....{}'.format(rss))
                except FileNotFoundError:
                    continue


if __name__ == '__main__':
    # Pass the Process ID through STDIN on calling
    pid = sys.argv[1]
    shmem = ShMemMonitorProcess(pid)

然后只需使用您要查找 RSS 总数的组的“父级”进程的 PID 来调用此函数即可。

python ./Find_RSS.py 1234
Found Child Process 12541!                                                                                    

22:54:40 [12/222]
['Privileged Cont\n']                                                                                                              
Adding Process to Hash...                                                                                                          
Bytes....202661888                                                                                                                 
Found Child Process 12606!                                                                                                         
['WebExtensions\n']                                                                                                                
Adding Process to Hash...                                                                                                          
Bytes....667672576                                                                                                                 
Found Child Process 12666!                                                                                                         
['Utility Process\n']                                                                                                              
Adding Process to Hash...                                                                                                          
Bytes....709660672                                                                                                                 
Found Child Process 14803!                                                                                                         
['RDD Process\n']  
© www.soinside.com 2019 - 2024. All rights reserved.