psutil
1#!/usr/bin/env python3
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"""Similar to 'ps aux --forest' on Linux, prints the process list
8as a tree structure.
9
10$ python3 scripts/pstree.py
110 ?
12|- 1 init
13| |- 289 cgmanager
14| |- 616 upstart-socket-bridge
15| |- 628 rpcbind
16| |- 892 upstart-file-bridge
17| |- 907 dbus-daemon
18| |- 978 avahi-daemon
19| | `_ 979 avahi-daemon
20| |- 987 NetworkManager
21| | |- 2242 dnsmasq
22| | `_ 10699 dhclient
23| |- 993 polkitd
24| |- 1061 getty
25| |- 1066 su
26| | `_ 1190 salt-minion...
27...
28"""
29
30from __future__ import print_function31
32import collections33import sys34
35import psutil36
37
38def print_tree(parent, tree, indent=''):39try:40name = psutil.Process(parent).name()41except psutil.Error:42name = "?"43print(parent, name)44if parent not in tree:45return46children = tree[parent][:-1]47for child in children:48sys.stdout.write(indent + "|- ")49print_tree(child, tree, indent + "| ")50child = tree[parent][-1]51sys.stdout.write(indent + "`_ ")52print_tree(child, tree, indent + " ")53
54
55def main():56# construct a dict where 'values' are all the processes57# having 'key' as their parent58tree = collections.defaultdict(list)59for p in psutil.process_iter():60try:61tree[p.ppid()].append(p.pid)62except (psutil.NoSuchProcess, psutil.ZombieProcess):63pass64# on systems supporting PID 0, PID 0's parent is usually 065if 0 in tree and 0 in tree[0]:66tree[0].remove(0)67print_tree(min(tree), tree)68
69
70if __name__ == '__main__':71main()72