|
1 #!/usr/bin/env python |
|
2 |
|
3 # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. |
|
4 # Use of this source code is governed by a BSD-style license that can be |
|
5 # found in the LICENSE file. |
|
6 |
|
7 """ |
|
8 Print detailed information about a process. |
|
9 |
|
10 Author: Giampaolo Rodola' <g.rodola@gmail.com> |
|
11 """ |
|
12 |
|
13 import os |
|
14 import datetime |
|
15 import socket |
|
16 import sys |
|
17 |
|
18 import psutil |
|
19 |
|
20 |
|
21 def convert_bytes(n): |
|
22 symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') |
|
23 prefix = {} |
|
24 for i, s in enumerate(symbols): |
|
25 prefix[s] = 1 << (i+1)*10 |
|
26 for s in reversed(symbols): |
|
27 if n >= prefix[s]: |
|
28 value = float(n) / prefix[s] |
|
29 return '%.1f%s' % (value, s) |
|
30 return "%sB" % n |
|
31 |
|
32 def print_(a, b): |
|
33 if sys.stdout.isatty() and os.name == 'posix': |
|
34 fmt = '\x1b[1;32m%-17s\x1b[0m %s' %(a, b) |
|
35 else: |
|
36 fmt = '%-15s %s' %(a, b) |
|
37 # python 2/3 compatibility layer |
|
38 sys.stdout.write(fmt + '\n') |
|
39 sys.stdout.flush() |
|
40 |
|
41 def run(pid): |
|
42 ACCESS_DENIED = '' |
|
43 try: |
|
44 p = psutil.Process(pid) |
|
45 pinfo = p.as_dict(ad_value=ACCESS_DENIED) |
|
46 except psutil.NoSuchProcess: |
|
47 sys.exit(str(sys.exc_info()[1])) |
|
48 |
|
49 try: |
|
50 if p.parent: |
|
51 parent = '(%s)' % p.parent.name |
|
52 else: |
|
53 parent = '' |
|
54 except psutil.Error: |
|
55 parent = '' |
|
56 started = datetime.datetime.fromtimestamp(pinfo['create_time'] |
|
57 ).strftime('%Y-%M-%d %H:%M') |
|
58 io = pinfo.get('io_counters', ACCESS_DENIED) |
|
59 mem = '%s%% (resident=%s, virtual=%s) ' % ( |
|
60 round(pinfo['memory_percent'], 1), |
|
61 convert_bytes(pinfo['memory_info'].rss), |
|
62 convert_bytes(pinfo['memory_info'].vms)) |
|
63 children = p.get_children() |
|
64 |
|
65 print_('pid', pinfo['pid']) |
|
66 print_('name', pinfo['name']) |
|
67 print_('exe', pinfo['exe']) |
|
68 print_('parent', '%s %s' % (pinfo['ppid'], parent)) |
|
69 print_('cmdline', ' '.join(pinfo['cmdline'])) |
|
70 print_('started', started) |
|
71 print_('user', pinfo['username']) |
|
72 if os.name == 'posix' and pinfo['uids'] and pinfo['gids']: |
|
73 print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids']) |
|
74 if os.name == 'posix' and pinfo['gids']: |
|
75 print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids']) |
|
76 if os.name == 'posix': |
|
77 print_('terminal', pinfo['terminal'] or '') |
|
78 if hasattr(p, 'getcwd'): |
|
79 print_('cwd', pinfo['cwd']) |
|
80 print_('memory', mem) |
|
81 print_('cpu', '%s%% (user=%s, system=%s)' % (pinfo['cpu_percent'], |
|
82 getattr(pinfo['cpu_times'], 'user', '?'), |
|
83 getattr(pinfo['cpu_times'], 'system', '?'))) |
|
84 print_('status', pinfo['status']) |
|
85 print_('niceness', pinfo['nice']) |
|
86 print_('num threads', pinfo['num_threads']) |
|
87 if io != ACCESS_DENIED: |
|
88 print_('I/O', 'bytes-read=%s, bytes-written=%s' % \ |
|
89 (convert_bytes(io.read_bytes), |
|
90 convert_bytes(io.write_bytes))) |
|
91 if children: |
|
92 print_('children', '') |
|
93 for child in children: |
|
94 print_('', 'pid=%s name=%s' % (child.pid, child.name)) |
|
95 |
|
96 if pinfo['open_files'] != ACCESS_DENIED: |
|
97 print_('open files', '') |
|
98 for file in pinfo['open_files']: |
|
99 print_('', 'fd=%s %s ' % (file.fd, file.path)) |
|
100 |
|
101 if pinfo['threads']: |
|
102 print_('running threads', '') |
|
103 for thread in pinfo['threads']: |
|
104 print_('', 'id=%s, user-time=%s, sys-time=%s' \ |
|
105 % (thread.id, thread.user_time, thread.system_time)) |
|
106 if pinfo['connections'] != ACCESS_DENIED: |
|
107 print_('open connections', '') |
|
108 for conn in pinfo['connections']: |
|
109 if conn.type == socket.SOCK_STREAM: |
|
110 type = 'TCP' |
|
111 elif conn.type == socket.SOCK_DGRAM: |
|
112 type = 'UDP' |
|
113 else: |
|
114 type = 'UNIX' |
|
115 lip, lport = conn.laddr |
|
116 if not conn.raddr: |
|
117 rip, rport = '*', '*' |
|
118 else: |
|
119 rip, rport = conn.raddr |
|
120 print_('', '%s:%s -> %s:%s type=%s status=%s' \ |
|
121 % (lip, lport, rip, rport, type, conn.status)) |
|
122 |
|
123 def main(argv=None): |
|
124 if argv is None: |
|
125 argv = sys.argv |
|
126 if len(argv) == 1: |
|
127 sys.exit(run(os.getpid())) |
|
128 elif len(argv) == 2: |
|
129 sys.exit(run(int(argv[1]))) |
|
130 else: |
|
131 sys.exit('usage: %s [pid]' % __file__) |
|
132 |
|
133 if __name__ == '__main__': |
|
134 sys.exit(main()) |