#! /usr/bin/python # -*- python -*- # -*- coding: utf-8 -*- # Copyright (C) 2009 Red Hat Inc. # Written by Arnaldo Carvalho de Melo # # This application is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2. # # This application is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. import getopt, inet_diag, os, re, procfs, pwd, sys version="0.2" state_width = 10 addr_width = 15 timer_width = 7 owner_width = 8 def load_sockets(): idiag = inet_diag.create() inodes = {} while True: try: s = idiag.get() except: break inodes[s.inode()] = s return inodes ps = None inode_re = None inodes = None def thread_mapper(s): global ps try: return [ int(s), ] except: pass if not ps: ps = procfs.pidstats() try: return ps.find_by_regex(re.compile(fnmatch.translate(s))) except: return ps.find_by_name(s) def print_sockets(pid, indent = 0): header_printed = False dirname = "/proc/%d/fd" % pid try: filenames = os.listdir(dirname) except: # Process died return for filename in filenames: pathname = os.path.join(dirname, filename) try: linkto = os.readlink(pathname) except: # Process died continue inode_match = inode_re.match(linkto) if not inode_match: continue inode = int(inode_match.group(1)) if not inodes.has_key(inode): continue if not header_printed: try: print "\n%s%d: %s" % (indent * " ", pid, procfs.process_cmdline(ps[pid])) except: return print " %-*s %-6s %-6s %*s:%-5s %*s:%-5s %-*s %-*s %-5s %-3s" % \ (state_width, "State", "Recv-Q", "Send-Q", addr_width, "Local Address", "Port", addr_width, "Peer Address", "Port", owner_width, "Owner", timer_width, "Timer", "(ms)", "Rtm") header_printed = True s = inodes[inode] owner = pwd.getpwuid(s.uid())[0] print " %-*s %-6d %-6d %*s:%-5d %*s:%-5d %-*s %-*s %-5d %-3d" % \ (state_width, s.state(), s.receive_queue(), s.write_queue(), addr_width, s.saddr(), s.sport(), addr_width, s.daddr(), s.dport(), owner_width, owner, timer_width, s.timer(), s.timer_expiration(), s.retransmissions()) def usage(): print '''Usage: psk [ OPTIONS ] psk [ OPTIONS ] [PID-LIST] -h, --help this message -V, --version output version information''' def main(): global ps, inode_re, inodes try: opts, args = getopt.getopt(sys.argv[1:], "hV", ("help", "version")) except getopt.GetoptError, err: usage() print str(err) sys.exit(2) for o, a in opts: if o in ( "-V", "--version"): print version return else: usage() return if args: pid_list = reduce(lambda i, j: i + j, map(thread_mapper, args)) inodes = load_sockets() ps = procfs.pidstats() pids = ps.keys() pids.sort() inode_re = re.compile(r"socket:\[(\d+)\]") ps.reload_threads() for pid in pids: if args and pid not in pid_list: continue print_sockets(pid) if ps[pid].has_key("threads"): for tid in ps[pid]["threads"].keys(): print_sockets(tid, 1) if __name__ == '__main__': main()