blob: 1acdf2a6e6e909dc91513f2f7f07445bc48b634b [file] [log] [blame]
#!/usr/bin/env python
# The MIT License
#
# Copyright (C) 2007 Chris Miles
#
# Copyright (C) 2009 Floris Bruynooghe
#
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""process_details.py
Display information about a running process.
"""
__author__ = 'Chris Miles'
__copyright__ = """\
Copyright (C) 2007 Chris Miles
Copyright (C) 2009 Floris Bruynooghe
"""
__version__ = '0.2'
import grp
import optparse
import os
import pwd
import sys
from datetime import datetime
import psi.arch
import psi.process
help_message = 'Display information about a running process'
def run(pid):
a = psi.arch.arch_type()
print "Python %s / PSI %s / %s %s" % (
'.'.join([str(v) for v in sys.version_info[:3]]),
psi.__version__,
a.sysname,
a.release
)
try:
p = psi.process.Process(pid)
except ValueError, e:
sys.stderr.write("%s\n"%e)
return 1
print "\nProcess information:"
fmt = " %-20s: %s"
print fmt %('Process ID', p.pid)
print fmt %('Parent Process ID', p.ppid)
print fmt %('Executable', getattr(p, 'exe', 'N/A'))
print fmt %('Command', p.command)
try:
v = ' '.join(p.args)
except psi.AttrInsufficientPrivsError, e:
v = str(e)
print fmt %('Full Command', v)
print fmt %('Effective user', '%s (%d)'
% (pwd.getpwuid(p.euid).pw_name, p.euid))
print fmt %('Real user', '%s (%d)'
% (pwd.getpwuid(p.ruid).pw_name, p.ruid))
print fmt %('Effective group', '%s (%d)'
%(grp.getgrgid(p.egid).gr_name, p.egid))
print fmt %('Real group', '%s (%d)'
% (grp.getgrgid(p.rgid).gr_name, p.rgid))
print fmt %('Process group', p.pgrp)
print fmt %('Number of threads', getattr(p, 'nthreads', 'N/A'))
print fmt %('Started', str(p.start_time.datetime()))
try:
status = p.status
except AttributeError, e:
value = str(e)
else:
all_status = [(s, getattr(psi.process, s)) for s in dir(psi.process)
if s.startswith('PROC_STATUS_')]
proc_status = [s[0] for s in all_status if status == s[1]]
value = ', '.join(proc_status)
print fmt %('Status', value)
print fmt %('Terminal device', getattr(p, 'terminal', 'N/A'))
print fmt %('Environment', getattr(p, 'env', 'N/A'))
print "\nCPU Use:"
print fmt %('CPU seconds used', str(p.cputime.timedelta()))
try:
print ' '*24 + '(User: %s System: %s)' % (p.utime.timedelta(),
p.stime.timedelta())
except AttributeError:
pass
print fmt %('Recent CPU used', getattr(p, 'pcpu', 'N/A'))
print fmt %('Nice level', getattr(p, 'nice', 'N/A'))
print fmt %('Priority', getattr(p, 'priority', 'N/A'))
print "\nMemory Use:"
print fmt %('Resident memory used', p.rss)
print fmt %('Virtual memory used', p.vsz)
def main(argv=None):
if argv is None:
argv = sys.argv
# define usage and version messages
usageMsg = "usage: %s [options] pid" % sys.argv[0]
versionMsg = """%s %s""" % (os.path.basename(argv[0]), __version__)
# get a parser object and define our options
parser = optparse.OptionParser(usage=usageMsg, version=versionMsg)
parser.add_option('-S', '--self', dest='self',
action='store_true', default=False,
help="Show information about itself")
# Parse options & arguments
(options, args) = parser.parse_args()
if len(args) < 1 and not options.self:
parser.error("A process ID must be specified.")
if len(args) > 1:
parser.error("Only one process ID can be specified.")
if options.self:
# introspect itself
pid = os.getpid()
else:
try:
pid = int(args[0])
except:
parser.error("Invalid process ID.")
return run(pid)
if __name__ == "__main__":
sys.exit(main())