blob: 8d4aa99ea196b3bdd1a667a29fdb57db4bcd563c [file] [log] [blame]
#! /usr/bin/python
# -*- python -*-
# -*- coding: utf-8 -*-
# Copyright (C) 2009 Red Hat Inc.
# Written by Arnaldo Carvalho de Melo <acme@redhat.com>
#
# 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.1"
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()