summaryrefslogtreecommitdiff
path: root/python/psutil/examples
diff options
context:
space:
mode:
Diffstat (limited to 'python/psutil/examples')
-rwxr-xr-xpython/psutil/examples/disk_usage.py62
-rwxr-xr-xpython/psutil/examples/free.py41
-rw-r--r--python/psutil/examples/ifconfig.py78
-rwxr-xr-xpython/psutil/examples/iotop.py179
-rwxr-xr-xpython/psutil/examples/killall.py32
-rwxr-xr-xpython/psutil/examples/meminfo.py68
-rwxr-xr-xpython/psutil/examples/netstat.py64
-rwxr-xr-xpython/psutil/examples/nettop.py165
-rwxr-xr-xpython/psutil/examples/pidof.py53
-rwxr-xr-xpython/psutil/examples/pmap.py57
-rwxr-xr-xpython/psutil/examples/process_detail.py167
-rw-r--r--python/psutil/examples/ps.py81
-rw-r--r--python/psutil/examples/pstree.py71
-rwxr-xr-xpython/psutil/examples/top.py233
-rwxr-xr-xpython/psutil/examples/who.py33
15 files changed, 1384 insertions, 0 deletions
diff --git a/python/psutil/examples/disk_usage.py b/python/psutil/examples/disk_usage.py
new file mode 100755
index 0000000000..d8600a8c47
--- /dev/null
+++ b/python/psutil/examples/disk_usage.py
@@ -0,0 +1,62 @@
+#!/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.
+
+"""
+List all mounted disk partitions a-la "df -h" command.
+
+$ python examples/disk_usage.py
+Device Total Used Free Use % Type Mount
+/dev/sdb3 18.9G 14.7G 3.3G 77% ext4 /
+/dev/sda6 345.9G 83.8G 244.5G 24% ext4 /home
+/dev/sda1 296.0M 43.1M 252.9M 14% vfat /boot/efi
+/dev/sda2 600.0M 312.4M 287.6M 52% fuseblk /media/Recovery
+"""
+
+import sys
+import os
+import psutil
+
+
+def bytes2human(n):
+ # http://code.activestate.com/recipes/578019
+ # >>> bytes2human(10000)
+ # '9.8K'
+ # >>> bytes2human(100001221)
+ # '95.4M'
+ 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():
+ templ = "%-17s %8s %8s %8s %5s%% %9s %s"
+ print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
+ "Mount"))
+ for part in psutil.disk_partitions(all=False):
+ if os.name == 'nt':
+ if 'cdrom' in part.opts or part.fstype == '':
+ # skip cd-rom drives with no disk in it; they may raise
+ # ENOENT, pop-up a Windows GUI error for a non-ready
+ # partition or just hang.
+ continue
+ usage = psutil.disk_usage(part.mountpoint)
+ print(templ % (
+ part.device,
+ bytes2human(usage.total),
+ bytes2human(usage.used),
+ bytes2human(usage.free),
+ int(usage.percent),
+ part.fstype,
+ part.mountpoint))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/python/psutil/examples/free.py b/python/psutil/examples/free.py
new file mode 100755
index 0000000000..913ca58a4c
--- /dev/null
+++ b/python/psutil/examples/free.py
@@ -0,0 +1,41 @@
+#!/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.
+
+"""
+A clone of 'free' cmdline utility.
+
+$ python examples/free.py
+ total used free shared buffers cache
+Mem: 10125520 8625996 1499524 0 349500 3307836
+Swap: 0 0 0
+"""
+
+import psutil
+
+
+def main():
+ virt = psutil.virtual_memory()
+ swap = psutil.swap_memory()
+ templ = "%-7s %10s %10s %10s %10s %10s %10s"
+ print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
+ print(templ % (
+ 'Mem:',
+ int(virt.total / 1024),
+ int(virt.used / 1024),
+ int(virt.free / 1024),
+ int(getattr(virt, 'shared', 0) / 1024),
+ int(getattr(virt, 'buffers', 0) / 1024),
+ int(getattr(virt, 'cached', 0) / 1024)))
+ print(templ % (
+ 'Swap:', int(swap.total / 1024),
+ int(swap.used / 1024),
+ int(swap.free / 1024),
+ '',
+ '',
+ ''))
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/ifconfig.py b/python/psutil/examples/ifconfig.py
new file mode 100644
index 0000000000..e7a436cc0a
--- /dev/null
+++ b/python/psutil/examples/ifconfig.py
@@ -0,0 +1,78 @@
+#!/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.
+
+"""
+A clone of 'ifconfig' on UNIX.
+
+$ python examples/ifconfig.py
+lo (speed=0MB, duplex=?, mtu=65536, up=yes):
+ IPv4 address : 127.0.0.1
+ broadcast : 127.0.0.1
+ netmask : 255.0.0.0
+ IPv6 address : ::1
+ netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+ MAC address : 00:00:00:00:00:00
+ broadcast : 00:00:00:00:00:00
+
+wlan0 (speed=0MB, duplex=?, mtu=1500, up=yes):
+ IPv4 address : 10.0.3.1
+ broadcast : 10.0.3.255
+ netmask : 255.255.255.0
+ IPv6 address : fe80::3005:adff:fe31:8698
+ netmask : ffff:ffff:ffff:ffff::
+ MAC address : 32:05:ad:31:86:98
+ broadcast : ff:ff:ff:ff:ff:ff
+
+eth0 (speed=100MB, duplex=full, mtu=1500, up=yes):
+ IPv4 address : 192.168.1.2
+ broadcast : 192.168.1.255
+ netmask : 255.255.255.0
+ IPv6 address : fe80::c685:8ff:fe45:641
+ netmask : ffff:ffff:ffff:ffff::
+ MAC address : c4:85:08:45:06:41
+ broadcast : ff:ff:ff:ff:ff:ff
+"""
+
+from __future__ import print_function
+import socket
+
+import psutil
+
+
+af_map = {
+ socket.AF_INET: 'IPv4',
+ socket.AF_INET6: 'IPv6',
+ psutil.AF_LINK: 'MAC',
+}
+
+duplex_map = {
+ psutil.NIC_DUPLEX_FULL: "full",
+ psutil.NIC_DUPLEX_HALF: "half",
+ psutil.NIC_DUPLEX_UNKNOWN: "?",
+}
+
+
+def main():
+ stats = psutil.net_if_stats()
+ for nic, addrs in psutil.net_if_addrs().items():
+ if nic in stats:
+ print("%s (speed=%sMB, duplex=%s, mtu=%s, up=%s):" % (
+ nic, stats[nic].speed, duplex_map[stats[nic].duplex],
+ stats[nic].mtu, "yes" if stats[nic].isup else "no"))
+ else:
+ print("%s:" % (nic))
+ for addr in addrs:
+ print(" %-8s" % af_map.get(addr.family, addr.family), end="")
+ print(" address : %s" % addr.address)
+ if addr.broadcast:
+ print(" broadcast : %s" % addr.broadcast)
+ if addr.netmask:
+ print(" netmask : %s" % addr.netmask)
+ print("")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/iotop.py b/python/psutil/examples/iotop.py
new file mode 100755
index 0000000000..16ac7fbf61
--- /dev/null
+++ b/python/psutil/examples/iotop.py
@@ -0,0 +1,179 @@
+#!/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.
+
+"""
+A clone of iotop (http://guichaz.free.fr/iotop/) showing real time
+disk I/O statistics.
+
+It works on Linux only (FreeBSD and OSX are missing support for IO
+counters).
+It doesn't work on Windows as curses module is required.
+
+Example output:
+
+$ python examples/iotop.py
+Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s
+PID USER DISK READ DISK WRITE COMMAND
+13155 giampao 0.00 B/s 428.00 K/s /usr/bin/google-chrome-beta
+3260 giampao 0.00 B/s 0.00 B/s bash
+3779 giampao 0.00 B/s 0.00 B/s gnome-session --session=ubuntu
+3830 giampao 0.00 B/s 0.00 B/s /usr/bin/dbus-launch
+3831 giampao 0.00 B/s 0.00 B/s //bin/dbus-daemon --fork --print-pid 5
+3841 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi-bus-launcher
+3845 giampao 0.00 B/s 0.00 B/s /bin/dbus-daemon
+3848 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi2-core/at-spi2-registryd
+3862 giampao 0.00 B/s 0.00 B/s /usr/lib/gnome-settings-daemon
+
+Author: Giampaolo Rodola' <g.rodola@gmail.com>
+"""
+
+import atexit
+import time
+import sys
+try:
+ import curses
+except ImportError:
+ sys.exit('platform not supported')
+
+import psutil
+
+
+# --- curses stuff
+def tear_down():
+ win.keypad(0)
+ curses.nocbreak()
+ curses.echo()
+ curses.endwin()
+
+win = curses.initscr()
+atexit.register(tear_down)
+curses.endwin()
+lineno = 0
+
+
+def print_line(line, highlight=False):
+ """A thin wrapper around curses's addstr()."""
+ global lineno
+ try:
+ if highlight:
+ line += " " * (win.getmaxyx()[1] - len(line))
+ win.addstr(lineno, 0, line, curses.A_REVERSE)
+ else:
+ win.addstr(lineno, 0, line, 0)
+ except curses.error:
+ lineno = 0
+ win.refresh()
+ raise
+ else:
+ lineno += 1
+# --- /curses stuff
+
+
+def bytes2human(n):
+ """
+ >>> bytes2human(10000)
+ '9.8 K/s'
+ >>> bytes2human(100001221)
+ '95.4 M/s'
+ """
+ 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 '%.2f %s/s' % (value, s)
+ return '%.2f B/s' % (n)
+
+
+def poll(interval):
+ """Calculate IO usage by comparing IO statics before and
+ after the interval.
+ Return a tuple including all currently running processes
+ sorted by IO activity and total disks I/O activity.
+ """
+ # first get a list of all processes and disk io counters
+ procs = [p for p in psutil.process_iter()]
+ for p in procs[:]:
+ try:
+ p._before = p.io_counters()
+ except psutil.Error:
+ procs.remove(p)
+ continue
+ disks_before = psutil.disk_io_counters()
+
+ # sleep some time
+ time.sleep(interval)
+
+ # then retrieve the same info again
+ for p in procs[:]:
+ try:
+ p._after = p.io_counters()
+ p._cmdline = ' '.join(p.cmdline())
+ if not p._cmdline:
+ p._cmdline = p.name()
+ p._username = p.username()
+ except (psutil.NoSuchProcess, psutil.ZombieProcess):
+ procs.remove(p)
+ disks_after = psutil.disk_io_counters()
+
+ # finally calculate results by comparing data before and
+ # after the interval
+ for p in procs:
+ p._read_per_sec = p._after.read_bytes - p._before.read_bytes
+ p._write_per_sec = p._after.write_bytes - p._before.write_bytes
+ p._total = p._read_per_sec + p._write_per_sec
+
+ disks_read_per_sec = disks_after.read_bytes - disks_before.read_bytes
+ disks_write_per_sec = disks_after.write_bytes - disks_before.write_bytes
+
+ # sort processes by total disk IO so that the more intensive
+ # ones get listed first
+ processes = sorted(procs, key=lambda p: p._total, reverse=True)
+
+ return (processes, disks_read_per_sec, disks_write_per_sec)
+
+
+def refresh_window(procs, disks_read, disks_write):
+ """Print results on screen by using curses."""
+ curses.endwin()
+ templ = "%-5s %-7s %11s %11s %s"
+ win.erase()
+
+ disks_tot = "Total DISK READ: %s | Total DISK WRITE: %s" \
+ % (bytes2human(disks_read), bytes2human(disks_write))
+ print_line(disks_tot)
+
+ header = templ % ("PID", "USER", "DISK READ", "DISK WRITE", "COMMAND")
+ print_line(header, highlight=True)
+
+ for p in procs:
+ line = templ % (
+ p.pid,
+ p._username[:7],
+ bytes2human(p._read_per_sec),
+ bytes2human(p._write_per_sec),
+ p._cmdline)
+ try:
+ print_line(line)
+ except curses.error:
+ break
+ win.refresh()
+
+
+def main():
+ try:
+ interval = 0
+ while True:
+ args = poll(interval)
+ refresh_window(*args)
+ interval = 1
+ except (KeyboardInterrupt, SystemExit):
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/killall.py b/python/psutil/examples/killall.py
new file mode 100755
index 0000000000..b548e7bc57
--- /dev/null
+++ b/python/psutil/examples/killall.py
@@ -0,0 +1,32 @@
+#!/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.
+
+"""
+Kill a process by name.
+"""
+
+import os
+import sys
+import psutil
+
+
+def main():
+ if len(sys.argv) != 2:
+ sys.exit('usage: %s name' % __file__)
+ else:
+ NAME = sys.argv[1]
+
+ killed = []
+ for proc in psutil.process_iter():
+ if proc.name() == NAME and proc.pid != os.getpid():
+ proc.kill()
+ killed.append(proc.pid)
+ if not killed:
+ sys.exit('%s: no process found' % NAME)
+ else:
+ sys.exit(0)
+
+sys.exit(main())
diff --git a/python/psutil/examples/meminfo.py b/python/psutil/examples/meminfo.py
new file mode 100755
index 0000000000..c463a3de4b
--- /dev/null
+++ b/python/psutil/examples/meminfo.py
@@ -0,0 +1,68 @@
+#!/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.
+
+"""
+Print system memory information.
+
+$ python examples/meminfo.py
+MEMORY
+------
+Total : 9.7G
+Available : 4.9G
+Percent : 49.0
+Used : 8.2G
+Free : 1.4G
+Active : 5.6G
+Inactive : 2.1G
+Buffers : 341.2M
+Cached : 3.2G
+
+SWAP
+----
+Total : 0B
+Used : 0B
+Free : 0B
+Percent : 0.0
+Sin : 0B
+Sout : 0B
+"""
+
+import psutil
+
+
+def bytes2human(n):
+ # http://code.activestate.com/recipes/578019
+ # >>> bytes2human(10000)
+ # '9.8K'
+ # >>> bytes2human(100001221)
+ # '95.4M'
+ 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 pprint_ntuple(nt):
+ for name in nt._fields:
+ value = getattr(nt, name)
+ if name != 'percent':
+ value = bytes2human(value)
+ print('%-10s : %7s' % (name.capitalize(), value))
+
+
+def main():
+ print('MEMORY\n------')
+ pprint_ntuple(psutil.virtual_memory())
+ print('\nSWAP\n----')
+ pprint_ntuple(psutil.swap_memory())
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/netstat.py b/python/psutil/examples/netstat.py
new file mode 100755
index 0000000000..884622e9e3
--- /dev/null
+++ b/python/psutil/examples/netstat.py
@@ -0,0 +1,64 @@
+#!/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.
+
+"""
+A clone of 'netstat -antp' on Linux.
+
+$ python examples/netstat.py
+Proto Local address Remote address Status PID Program name
+tcp 127.0.0.1:48256 127.0.0.1:45884 ESTABLISHED 13646 chrome
+tcp 127.0.0.1:47073 127.0.0.1:45884 ESTABLISHED 13646 chrome
+tcp 127.0.0.1:47072 127.0.0.1:45884 ESTABLISHED 13646 chrome
+tcp 127.0.0.1:45884 - LISTEN 13651 GoogleTalkPlugi
+tcp 127.0.0.1:60948 - LISTEN 13651 GoogleTalkPlugi
+tcp 172.17.42.1:49102 127.0.0.1:19305 CLOSE_WAIT 13651 GoogleTalkPlugi
+tcp 172.17.42.1:55797 127.0.0.1:443 CLOSE_WAIT 13651 GoogleTalkPlugi
+...
+"""
+
+import socket
+from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
+
+import psutil
+
+
+AD = "-"
+AF_INET6 = getattr(socket, 'AF_INET6', object())
+proto_map = {
+ (AF_INET, SOCK_STREAM): 'tcp',
+ (AF_INET6, SOCK_STREAM): 'tcp6',
+ (AF_INET, SOCK_DGRAM): 'udp',
+ (AF_INET6, SOCK_DGRAM): 'udp6',
+}
+
+
+def main():
+ templ = "%-5s %-30s %-30s %-13s %-6s %s"
+ print(templ % (
+ "Proto", "Local address", "Remote address", "Status", "PID",
+ "Program name"))
+ proc_names = {}
+ for p in psutil.process_iter():
+ try:
+ proc_names[p.pid] = p.name()
+ except psutil.Error:
+ pass
+ for c in psutil.net_connections(kind='inet'):
+ laddr = "%s:%s" % (c.laddr)
+ raddr = ""
+ if c.raddr:
+ raddr = "%s:%s" % (c.raddr)
+ print(templ % (
+ proto_map[(c.family, c.type)],
+ laddr,
+ raddr or AD,
+ c.status,
+ c.pid or AD,
+ proc_names.get(c.pid, '?')[:15],
+ ))
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/nettop.py b/python/psutil/examples/nettop.py
new file mode 100755
index 0000000000..7a8343ee4c
--- /dev/null
+++ b/python/psutil/examples/nettop.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+#
+# $Id: iotop.py 1160 2011-10-14 18:50:36Z g.rodola@gmail.com $
+#
+# 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.
+
+"""
+Shows real-time network statistics.
+
+Author: Giampaolo Rodola' <g.rodola@gmail.com>
+
+$ python examples/nettop.py
+-----------------------------------------------------------
+total bytes: sent: 1.49 G received: 4.82 G
+total packets: sent: 7338724 received: 8082712
+
+wlan0 TOTAL PER-SEC
+-----------------------------------------------------------
+bytes-sent 1.29 G 0.00 B/s
+bytes-recv 3.48 G 0.00 B/s
+pkts-sent 7221782 0
+pkts-recv 6753724 0
+
+eth1 TOTAL PER-SEC
+-----------------------------------------------------------
+bytes-sent 131.77 M 0.00 B/s
+bytes-recv 1.28 G 0.00 B/s
+pkts-sent 0 0
+pkts-recv 1214470 0
+"""
+
+import atexit
+import time
+import sys
+try:
+ import curses
+except ImportError:
+ sys.exit('platform not supported')
+
+import psutil
+
+
+# --- curses stuff
+def tear_down():
+ win.keypad(0)
+ curses.nocbreak()
+ curses.echo()
+ curses.endwin()
+
+win = curses.initscr()
+atexit.register(tear_down)
+curses.endwin()
+lineno = 0
+
+
+def print_line(line, highlight=False):
+ """A thin wrapper around curses's addstr()."""
+ global lineno
+ try:
+ if highlight:
+ line += " " * (win.getmaxyx()[1] - len(line))
+ win.addstr(lineno, 0, line, curses.A_REVERSE)
+ else:
+ win.addstr(lineno, 0, line, 0)
+ except curses.error:
+ lineno = 0
+ win.refresh()
+ raise
+ else:
+ lineno += 1
+# --- curses stuff
+
+
+def bytes2human(n):
+ """
+ >>> bytes2human(10000)
+ '9.8 K'
+ >>> bytes2human(100001221)
+ '95.4 M'
+ """
+ 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 '%.2f %s' % (value, s)
+ return '%.2f B' % (n)
+
+
+def poll(interval):
+ """Retrieve raw stats within an interval window."""
+ tot_before = psutil.net_io_counters()
+ pnic_before = psutil.net_io_counters(pernic=True)
+ # sleep some time
+ time.sleep(interval)
+ tot_after = psutil.net_io_counters()
+ pnic_after = psutil.net_io_counters(pernic=True)
+ return (tot_before, tot_after, pnic_before, pnic_after)
+
+
+def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
+ """Print stats on screen."""
+ global lineno
+
+ # totals
+ print_line("total bytes: sent: %-10s received: %s" % (
+ bytes2human(tot_after.bytes_sent),
+ bytes2human(tot_after.bytes_recv))
+ )
+ print_line("total packets: sent: %-10s received: %s" % (
+ tot_after.packets_sent, tot_after.packets_recv))
+
+ # per-network interface details: let's sort network interfaces so
+ # that the ones which generated more traffic are shown first
+ print_line("")
+ nic_names = list(pnic_after.keys())
+ nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True)
+ for name in nic_names:
+ stats_before = pnic_before[name]
+ stats_after = pnic_after[name]
+ templ = "%-15s %15s %15s"
+ print_line(templ % (name, "TOTAL", "PER-SEC"), highlight=True)
+ print_line(templ % (
+ "bytes-sent",
+ bytes2human(stats_after.bytes_sent),
+ bytes2human(
+ stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
+ ))
+ print_line(templ % (
+ "bytes-recv",
+ bytes2human(stats_after.bytes_recv),
+ bytes2human(
+ stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
+ ))
+ print_line(templ % (
+ "pkts-sent",
+ stats_after.packets_sent,
+ stats_after.packets_sent - stats_before.packets_sent,
+ ))
+ print_line(templ % (
+ "pkts-recv",
+ stats_after.packets_recv,
+ stats_after.packets_recv - stats_before.packets_recv,
+ ))
+ print_line("")
+ win.refresh()
+ lineno = 0
+
+
+def main():
+ try:
+ interval = 0
+ while True:
+ args = poll(interval)
+ refresh_window(*args)
+ interval = 1
+ except (KeyboardInterrupt, SystemExit):
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/pidof.py b/python/psutil/examples/pidof.py
new file mode 100755
index 0000000000..8692a3152b
--- /dev/null
+++ b/python/psutil/examples/pidof.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009, Giampaolo Rodola', karthikrev. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""
+A clone of 'pidof' cmdline utility.
+$ pidof python
+1140 1138 1136 1134 1133 1129 1127 1125 1121 1120 1119
+"""
+
+from __future__ import print_function
+import psutil
+import sys
+
+
+def pidof(pgname):
+ pids = []
+ for proc in psutil.process_iter():
+ # search for matches in the process name and cmdline
+ try:
+ name = proc.name()
+ except psutil.Error:
+ pass
+ else:
+ if name == pgname:
+ pids.append(str(proc.pid))
+ continue
+
+ try:
+ cmdline = proc.cmdline()
+ except psutil.Error:
+ pass
+ else:
+ if cmdline and cmdline[0] == pgname:
+ pids.append(str(proc.pid))
+
+ return pids
+
+
+def main():
+ if len(sys.argv) != 2:
+ sys.exit('usage: %s pgname' % __file__)
+ else:
+ pgname = sys.argv[1]
+ pids = pidof(pgname)
+ if pids:
+ print(" ".join(pids))
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/pmap.py b/python/psutil/examples/pmap.py
new file mode 100755
index 0000000000..7593777aef
--- /dev/null
+++ b/python/psutil/examples/pmap.py
@@ -0,0 +1,57 @@
+#!/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.
+
+"""
+A clone of 'pmap' utility on Linux, 'vmmap' on OSX and 'procstat -v' on BSD.
+Report memory map of a process.
+
+$ python examples/pmap.py 32402
+pid=32402, name=hg
+Address RSS Mode Mapping
+0000000000400000 1200K r-xp /usr/bin/python2.7
+0000000000838000 4K r--p /usr/bin/python2.7
+0000000000839000 304K rw-p /usr/bin/python2.7
+00000000008ae000 68K rw-p [anon]
+000000000275e000 5396K rw-p [heap]
+00002b29bb1e0000 124K r-xp /lib/x86_64-linux-gnu/ld-2.17.so
+00002b29bb203000 8K rw-p [anon]
+00002b29bb220000 528K rw-p [anon]
+00002b29bb2d8000 768K rw-p [anon]
+00002b29bb402000 4K r--p /lib/x86_64-linux-gnu/ld-2.17.so
+00002b29bb403000 8K rw-p /lib/x86_64-linux-gnu/ld-2.17.so
+00002b29bb405000 60K r-xp /lib/x86_64-linux-gnu/libpthread-2.17.so
+00002b29bb41d000 0K ---p /lib/x86_64-linux-gnu/libpthread-2.17.so
+00007fff94be6000 48K rw-p [stack]
+00007fff94dd1000 4K r-xp [vdso]
+ffffffffff600000 0K r-xp [vsyscall]
+...
+"""
+
+import sys
+
+import psutil
+
+
+def main():
+ if len(sys.argv) != 2:
+ sys.exit('usage: pmap <pid>')
+ p = psutil.Process(int(sys.argv[1]))
+ print("pid=%s, name=%s" % (p.pid, p.name()))
+ templ = "%-16s %10s %-7s %s"
+ print(templ % ("Address", "RSS", "Mode", "Mapping"))
+ total_rss = 0
+ for m in p.memory_maps(grouped=False):
+ total_rss += m.rss
+ print(templ % (
+ m.addr.split('-')[0].zfill(16),
+ str(m.rss / 1024) + 'K',
+ m.perms,
+ m.path))
+ print("-" * 33)
+ print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/process_detail.py b/python/psutil/examples/process_detail.py
new file mode 100755
index 0000000000..e20371aefe
--- /dev/null
+++ b/python/psutil/examples/process_detail.py
@@ -0,0 +1,167 @@
+#!/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.
+
+"""
+Print detailed information about a process.
+Author: Giampaolo Rodola' <g.rodola@gmail.com>
+
+$ python examples/process_detail.py
+pid 820
+name python
+exe /usr/bin/python2.7
+parent 29613 (bash)
+cmdline python examples/process_detail.py
+started 2014-41-27 03:41
+user giampaolo
+uids real=1000, effective=1000, saved=1000
+gids real=1000, effective=1000, saved=1000
+terminal /dev/pts/17
+cwd /ssd/svn/psutil
+memory 0.1% (resident=10.6M, virtual=58.5M)
+cpu 0.0% (user=0.09, system=0.0)
+status running
+niceness 0
+num threads 1
+I/O bytes-read=0B, bytes-written=0B
+open files
+running threads id=820, user-time=0.09, sys-time=0.0
+"""
+
+import datetime
+import os
+import socket
+import sys
+
+import psutil
+
+
+POSIX = os.name == 'posix'
+
+
+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 print_(a, b):
+ if sys.stdout.isatty() and POSIX:
+ 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()
+
+
+def run(pid):
+ ACCESS_DENIED = ''
+ try:
+ p = psutil.Process(pid)
+ pinfo = p.as_dict(ad_value=ACCESS_DENIED)
+ except psutil.NoSuchProcess as err:
+ sys.exit(str(err))
+
+ try:
+ parent = p.parent()
+ if parent:
+ parent = '(%s)' % parent.name()
+ else:
+ parent = ''
+ except psutil.Error:
+ parent = ''
+ if pinfo['create_time'] != ACCESS_DENIED:
+ started = datetime.datetime.fromtimestamp(
+ pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
+ else:
+ started = ACCESS_DENIED
+ io = pinfo.get('io_counters', ACCESS_DENIED)
+ if pinfo['memory_info'] != ACCESS_DENIED:
+ mem = '%s%% (resident=%s, virtual=%s) ' % (
+ round(pinfo['memory_percent'], 1),
+ convert_bytes(pinfo['memory_info'].rss),
+ convert_bytes(pinfo['memory_info'].vms))
+ else:
+ mem = ACCESS_DENIED
+ children = p.children()
+
+ print_('pid', pinfo['pid'])
+ print_('name', pinfo['name'])
+ print_('exe', pinfo['exe'])
+ print_('parent', '%s %s' % (pinfo['ppid'], parent))
+ print_('cmdline', ' '.join(pinfo['cmdline']))
+ print_('started', started)
+ print_('user', pinfo['username'])
+ if POSIX and pinfo['uids'] and pinfo['gids']:
+ print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids'])
+ if POSIX and pinfo['gids']:
+ print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
+ if POSIX:
+ print_('terminal', pinfo['terminal'] or '')
+ print_('cwd', pinfo['cwd'])
+ print_('memory', mem)
+ print_('cpu', '%s%% (user=%s, system=%s)' % (
+ pinfo['cpu_percent'],
+ getattr(pinfo['cpu_times'], 'user', '?'),
+ getattr(pinfo['cpu_times'], 'system', '?')))
+ print_('status', pinfo['status'])
+ print_('niceness', pinfo['nice'])
+ print_('num threads', pinfo['num_threads'])
+ if io != ACCESS_DENIED:
+ print_('I/O', 'bytes-read=%s, bytes-written=%s' % (
+ convert_bytes(io.read_bytes),
+ convert_bytes(io.write_bytes)))
+ if children:
+ print_('children', '')
+ for child in children:
+ print_('', 'pid=%s name=%s' % (child.pid, child.name()))
+
+ if pinfo['open_files'] != ACCESS_DENIED:
+ print_('open files', '')
+ for file in pinfo['open_files']:
+ print_('', 'fd=%s %s ' % (file.fd, file.path))
+
+ if pinfo['threads']:
+ print_('running threads', '')
+ for thread in pinfo['threads']:
+ print_('', 'id=%s, user-time=%s, sys-time=%s' % (
+ thread.id, thread.user_time, thread.system_time))
+ if pinfo['connections'] not in (ACCESS_DENIED, []):
+ print_('open connections', '')
+ for conn in pinfo['connections']:
+ if conn.type == socket.SOCK_STREAM:
+ type = 'TCP'
+ elif conn.type == socket.SOCK_DGRAM:
+ type = 'UDP'
+ else:
+ type = 'UNIX'
+ lip, lport = conn.laddr
+ if not conn.raddr:
+ rip, rport = '*', '*'
+ else:
+ rip, rport = conn.raddr
+ print_('', '%s:%s -> %s:%s type=%s status=%s' % (
+ lip, lport, rip, rport, type, conn.status))
+
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+ if len(argv) == 1:
+ sys.exit(run(os.getpid()))
+ elif len(argv) == 2:
+ sys.exit(run(int(argv[1])))
+ else:
+ sys.exit('usage: %s [pid]' % __file__)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/python/psutil/examples/ps.py b/python/psutil/examples/ps.py
new file mode 100644
index 0000000000..2b67bd18ff
--- /dev/null
+++ b/python/psutil/examples/ps.py
@@ -0,0 +1,81 @@
+#!/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.
+
+"""
+A clone of 'ps -aux' on UNIX.
+
+$ python examples/ps.py
+...
+"""
+
+import datetime
+import os
+import time
+
+import psutil
+
+
+def main():
+ today_day = datetime.date.today()
+ templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s"
+ attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
+ 'create_time', 'memory_info']
+ if os.name == 'posix':
+ attrs.append('uids')
+ attrs.append('terminal')
+ print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
+ "START", "TIME", "COMMAND"))
+ for p in psutil.process_iter():
+ try:
+ pinfo = p.as_dict(attrs, ad_value='')
+ except psutil.NoSuchProcess:
+ pass
+ else:
+ if pinfo['create_time']:
+ ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
+ if ctime.date() == today_day:
+ ctime = ctime.strftime("%H:%M")
+ else:
+ ctime = ctime.strftime("%b%d")
+ else:
+ ctime = ''
+ cputime = time.strftime("%M:%S",
+ time.localtime(sum(pinfo['cpu_times'])))
+ try:
+ user = p.username()
+ except KeyError:
+ if os.name == 'posix':
+ if pinfo['uids']:
+ user = str(pinfo['uids'].real)
+ else:
+ user = ''
+ else:
+ raise
+ except psutil.Error:
+ user = ''
+ if os.name == 'nt' and '\\' in user:
+ user = user.split('\\')[1]
+ vms = pinfo['memory_info'] and \
+ int(pinfo['memory_info'].vms / 1024) or '?'
+ rss = pinfo['memory_info'] and \
+ int(pinfo['memory_info'].rss / 1024) or '?'
+ memp = pinfo['memory_percent'] and \
+ round(pinfo['memory_percent'], 1) or '?'
+ print(templ % (
+ user[:10],
+ pinfo['pid'],
+ pinfo['cpu_percent'],
+ memp,
+ vms,
+ rss,
+ pinfo.get('terminal', '') or '?',
+ ctime,
+ cputime,
+ pinfo['name'].strip() or '?'))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/pstree.py b/python/psutil/examples/pstree.py
new file mode 100644
index 0000000000..1bf8c9c049
--- /dev/null
+++ b/python/psutil/examples/pstree.py
@@ -0,0 +1,71 @@
+#!/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.
+
+"""
+Similar to 'ps aux --forest' on Linux, prints the process list
+as a tree structure.
+
+$ python examples/pstree.py
+0 ?
+|- 1 init
+| |- 289 cgmanager
+| |- 616 upstart-socket-bridge
+| |- 628 rpcbind
+| |- 892 upstart-file-bridge
+| |- 907 dbus-daemon
+| |- 978 avahi-daemon
+| | `_ 979 avahi-daemon
+| |- 987 NetworkManager
+| | |- 2242 dnsmasq
+| | `_ 10699 dhclient
+| |- 993 polkitd
+| |- 1061 getty
+| |- 1066 su
+| | `_ 1190 salt-minion...
+...
+"""
+
+from __future__ import print_function
+import collections
+import sys
+
+import psutil
+
+
+def print_tree(parent, tree, indent=''):
+ try:
+ name = psutil.Process(parent).name()
+ except psutil.Error:
+ name = "?"
+ print(parent, name)
+ if parent not in tree:
+ return
+ children = tree[parent][:-1]
+ for child in children:
+ sys.stdout.write(indent + "|- ")
+ print_tree(child, tree, indent + "| ")
+ child = tree[parent][-1]
+ sys.stdout.write(indent + "`_ ")
+ print_tree(child, tree, indent + " ")
+
+
+def main():
+ # construct a dict where 'values' are all the processes
+ # having 'key' as their parent
+ tree = collections.defaultdict(list)
+ for p in psutil.process_iter():
+ try:
+ tree[p.ppid()].append(p.pid)
+ except (psutil.NoSuchProcess, psutil.ZombieProcess):
+ pass
+ # on systems supporting PID 0, PID 0's parent is usually 0
+ if 0 in tree and 0 in tree[0]:
+ tree[0].remove(0)
+ print_tree(min(tree), tree)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/top.py b/python/psutil/examples/top.py
new file mode 100755
index 0000000000..7aebef1d42
--- /dev/null
+++ b/python/psutil/examples/top.py
@@ -0,0 +1,233 @@
+#!/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.
+
+"""
+A clone of top / htop.
+
+Author: Giampaolo Rodola' <g.rodola@gmail.com>
+
+$ python examples/top.py
+ CPU0 [| ] 4.9%
+ CPU1 [||| ] 7.8%
+ CPU2 [ ] 2.0%
+ CPU3 [||||| ] 13.9%
+ Mem [||||||||||||||||||| ] 49.8% 4920M/9888M
+ Swap [ ] 0.0% 0M/0M
+ Processes: 287 (running=1 sleeping=286)
+ Load average: 0.34 0.54 0.46 Uptime: 3 days, 10:16:37
+
+PID USER NI VIRT RES CPU% MEM% TIME+ NAME
+------------------------------------------------------------
+989 giampaol 0 66M 12M 7.4 0.1 0:00.61 python
+2083 root 0 506M 159M 6.5 1.6 0:29.26 Xorg
+4503 giampaol 0 599M 25M 6.5 0.3 3:32.60 gnome-terminal
+3868 giampaol 0 358M 8M 2.8 0.1 23:12.60 pulseaudio
+3936 giampaol 0 1G 111M 2.8 1.1 33:41.67 compiz
+4401 giampaol 0 536M 141M 2.8 1.4 35:42.73 skype
+4047 giampaol 0 743M 76M 1.8 0.8 42:03.33 unity-panel-service
+13155 giampaol 0 1G 280M 1.8 2.8 41:57.34 chrome
+10 root 0 0B 0B 0.9 0.0 4:01.81 rcu_sched
+339 giampaol 0 1G 113M 0.9 1.1 8:15.73 chrome
+...
+"""
+
+from datetime import datetime, timedelta
+import atexit
+import os
+import time
+import sys
+try:
+ import curses
+except ImportError:
+ sys.exit('platform not supported')
+
+import psutil
+
+
+# --- curses stuff
+def tear_down():
+ win.keypad(0)
+ curses.nocbreak()
+ curses.echo()
+ curses.endwin()
+
+win = curses.initscr()
+atexit.register(tear_down)
+curses.endwin()
+lineno = 0
+
+
+def print_line(line, highlight=False):
+ """A thin wrapper around curses's addstr()."""
+ global lineno
+ try:
+ if highlight:
+ line += " " * (win.getmaxyx()[1] - len(line))
+ win.addstr(lineno, 0, line, curses.A_REVERSE)
+ else:
+ win.addstr(lineno, 0, line, 0)
+ except curses.error:
+ lineno = 0
+ win.refresh()
+ raise
+ else:
+ lineno += 1
+# --- /curses stuff
+
+
+def bytes2human(n):
+ """
+ >>> bytes2human(10000)
+ '9K'
+ >>> bytes2human(100001221)
+ '95M'
+ """
+ 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 = int(float(n) / prefix[s])
+ return '%s%s' % (value, s)
+ return "%sB" % n
+
+
+def poll(interval):
+ # sleep some time
+ time.sleep(interval)
+ procs = []
+ procs_status = {}
+ for p in psutil.process_iter():
+ try:
+ p.dict = p.as_dict(['username', 'nice', 'memory_info',
+ 'memory_percent', 'cpu_percent',
+ 'cpu_times', 'name', 'status'])
+ try:
+ procs_status[p.dict['status']] += 1
+ except KeyError:
+ procs_status[p.dict['status']] = 1
+ except psutil.NoSuchProcess:
+ pass
+ else:
+ procs.append(p)
+
+ # return processes sorted by CPU percent usage
+ processes = sorted(procs, key=lambda p: p.dict['cpu_percent'],
+ reverse=True)
+ return (processes, procs_status)
+
+
+def print_header(procs_status, num_procs):
+ """Print system-related info, above the process list."""
+
+ def get_dashes(perc):
+ dashes = "|" * int((float(perc) / 10 * 4))
+ empty_dashes = " " * (40 - len(dashes))
+ return dashes, empty_dashes
+
+ # cpu usage
+ percs = psutil.cpu_percent(interval=0, percpu=True)
+ for cpu_num, perc in enumerate(percs):
+ dashes, empty_dashes = get_dashes(perc)
+ print_line(" CPU%-2s [%s%s] %5s%%" % (cpu_num, dashes, empty_dashes,
+ perc))
+ mem = psutil.virtual_memory()
+ dashes, empty_dashes = get_dashes(mem.percent)
+ used = mem.total - mem.available
+ line = " Mem [%s%s] %5s%% %6s/%s" % (
+ dashes, empty_dashes,
+ mem.percent,
+ str(int(used / 1024 / 1024)) + "M",
+ str(int(mem.total / 1024 / 1024)) + "M"
+ )
+ print_line(line)
+
+ # swap usage
+ swap = psutil.swap_memory()
+ dashes, empty_dashes = get_dashes(swap.percent)
+ line = " Swap [%s%s] %5s%% %6s/%s" % (
+ dashes, empty_dashes,
+ swap.percent,
+ str(int(swap.used / 1024 / 1024)) + "M",
+ str(int(swap.total / 1024 / 1024)) + "M"
+ )
+ print_line(line)
+
+ # processes number and status
+ st = []
+ for x, y in procs_status.items():
+ if y:
+ st.append("%s=%s" % (x, y))
+ st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1)
+ print_line(" Processes: %s (%s)" % (num_procs, ' '.join(st)))
+ # load average, uptime
+ uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time())
+ av1, av2, av3 = os.getloadavg()
+ line = " Load average: %.2f %.2f %.2f Uptime: %s" \
+ % (av1, av2, av3, str(uptime).split('.')[0])
+ print_line(line)
+
+
+def refresh_window(procs, procs_status):
+ """Print results on screen by using curses."""
+ curses.endwin()
+ templ = "%-6s %-8s %4s %5s %5s %6s %4s %9s %2s"
+ win.erase()
+ header = templ % ("PID", "USER", "NI", "VIRT", "RES", "CPU%", "MEM%",
+ "TIME+", "NAME")
+ print_header(procs_status, len(procs))
+ print_line("")
+ print_line(header, highlight=True)
+ for p in procs:
+ # TIME+ column shows process CPU cumulative time and it
+ # is expressed as: "mm:ss.ms"
+ if p.dict['cpu_times'] is not None:
+ ctime = timedelta(seconds=sum(p.dict['cpu_times']))
+ ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60,
+ str((ctime.seconds % 60)).zfill(2),
+ str(ctime.microseconds)[:2])
+ else:
+ ctime = ''
+ if p.dict['memory_percent'] is not None:
+ p.dict['memory_percent'] = round(p.dict['memory_percent'], 1)
+ else:
+ p.dict['memory_percent'] = ''
+ if p.dict['cpu_percent'] is None:
+ p.dict['cpu_percent'] = ''
+ if p.dict['username']:
+ username = p.dict['username'][:8]
+ else:
+ username = ""
+ line = templ % (p.pid,
+ username,
+ p.dict['nice'],
+ bytes2human(getattr(p.dict['memory_info'], 'vms', 0)),
+ bytes2human(getattr(p.dict['memory_info'], 'rss', 0)),
+ p.dict['cpu_percent'],
+ p.dict['memory_percent'],
+ ctime,
+ p.dict['name'] or '',
+ )
+ try:
+ print_line(line)
+ except curses.error:
+ break
+ win.refresh()
+
+
+def main():
+ try:
+ interval = 0
+ while True:
+ args = poll(interval)
+ refresh_window(*args)
+ interval = 1
+ except (KeyboardInterrupt, SystemExit):
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/python/psutil/examples/who.py b/python/psutil/examples/who.py
new file mode 100755
index 0000000000..b382bebfa3
--- /dev/null
+++ b/python/psutil/examples/who.py
@@ -0,0 +1,33 @@
+#!/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.
+
+"""
+A clone of 'who' command; print information about users who are
+currently logged in.
+
+$ python examples/who.py
+giampaolo tty7 2014-02-23 17:25 (:0)
+giampaolo pts/7 2014-02-24 18:25 (:192.168.1.56)
+giampaolo pts/8 2014-02-24 18:25 (:0)
+giampaolo pts/9 2014-02-27 01:32 (:0)
+"""
+
+from datetime import datetime
+
+import psutil
+
+
+def main():
+ users = psutil.users()
+ for user in users:
+ print("%-15s %-15s %s (%s)" % (
+ user.name,
+ user.terminal or '-',
+ datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
+ user.host))
+
+if __name__ == '__main__':
+ main()