-
-
Save eMPee584/5883444 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ strace-process-tree zdaemon-py3.GIT/TRACE3 | |
6184 execve("bin/test", ["bin/test", "-pvc", "-t", "README"], [/* 65 vars */]) | |
├─6196 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -p 'echo hello world' "...], [/* 67 vars */]) | |
│ └─6197 execve("./zdaemon", ["./zdaemon", "-p", "echo hello world", "fg"], [/* 67 vars */]) | |
│ └─6199 execve("/bin/echo", ["echo", "hello", "world"], [/* 67 vars */]) | |
├─6200 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -p 'sleep 100' start"], [/* 67 vars */]) | |
│ └─6201 execve("./zdaemon", ["./zdaemon", "-p", "sleep 100", "start"], [/* 67 vars */]) | |
│ └─6205 execve("/usr/bin/python3.3", ["/usr/bin/python3.3", "./zdaemon", "-S", "schema.xml", "-b", "10", "-s", "zdsock", "-m", "0o22", "-x", "0,2", "sleep", "100"], [/* 68 vars */]) | |
│ └─6212 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f163fcab9d0) | |
│ ├─6213 clone(child_stack=0x7f163e4b4ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f163e4b59d0, tls=0x7f163e4b5700, child_tidptr=0x7f163e4b59d0) | |
│ └─6214 execve("/bin/sleep", ["sleep", "100"], [/* 67 vars */]) | |
├─6215 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -p 'sleep 100' status"], [/* 67 vars */]) | |
│ └─6216 execve("./zdaemon", ["./zdaemon", "-p", "sleep 100", "status"], [/* 67 vars */]) | |
├─6217 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -p 'sleep 100' stop"], [/* 67 vars */]) | |
│ └─6218 execve("./zdaemon", ["./zdaemon", "-p", "sleep 100", "stop"], [/* 67 vars */]) | |
├─6220 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -p 'sleep 100' status"], [/* 67 vars */]) | |
│ └─6221 execve("./zdaemon", ["./zdaemon", "-p", "sleep 100", "status"], [/* 67 vars */]) | |
├─6225 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf start"], [/* 67 vars */]) | |
│ └─6226 execve("./zdaemon", ["./zdaemon", "-Cconf", "start"], [/* 67 vars */]) | |
│ └─6253 execve("/usr/bin/python3.3", ["/usr/bin/python3.3", "./zdaemon", "-S", "/home/mg/src/zdaemon-py3.GIT/src"..., "-C", "conf", "sleep", "100"], [/* 68 vars */]) | |
│ └─6262 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd2a97bf9d0) | |
│ ├─6263 clone(child_stack=0x7fd2a7fc8ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fd2a7fc99d0, tls=0x7fd2a7fc9700, child_tidptr=0x7fd2a7fc99d0) | |
│ └─6264 execve("/bin/sleep", ["sleep", "100"], [/* 67 vars */]) | |
├─6269 execve("/bin/sh", ["/bin/sh", "-c", "ls"], [/* 67 vars */]) | |
│ └─6270 execve("/bin/ls", ["ls"], [/* 67 vars */]) | |
├─6271 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf stop"], [/* 67 vars */]) | |
│ └─6272 execve("./zdaemon", ["./zdaemon", "-Cconf", "stop"], [/* 67 vars */]) | |
├─6278 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf start"], [/* 67 vars */]) | |
│ └─6279 execve("./zdaemon", ["./zdaemon", "-Cconf", "start"], [/* 67 vars */]) | |
│ └─6288 execve("/usr/bin/python3.3", ["/usr/bin/python3.3", "./zdaemon", "-S", "/home/mg/src/zdaemon-py3.GIT/src"..., "-C", "conf", "sleep", "100"], [/* 68 vars */]) | |
│ └─6294 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f44cb0e79d0) | |
│ ├─6295 clone(child_stack=0x7f44c98f0ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f44c98f19d0, tls=0x7f44c98f1700, child_tidptr=0x7f44c98f19d0) | |
│ └─6296 execve("/bin/sleep", ["sleep", "100"], [/* 67 vars */]) | |
├─6298 execve("/bin/sh", ["/bin/sh", "-c", "ls"], [/* 67 vars */]) | |
│ └─6300 execve("/bin/ls", ["ls"], [/* 67 vars */]) | |
├─6301 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf stop"], [/* 67 vars */]) | |
│ └─6302 execve("./zdaemon", ["./zdaemon", "-Cconf", "stop"], [/* 67 vars */]) | |
├─6304 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf start 100"], [/* 67 vars */]) | |
│ └─6305 execve("./zdaemon", ["./zdaemon", "-Cconf", "start", "100"], [/* 67 vars */]) | |
│ └─6314 execve("/usr/bin/python3.3", ["/usr/bin/python3.3", "./zdaemon", "-S", "/home/mg/src/zdaemon-py3.GIT/src"..., "-C", "conf", "sleep", "100"], [/* 68 vars */]) | |
│ └─6322 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff8f14959d0) | |
│ ├─6323 clone(child_stack=0x7ff8efc9eff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7ff8efc9f9d0, tls=0x7ff8efc9f700, child_tidptr=0x7ff8efc9f9d0) | |
│ └─6324 execve("/bin/sleep", ["sleep", "100"], [/* 67 vars */]) | |
├─6333 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf status"], [/* 67 vars */]) | |
│ └─6334 execve("./zdaemon", ["./zdaemon", "-Cconf", "status"], [/* 67 vars */]) | |
├─6346 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf stop"], [/* 67 vars */]) | |
│ └─6347 execve("./zdaemon", ["./zdaemon", "-Cconf", "stop"], [/* 67 vars */]) | |
├─6348 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf fg"], [/* 67 vars */]) | |
│ └─6349 execve("./zdaemon", ["./zdaemon", "-Cconf", "fg"], [/* 67 vars */]) | |
│ └─6350 execve("/usr/bin/env", ["env"], [/* 68 vars */]) | |
├─6351 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf start"], [/* 67 vars */]) | |
│ └─6352 execve("./zdaemon", ["./zdaemon", "-Cconf", "start"], [/* 67 vars */]) | |
│ └─6354 execve("/usr/bin/python3.3", ["/usr/bin/python3.3", "./zdaemon", "-S", "/home/mg/src/zdaemon-py3.GIT/src"..., "-C", "conf", "tail", "-f", "data"], [/* 68 vars */]) | |
│ └─6380 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb4506119d0) | |
│ ├─6381 clone(child_stack=0x7fb44ee1aff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fb44ee1b9d0, tls=0x7fb44ee1b700, child_tidptr=0x7fb44ee1b9d0) | |
│ └─6382 execve("/usr/bin/tail", ["tail", "-f", "data"], [/* 67 vars */]) | |
└─6399 execve("/bin/sh", ["/bin/sh", "-c", "./zdaemon -Cconf reopen_transcri"...], [/* 67 vars */]) | |
└─6400 execve("./zdaemon", ["./zdaemon", "-Cconf", "reopen_transcript"], [/* 67 vars */]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: UTF-8 -*- | |
""" | |
Usage: | |
strace-process-tree [filename] | |
Read strace -f output and produce a process tree. | |
""" | |
import re | |
import fileinput | |
from collections import defaultdict | |
__version__ = '0.2.2' | |
__author__ = 'Marius Gedminas <marius@gedmin.as>' | |
__url__ = 'https://gist.github.com/mgedmin/4953427' | |
__licence__ = 'GPL v2 or later' # or ask me for MIT | |
def events(stream): | |
RESUMED_PREFIX = re.compile('<... \w+ resumed> ') | |
UNFINISHED_SUFFIX = ' <unfinished ...>' | |
pending = {} | |
for line in stream: | |
pid, spaces, event = line.rstrip().partition(' ') | |
pid = int(pid) | |
event = event.lstrip() | |
m = RESUMED_PREFIX.match(event) | |
if m is not None: | |
event = pending.pop(pid) + event[len(m.group()):] | |
if event.endswith(UNFINISHED_SUFFIX): | |
pending[pid] = event[:-len(UNFINISHED_SUFFIX)] | |
else: | |
yield (pid, event) | |
class ProcessTree: | |
def __init__(self): | |
self.names = {} | |
self.parents = {} | |
self.children = defaultdict(list) | |
self.roots = set() | |
self.all = set() | |
# invariant: self.roots == self.all - set(self.parents), probably | |
def make_known(self, pid): | |
if pid not in self.all: | |
self.roots.add(pid) | |
self.all.add(pid) | |
def set_name(self, pid, name): | |
self.make_known(pid) | |
self.names[pid] = name | |
def add_child(self, ppid, pid): | |
self.make_known(ppid) | |
self.make_known(pid) | |
if pid in self.roots: | |
self.roots.remove(pid) | |
self.parents[pid] = ppid | |
self.children[ppid].append(pid) | |
def _format(self, pids, indent='', level=0): | |
r = [] | |
for n, pid in enumerate(pids): | |
if level == 0: | |
s, cs = '', '' | |
elif n < len(pids) - 1: | |
s, cs = ' ├─', ' │ ' | |
else: | |
s, cs = ' └─', ' ' | |
r.append(indent + s + '{} {}\n'.format(pid, self.names.get(pid, ''))) | |
r.append(self._format(sorted(self.children.get(pid, [])), | |
indent+cs, level+1)) | |
return ''.join(r) | |
def __str__(self): | |
return self._format(sorted(self.roots)) | |
def main(): | |
tree = ProcessTree() | |
for pid, event in events(fileinput.input()): | |
if event.startswith('execve('): | |
args, equal, result = event.rpartition(' = ') | |
if result == '0': | |
tree.set_name(pid, args) | |
if event.startswith('clone('): | |
args, equal, result = event.rpartition(' = ') | |
if result.isdigit(): | |
child_pid = int(result) | |
tree.set_name(child_pid, args) | |
tree.add_child(pid, child_pid) | |
print(str(tree).rstrip()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment