#!/usr/bin/env python2.4 import sys import os import subprocess import errors # TODO: minimise shell/process calls def execute(*args, **kwargs): if isinstance(args, tuple): args = list(args) PIPE = subprocess.PIPE p = subprocess.Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs) p.wait() errors = p.stderr.read() if errors: raise OSError("Error executing %s:\n%s" % (" ".join(args), errors)) return p.stdout.read() def exec_dcop(*args): args = [str(arg) for arg in args] print "calling dcop with %r" % args return execute("dcop", *args, **{"env": {"DISPLAY": ":0.0", "HOME": "/home/davidf"}}).split("\n") try: # using native python dcop may be slightly faster import pcop def dcop(*args): if len(args) == 0: return pcop.app_list() elif len(args) == 1: return pcop.obj_list(*args) elif len(args) >= 3: return str(pcop.dcop_call(args[0], args[1], args[2], args[3:])) else: return exec_dcop(*args) except ImportError: dcop = exec_dcop def shell(*args): return execute(*args, **{"shell": True}) def list_konsole_processes(): processlist = shell("ps --no-heading -o uid,pid -C konsole") for processline in processlist.split("\n"): if not processline: continue uid, pid = processline.strip().split() uid = uid.strip() if not uid.isdigit(): continue pid = pid.strip() if not pid.isdigit(): continue yield int(uid), int(pid) class Process: """OS process analyzer""" def __init__(self, pid): if isinstance(pid, (str, unicode)): self.pid = int(pid) else: self.pid = pid self.cmdline, self.cwd, self.exe, self.env, self.fds, self.children = None, None, None, {}, [], {} self.get_proc_info() self.uid = shell("ps --no-heading -o '%%u' %d" % self.pid).strip() self.get_children() def safe_read(self, filename): """returns contents of file, but won't raise an error on IO problems (e.g. permissions)""" try: return open(filename).read() except Exception, e: return "" def safe_readlink(self, filename): """returns contents of file, but won't raise an error on IO problems (e.g. permissions)""" try: return os.readlink(filename) except Exception, e: return "" def safe_listdir(self, dirname): """returns contents of file, but won't raise an error on IO problems (e.g. permissions)""" try: return os.listdir(dirname) except Exception, e: return [] def get_proc_info(self): """reads information about the process from /proc""" procdir = os.path.join("/proc", str(self.pid)) self.cmdline = self.safe_read(os.path.join(procdir, "cmdline")).replace("\0", " ") self.cwd = self.safe_readlink(os.path.join(procdir, "cwd")) self.exe = self.safe_readlink(os.path.join(procdir, "exe")) environ_items = self.safe_read(os.path.join(procdir, "environ")).split("\0") self.env = {} for environ_item in environ_items: if not environ_item: continue if "=" not in environ_item: continue variable, value = environ_item.split("=", 1) self.env[variable] = value fddir = os.path.join(procdir, "fd") self.fds = [] for fd in self.safe_listdir(fddir): fullfd = os.path.join(fddir, fd) if os.path.islink(fullfd): fdfile = self.safe_readlink(fullfd) if fdfile is not None: self.fds.append(fdfile) def get_vim_info(self): """gets vim-specific info""" swapfiles = {} for fd in self.fds: basefd = os.path.basename(fd) fddir = os.path.dirname(fd) if basefd.startswith(".") and basefd[:-1].endswith(".sw"): filename = os.path.join(fddir, basefd[1:-4]) swapfiles[fd] = filename return swapfiles def get_children(self): """finds child process IDs and creates child Process objects in self.children""" child_pids = shell("pgrep -P %d" % self.pid).split() self.children = {} for child_pid in child_pids: if not child_pid: continue child_pid = int(child_pid) self.children[child_pid] = Process(child_pid) def plaintree(self, indent=0): """prints out a process tree with the given indent""" # plaintree = shell("pstree -alupG %s" % session_pid, shell=True) print " "*indent + self.cmdline + "[%s@%s]" % (self.uid, self.cwd) for child, child_process in self.children.iteritems(): child_process.plaintree(indent+2) def htmltree(self): """prints out a process tree with the given indent""" html = "
Konsole session at %s
" % time.asctime()) konsolefile.write(html) konsolefile.write("") konsolefile.close() except Exception, e: open("/var/log/cron", "a").write("Exception on konsole: %s\n" % str(e)) continue indexhtml += "" % (konsolefilename, konsole.pid) endtime = time.time() indexhtml += "Generated in %0.2f seconds
" % (endtime-starttime) indexhtml += "" indexfile = open(os.path.join(basedir, "index.html"), "w") indexfile.write(indexhtml) indexfile.close() else: starttime = time.time() print "" print "Generated in %0.2f seconds
" % (endtime-starttime) print "" if __name__ == "__main__": if "--html" in sys.argv: try: # pcop.dcop_call("konsole-6972", "konsole", "sessionCount", ()) main() except Exception, e: from jToolkit import errors xlog("error: %s" % errors.ConsoleErrorHandler().traceback_str()) else: plain()