7
"""Print detailed information about a process.
9
Author: Giampaolo Rodola' <g.rodola@gmail.com>
11
$ python3 scripts/procinfo.py
15
exe /opt/google/chrome/chrome
17
cmdline /opt/google/chrome/chrome
18
started 2016-09-19 11:12
20
cpu-times user=8914.32, system=3530.59,
21
children_user=1.46, children_system=1.31
22
cpu-affinity [0, 1, 2, 3, 4, 5, 6, 7]
23
memory rss=520.5M, vms=1.9G, shared=132.6M, text=95.0M, lib=0B,
27
uids real=1000, effective=1000, saved=1000
28
uids real=1000, effective=1000, saved=1000
32
ionice class=IOPriority.IOPRIO_CLASS_NONE, value=0
35
I/O read_count=96.6M, write_count=80.7M,
36
read_bytes=293.2M, write_bytes=24.5G
37
ctx-switches voluntary=30426463, involuntary=460108
44
/opt/google/chrome/icudtl.dat
45
/opt/google/chrome/snapshot_blob.bin
46
/opt/google/chrome/natives_blob.bin
47
/opt/google/chrome/chrome_100_percent.pak
49
connections PROTO LOCAL ADDR REMOTE ADDR STATUS
50
UDP 10.0.0.3:3693 *:* NONE
51
TCP 10.0.0.3:55102 172.217.22.14:443 ESTABLISHED
52
UDP 10.0.0.3:35172 *:* NONE
53
TCP 10.0.0.3:32922 172.217.16.163:443 ESTABLISHED
55
UDP 10.0.0.3:59925 *:* NONE
56
threads TID USER SYSTEM
63
res-limits RLIMIT SOFT HARD
64
virtualmem infinity infinity
65
coredumpsize 0 infinity
66
cputime infinity infinity
67
datasize infinity infinity
68
filesize infinity infinity
69
locks infinity infinity
71
msgqueue 819200 819200
74
maxprocesses 63304 63304
77
rtimesched infinity infinity
78
sigspending 63304 63304
79
stack 8388608 infinity
82
62.8M /opt/google/chrome/chrome
83
15.8M /home/giampaolo/.config/google-chrome/Default/History
84
6.6M /home/giampaolo/.config/google-chrome/Default/Favicons
94
from psutil._common import bytes2human
98
NON_VERBOSE_ITERATIONS = 4
100
"RLIMIT_AS": "virtualmem",
101
"RLIMIT_CORE": "coredumpsize",
102
"RLIMIT_CPU": "cputime",
103
"RLIMIT_DATA": "datasize",
104
"RLIMIT_FSIZE": "filesize",
105
"RLIMIT_MEMLOCK": "memlock",
106
"RLIMIT_MSGQUEUE": "msgqueue",
107
"RLIMIT_NICE": "nice",
108
"RLIMIT_NOFILE": "openfiles",
109
"RLIMIT_NPROC": "maxprocesses",
110
"RLIMIT_NPTS": "pseudoterms",
112
"RLIMIT_RTPRIO": "realtimeprio",
113
"RLIMIT_RTTIME": "rtimesched",
114
"RLIMIT_SBSIZE": "sockbufsize",
115
"RLIMIT_SIGPENDING": "sigspending",
116
"RLIMIT_STACK": "stack",
117
"RLIMIT_SWAP": "swapuse",
122
if sys.stdout.isatty() and psutil.POSIX:
123
fmt = '\x1b[1;32m%-13s\x1b[0m %s' % (a, b)
125
fmt = '%-11s %s' % (a, b)
129
def str_ntuple(nt, convert_bytes=False):
130
if nt == ACCESS_DENIED:
132
if not convert_bytes:
133
return ", ".join(["%s=%s" % (x, getattr(nt, x)) for x in nt._fields])
136
["%s=%s" % (x, bytes2human(getattr(nt, x))) for x in nt._fields]
140
def run(pid, verbose=False):
142
proc = psutil.Process(pid)
143
pinfo = proc.as_dict(ad_value=ACCESS_DENIED)
144
except psutil.NoSuchProcess as err:
150
parent = proc.parent()
151
parent = '(%s)' % parent.name() if parent else ''
155
pinfo['children'] = proc.children()
157
pinfo['children'] = []
158
if pinfo['create_time']:
159
started = datetime.datetime.fromtimestamp(
161
).strftime('%Y-%m-%d %H:%M')
163
started = ACCESS_DENIED
166
print_('pid', pinfo['pid'])
167
print_('name', pinfo['name'])
168
print_('parent', '%s %s' % (pinfo['ppid'], parent))
169
print_('exe', pinfo['exe'])
170
print_('cwd', pinfo['cwd'])
171
print_('cmdline', ' '.join(pinfo['cmdline']))
172
print_('started', started)
174
cpu_tot_time = datetime.timedelta(seconds=sum(pinfo['cpu_times']))
175
cpu_tot_time = "%s:%s.%s" % (
176
cpu_tot_time.seconds // 60 % 60,
177
str(cpu_tot_time.seconds % 60).zfill(2),
178
str(cpu_tot_time.microseconds)[:2],
180
print_('cpu-tspent', cpu_tot_time)
181
print_('cpu-times', str_ntuple(pinfo['cpu_times']))
182
if hasattr(proc, "cpu_affinity"):
183
print_("cpu-affinity", pinfo["cpu_affinity"])
184
if hasattr(proc, "cpu_num"):
185
print_("cpu-num", pinfo["cpu_num"])
187
print_('memory', str_ntuple(pinfo['memory_info'], convert_bytes=True))
188
print_('memory %', round(pinfo['memory_percent'], 2))
189
print_('user', pinfo['username'])
191
print_('uids', str_ntuple(pinfo['uids']))
193
print_('uids', str_ntuple(pinfo['uids']))
195
print_('terminal', pinfo['terminal'] or '')
197
print_('status', pinfo['status'])
198
print_('nice', pinfo['nice'])
199
if hasattr(proc, "ionice"):
201
ionice = proc.ionice()
206
print_("ionice", ionice)
210
"class=%s, value=%s" % (str(ionice.ioclass), ionice.value),
213
print_('num-threads', pinfo['num_threads'])
215
print_('num-fds', pinfo['num_fds'])
217
print_('num-handles', pinfo['num_handles'])
219
if 'io_counters' in pinfo:
220
print_('I/O', str_ntuple(pinfo['io_counters'], convert_bytes=True))
221
if 'num_ctx_switches' in pinfo:
222
print_("ctx-switches", str_ntuple(pinfo['num_ctx_switches']))
223
if pinfo['children']:
225
print_("children", template % ("PID", "NAME"))
226
for child in pinfo['children']:
228
print_('', template % (child.pid, child.name()))
229
except psutil.AccessDenied:
230
print_('', template % (child.pid, ""))
231
except psutil.NoSuchProcess:
234
if pinfo['open_files']:
235
print_('open-files', 'PATH')
236
for i, file in enumerate(pinfo['open_files']):
237
if not verbose and i >= NON_VERBOSE_ITERATIONS:
240
print_('', file.path)
242
print_('open-files', '')
244
if pinfo['net_connections']:
245
template = '%-5s %-25s %-25s %s'
248
template % ('PROTO', 'LOCAL ADDR', 'REMOTE ADDR', 'STATUS'),
250
for conn in pinfo['net_connections']:
251
if conn.type == socket.SOCK_STREAM:
253
elif conn.type == socket.SOCK_DGRAM:
257
lip, lport = conn.laddr
259
rip, rport = '*', '*'
261
rip, rport = conn.raddr
264
"%s:%s" % (lip, lport),
265
"%s:%s" % (rip, rport),
270
print_('connections', '')
272
if pinfo['threads'] and len(pinfo['threads']) > 1:
273
template = "%-5s %12s %12s"
274
print_('threads', template % ("TID", "USER", "SYSTEM"))
275
for i, thread in enumerate(pinfo['threads']):
276
if not verbose and i >= NON_VERBOSE_ITERATIONS:
279
print_('', template % thread)
280
print_('', "total=%s" % len(pinfo['threads']))
282
print_('threads', '')
284
if hasattr(proc, "rlimit"):
285
res_names = [x for x in dir(psutil) if x.startswith("RLIMIT")]
287
for res_name in res_names:
289
soft, hard = proc.rlimit(getattr(psutil, res_name))
290
except psutil.AccessDenied:
293
resources.append((res_name, soft, hard))
295
template = "%-12s %15s %15s"
296
print_("res-limits", template % ("RLIMIT", "SOFT", "HARD"))
297
for res_name, soft, hard in resources:
298
if soft == psutil.RLIM_INFINITY:
300
if hard == psutil.RLIM_INFINITY:
305
% (RLIMITS_MAP.get(res_name, res_name), soft, hard),
308
if hasattr(proc, "environ") and pinfo['environ']:
309
template = "%-25s %s"
310
print_("environ", template % ("NAME", "VALUE"))
311
for i, k in enumerate(sorted(pinfo['environ'])):
312
if not verbose and i >= NON_VERBOSE_ITERATIONS:
315
print_("", template % (k, pinfo['environ'][k]))
317
if pinfo.get('memory_maps', None):
319
print_("mem-maps", template % ("RSS", "PATH"))
320
maps = sorted(pinfo['memory_maps'], key=lambda x: x.rss, reverse=True)
321
for i, region in enumerate(maps):
322
if not verbose and i >= NON_VERBOSE_ITERATIONS:
325
print_("", template % (bytes2human(region.rss), region.path))
329
parser = argparse.ArgumentParser(
330
description="print information about a process"
332
parser.add_argument("pid", type=int, help="process pid", nargs='?')
334
'--verbose', '-v', action='store_true', help="print more info"
336
args = parser.parse_args()
337
run(args.pid, args.verbose)
340
if __name__ == '__main__':