Python Forum
ptb.py - process trace back for linux
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ptb.py - process trace back for linux
#1
this script is a command for linux to trace back a specified process (or itself if none specified) through its ancestry to help a sysadmin figure out where a mystery process came from. run the script giving it a process id or just run it w/o one. it stops at pid 1.

you can download it from here or just use the copy below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division, generators, print_function, with_statement
import os
from subprocess import call
from sys import argv, stderr, stdin, stdout, version_info

def parpid(pid):
    pid=str(pid)
    if not int(pid):
        return None
    fn='/proc/'+pid+'/status'
    with open(fn) as s:
        for line in s:
            a,b = line.split()[:2]
            if a=='PPid:':
                return b

def dopids(pid):
    pid=str(pid)
    pids=[pid]
    while pid:
        pid=int(pid)
        pid=parpid(pid)
        if not int(pid):
            return pids
        pids.append(str(pid))

def main(args):
    s=None
    this=os.getpid()
    if len(args)>1:
        for arg in argv[1:]:
            s=dopids(arg)
    else:
        s=dopids(os.getpid())
    print(' '.join(s))
    cmd=['ps']
    for p in s:
        call(cmd+[p])
        cmd[1:2]=['h']
    return 0

if __name__ == '__main__':
    if version_info.major < 3:
        BrokenPipeError = IOError
    try:
        result=main(argv)
        stdout.flush()
    except BrokenPipeError:
        result = 99
    except KeyboardInterrupt:
        print('')
        result = 98
    if result is 0 or result is None or result is True:
        exit(0)
    if result is 1 or result is False:
        exit(1)
    if isinstance(result,str):
        print(result,file=stderr)
        exit(2)
    try:
        exit(int(result))
    except ValueError:
        print(str(result),file=stderr)
        exit(3)
    except TypeError:
        exit(4)
# EOF
the extra imports are from my initial template file and i'm too lazy to remove them.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
Interesting. Did you consider using module psutil in order to avoid calls to ps?
Reply
#3
(Feb-05-2018, 08:33 AM)Gribouillis Wrote: Interesting. Did you consider using module psutil in order to avoid calls to ps?
no. does it make things simpler and more readable? can it do what my calls to ps do in fewer lines? have you memorized all the third party modules out there and what they do.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#4
Here is an attempt using psutil
import argparse
import os
import psutil as ps


def parse_args():
    parser = argparse.ArgumentParser(description='Displays ancestors of a process')
    parser.add_argument('pid', help='pid of process to show (defaults to this process)', default='-1', type=int, metavar='PID', nargs='?')
    args = parser.parse_args()
    if args.pid < 0: args.pid = os.getpid()
    return args

def main():
    args = parse_args()
    tpl = "{:>8} {:>15s} {:>12s} {:>10} {}"
    print(tpl.format('PID','TTY', 'STATUS', 'UTIME', 'COMMAND'))
    p = ps.Process(args.pid)
    while p is not None:
        row = (p.pid, p.terminal() or '?', p.status(), p.cpu_times().user, ' '.join(p.cmdline()))
        print(tpl.format(*row))
        p = p.parent()

if __name__ == '__main__':
    main()
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020