summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-02-09 13:21:16 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2016-02-09 13:21:16 +0100
commitf0211e90a9c52e61fca2a197a894642f2dff74e7 (patch)
tree0ed9cb0cdbb98986d7629928291f58af7f1ff0b7
parent5018d79a8980b7767370333108b4e98fb4ca44df (diff)
downloadpsutil-f0211e90a9c52e61fca2a197a894642f2dff74e7.tar.gz
fix #762: add sripts/procsmem.py script.
-rw-r--r--HISTORY.rst1
-rw-r--r--psutil/tests/test_misc.py5
-rwxr-xr-xscripts/procinfo.py8
-rwxr-xr-xscripts/procsmem.py80
4 files changed, 89 insertions, 5 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 1b1cf7e1..5be3772f 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -13,6 +13,7 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
- #755: Process.memory_percent() "memtype" parameter.
- #758: tests now live in psutil namespace.
- #760: expose OS constants (LINUX, OSX, etc.)
+- #762: new sripts/procsmem.py script.
**Bug fixes**
diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py
index 45689a33..507abf94 100644
--- a/psutil/tests/test_misc.py
+++ b/psutil/tests/test_misc.py
@@ -392,6 +392,11 @@ class TestScripts(unittest.TestCase):
def test_pmap(self):
self.assert_stdout('pmap.py', args=str(os.getpid()))
+ @unittest.skipUnless(hasattr(psutil.Process, "memory_addrspace_info"),
+ "memory_addrspace_info() not supported")
+ def test_procsmem(self):
+ self.assert_stdout('procsmem.py')
+
@unittest.skipIf(ast is None,
'ast module not available on this python version')
def test_killall(self):
diff --git a/scripts/procinfo.py b/scripts/procinfo.py
index bbb0b8e4..9990086f 100755
--- a/scripts/procinfo.py
+++ b/scripts/procinfo.py
@@ -58,9 +58,7 @@ def print_(a, b):
fmt = '\x1b[1;32m%-17s\x1b[0m %s' % (a, b)
else:
fmt = '%-15s %s' % (a, b)
- # python 2/3 compatibility layer
- sys.stdout.write(fmt + '\n')
- sys.stdout.flush()
+ print(fmt)
def run(pid):
@@ -125,12 +123,12 @@ def run(pid):
for child in children:
print_('', 'pid=%s name=%s' % (child.pid, child.name()))
- if pinfo['open_files'] != ACCESS_DENIED:
+ if pinfo['open_files'] != ACCESS_DENIED and pinfo['open_files']:
print_('open files', '')
for file in pinfo['open_files']:
print_('', 'fd=%s %s ' % (file.fd, file.path))
- if pinfo['threads']:
+ if pinfo['threads'] and len(pinfo['threads']) > 1:
print_('running threads', '')
for thread in pinfo['threads']:
print_('', 'id=%s, user-time=%s, sys-time=%s' % (
diff --git a/scripts/procsmem.py b/scripts/procsmem.py
new file mode 100755
index 00000000..bc2a79a2
--- /dev/null
+++ b/scripts/procsmem.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Show detailed memory usage about all (querable) processes.
+
+Processes are sorted by their "USS" (Unique Set Size) memory, which is
+probably the most representative metric for determining how much memory
+is being used by a process.
+
+This is similar to "smem" cmdline utility on Linux:
+https://www.selenic.com/smem/
+"""
+
+from __future__ import print_function
+import sys
+
+import psutil
+
+
+if not hasattr(psutil.Process, "memory_addrspace_info"):
+ sys.exit("platform not supported")
+
+
+def convert_bytes(n):
+ symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
+ prefix = {}
+ for i, s in enumerate(symbols):
+ prefix[s] = 1 << (i + 1) * 10
+ for s in reversed(symbols):
+ if n >= prefix[s]:
+ value = float(n) / prefix[s]
+ return '%.1f%s' % (value, s)
+ return "%sB" % n
+
+
+def main():
+ ad_pids = []
+ procs = []
+ for p in psutil.process_iter():
+ try:
+ mem_addrspace = p.memory_addrspace_info()
+ info = p.as_dict(attrs=["cmdline", "username", "memory_info"])
+ except psutil.AccessDenied:
+ ad_pids.append(p.pid)
+ except psutil.NoSuchProcess:
+ pass
+ else:
+ p._uss = mem_addrspace.uss
+ if not p._uss:
+ continue
+ p._pss = getattr(mem_addrspace, "pss", "")
+ p._swap = getattr(mem_addrspace, "swap", "")
+ p._info = info
+ procs.append(p)
+
+ procs.sort(key=lambda p: p._uss)
+ templ = "%-7s %-7s %-30s %7s %7s %7s %7s"
+ print(templ % ("PID", "User", "Cmdline", "USS", "PSS", "Swap", "RSS"))
+ print("=" * 78)
+ for p in procs:
+ line = templ % (
+ p.pid,
+ p._info["username"][:7],
+ " ".join(p._info["cmdline"])[:30],
+ convert_bytes(p._uss),
+ convert_bytes(p._pss),
+ convert_bytes(p._swap),
+ convert_bytes(p._info['memory_info'].rss),
+ )
+ print(line)
+ if ad_pids:
+ print("warning: access denied for %s pids" % (len(ad_pids)),
+ file=sys.stderr)
+
+if __name__ == '__main__':
+ sys.exit(main())