linuxproc.py

Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Zope Public License (ZPL) Version 1.0
00004 # -------------------------------------
00005 #
00006 # Copyright (c) Digital Creations.  All rights reserved.
00007 #
00008 # This license has been certified as Open Source(tm).
00009 #
00010 # Redistribution and use in source and binary forms, with or without
00011 # modification, are permitted provided that the following conditions are
00012 # met:
00013 #
00014 # 1. Redistributions in source code must retain the above copyright
00015 #    notice, this list of conditions, and the following disclaimer.
00016 #
00017 # 2. Redistributions in binary form must reproduce the above copyright
00018 #    notice, this list of conditions, and the following disclaimer in
00019 #    the documentation and/or other materials provided with the
00020 #    distribution.
00021 #
00022 # 3. Digital Creations requests that attribution be given to Zope
00023 #    in any manner possible. Zope includes a "Powered by Zope"
00024 #    button that is installed by default. While it is not a license
00025 #    violation to remove this button, it is requested that the
00026 #    attribution remain. A significant investment has been put
00027 #    into Zope, and this effort will continue if the Zope community
00028 #    continues to grow. This is one way to assure that growth.
00029 #
00030 # 4. All advertising materials and documentation mentioning
00031 #    features derived from or use of this software must display
00032 #    the following acknowledgement:
00033 #
00034 #      "This product includes software developed by Digital Creations
00035 #      for use in the Z Object Publishing Environment
00036 #      (http://www.zope.org/)."
00037 #
00038 #    In the event that the product being advertised includes an
00039 #    intact Zope distribution (with copyright and license included)
00040 #    then this clause is waived.
00041 #
00042 # 5. Names associated with Zope or Digital Creations must not be used to
00043 #    endorse or promote products derived from this software without
00044 #    prior written permission from Digital Creations.
00045 #
00046 # 6. Modified redistributions of any form whatsoever must retain
00047 #    the following acknowledgment:
00048 #
00049 #      "This product includes software developed by Digital Creations
00050 #      for use in the Z Object Publishing Environment
00051 #      (http://www.zope.org/)."
00052 #
00053 #    Intact (re-)distributions of any official Zope release do not
00054 #    require an external acknowledgement.
00055 #
00056 # 7. Modifications are encouraged but must be packaged separately as
00057 #    patches to official Zope releases.  Distributions that do not
00058 #    clearly separate the patches from the original work must be clearly
00059 #    labeled as unofficial distributions.  Modifications which do not
00060 #    carry the name Zope may be packaged in any form, as long as they
00061 #    conform to all of the clauses above.
00062 #
00063 #
00064 # Disclaimer
00065 #
00066 #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
00067 #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00068 #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00069 #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
00070 #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00071 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00072 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00073 #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00074 #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00075 #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00076 #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00077 #   SUCH DAMAGE.
00078 #
00079 #
00080 # This software consists of contributions made by Digital Creations and
00081 # many individuals on behalf of Digital Creations.  Specific
00082 # attributions are listed in the accompanying credits file.
00083 #
00084 ##############################################################################
00085 """ module for investigating the Linux /proc filesystem
00086 
00087 """
00088 import os, re, string
00089 __ext_version__ = '1.0'          # External code revision
00090 __version__ = '$Revision: 1.2 $' # LICOS version
00091 
00092 DIGITS = {}
00093 for d  in "1234567890":
00094     DIGITS[d] = 1
00095 
00096 # linux 2_2_18 /proc/self/stat format
00097 l2_2_18_procstat = [
00098     'pid', 'comm', 'state', 'ppid', 'pgrp', 'session', 'tty', 'tty_pgrp',
00099     'flags', 'min_flt', 'cmin_flt', 'maj_flt', 'cmaj_flt', 'utime',
00100     'stime', 'cutime', 'cstime', 'priority', 'nice', 'NULL',
00101     'it_real_value', 'start_time', 'vsize', 'rss', 'rlim', 'start_code',
00102     'end_code', 'start_stack', 'esp', 'eip', 'signal',
00103     'blocked', 'sigign', 'sigcatch', 'wchan', 'nswap', 'cnswap',
00104     'exit_signal', 'processor'
00105     ]
00106 
00107 # linux 2_2_18 /proc/loadavg format
00108 l2_2_18_loadavg = ['1min', '5min', '15min', 'running', 'cumulative']
00109 
00110 # linux 2_2_18 /proc/uptime format
00111 l2_2_18_uptime = ['uptime', 'idle']
00112 
00113 # linux 2_2_18 /proc/self/statm format
00114 l2_2_18_procstatm = ['size', 'resident', 'shared', 'trs', 'drs', 'lrs', 'dt']
00115 
00116 # linix 2_2_18 /proc/stat format
00117 l2_2_18_stat = {
00118     'cpu'       : ['user', 'nice', 'system', 'idle'],
00119     'disk'      : ['unknown1', 'unknown2', 'unknown3'],
00120     'disk_rio'  : ['unknown1', 'unknown2', 'unknown3'],
00121     'disk_wio'  : ['unknown1', 'unknown2', 'unknown3'],
00122     'disk_rblk' : ['unknown1', 'unknown2', 'unknown3'],
00123     'disk_wblk' : ['unknown1', 'unknown2', 'unknown3'],
00124     'page'      : ['in', 'out'],
00125     'swap'      : ['in', 'out'],
00126     'intr'      : ['interrupts'],
00127     'ctxt'      : ['context_switches'],
00128     'btime'     : ['boot_time'],
00129     'processes' : ['processes'],
00130     }
00131 
00132 # Linux 2_4_2 /proc/stat info
00133 l2_4_2_stat = {
00134     'cpu'       : ['user', 'nice', 'system', 'idle'],
00135     'cpu0'      : ['user', 'nice', 'system', 'idle'],
00136     'cpu1'      : ['user', 'nice', 'system', 'idle'],
00137     'cpu2'      : ['user', 'nice', 'system', 'idle'],
00138     'cpu3'      : ['user', 'nice', 'system', 'idle'],
00139     'cpu4'      : ['user', 'nice', 'system', 'idle'],
00140     'cpu5'      : ['user', 'nice', 'system', 'idle'],
00141     'cpu6'      : ['user', 'nice', 'system', 'idle'],
00142     'cpu7'      : ['user', 'nice', 'system', 'idle'],
00143     'cpu8'      : ['user', 'nice', 'system', 'idle'],
00144     'cpu9'      : ['user', 'nice', 'system', 'idle'],
00145     'cpu10'     : ['user', 'nice', 'system', 'idle'],
00146     'cpu11'     : ['user', 'nice', 'system', 'idle'],
00147     'page'      : ['in', 'out'],
00148     'swap'      : ['in', 'out'],
00149     'intr'      : ['interrupts'],
00150     'disk_io'   : ['unknown1', 'unknown2', 'unknown3'],
00151     'ctxt'      : ['context_switches'],
00152     'btime'     : ['boot_time'],
00153     'processes' : ['processes'],
00154     }
00155 
00156 version_map = {
00157     ('2','2','18'): { 'procstat' : l2_2_18_procstat,
00158                       'loadavg' : l2_2_18_loadavg,
00159                       'uptime' : l2_2_18_uptime,
00160                       'stat': l2_2_18_stat,
00161                       'procstatm' : l2_2_18_procstatm,
00162                       },
00163     ('2','4','2') : { 'procstat' : l2_2_18_procstat,
00164                       'loadavg' : l2_2_18_loadavg,
00165                       'uptime' : l2_2_18_uptime,
00166                       'stat': l2_4_2_stat,
00167                       'procstatm' : l2_2_18_procstatm,
00168                       },
00169     }
00170 
00171 version_guess_map = {
00172     ('2', '2')  :  ('2', '2', '18'),
00173     ('2', '4')  :  ('2', '4', '2'),
00174     ('2', '6')  :  ('2', '4', '2'),
00175     }
00176 
00177 def get_struct(v, vmap=version_map.get, guess=version_guess_map.get):
00178     return vmap(v) or vmap(guess(tuple(v[:2])))
00179 
00180 def get_kernel_version():
00181     version_match = re.compile(r'(\d+)\.(\d+)\.(\d+)').search
00182     s = open('/proc/version').readline()
00183     match = version_match(s)
00184     return (match.group(1), match.group(2), match.group(3))
00185 
00186 VERSION = get_kernel_version()
00187 
00188 def proc_statm(pid):
00189     return get_dict('procstatm', '/proc/%s/statm' % pid)
00190 
00191 def self_statm():
00192     return get_dict('procstatm', '/proc/self/statm')
00193 
00194 def proc_stat(pid):
00195     return get_dict('procstat', '/proc/%s/stat' % pid)
00196 
00197 def self_stat():
00198     return get_dict('procstat', '/proc/self/stat')
00199 
00200 def loadavg():
00201     return get_dict('loadavg', '/proc/loadavg')
00202 
00203 def uptime():
00204     return get_dict('uptime', '/proc/uptime')
00205 
00206 def stat():
00207     return get_multidict('stat', '/proc/stat')
00208 
00209 def meminfo():
00210     """ very expensive on 2.2 kernels, not so on 2.4 kernels """
00211     lines = []; dict = {}
00212     for line in open('/proc/meminfo').readlines():
00213         if line:
00214             l = string.split(line)
00215             name, value = l[0], l[1:]
00216             if name in('total:', 'Mem:', 'Swap:'):
00217                 continue
00218             key = string.lower(name)[:-1]
00219             value = value[0]
00220             if value and DIGITS.has_key(value[0]):
00221                 value = maybe_number(value)
00222             dict[key] = value
00223     return dict
00224 
00225 def getrunners(getsleepers=0, isdigit=DIGITS.has_key):
00226     running = []; swapped = []; blocked = []; sleeping = []
00227     addtorun   = running.append
00228     addtoswap  = swapped.append
00229     addtoblock = blocked.append
00230     addtosleep = sleeping.append
00231     names = os.listdir('/proc')
00232     for name in names:
00233         excp_happened = 0
00234         if isdigit(name[0]):
00235             try: stat = proc_stat(name)
00236             except: excp_happened = 1
00237             if excp_happened: continue
00238             state = stat['state']
00239             rss   = stat['rss']
00240             if getsleepers and state == "S":
00241                 addtosleep(name)
00242             elif state == "R":
00243                 if rss > 0: addtorun(name)
00244                 else: addtoswap(name)
00245             elif state == "D":
00246                 if rss > 0: addtoblock(name)
00247                 else: addtoswap(name)
00248     if getsleepers:
00249         return running, blocked, swapped, sleeping
00250     else:
00251         return running, blocked, swapped
00252 
00253 def get_dict(structname, filename, isdigit=DIGITS.has_key,
00254              find=string.find):
00255     lookup = get_struct(VERSION)[structname]
00256     d = {}; i = 0
00257     raw = string.split(open(filename).readline())
00258     for value in raw:
00259         if value and isdigit(value[0]):
00260             value = maybe_number(value)
00261         try:
00262             name = lookup[i]
00263             d[name] = value
00264         except:
00265             pass
00266         i = i + 1
00267     return d
00268 
00269 def get_multidict(structname, filename, isdigit=DIGITS.has_key,
00270                   find=string.find):
00271     dict = {}
00272     lookup = get_struct(VERSION)[structname]
00273     for line in open(filename, 'r').readlines():
00274         l = string.split(line)
00275         category = l[0]
00276         if not lookup.has_key(category):
00277             continue
00278         items = l[1:]
00279         d = {}; i = 0
00280         for name in lookup[category]:
00281             value = items[i]
00282             if value and isdigit(value[0]):
00283                 value = maybe_number(value)
00284             d[name] = value
00285             i = i + 1
00286         dict[category] = d
00287     return dict
00288 
00289 def maybe_number(value, find=string.find, float=float, int=int):
00290     try:
00291         if find(value, '.') != -1:
00292             return float(value)
00293         else:
00294             return int(value)
00295     except ValueError:
00296         return value
00297 
00298 if __name__ == '__main__':
00299     import time
00300     start = time.time()
00301     for x in xrange(100):
00302         getrunners()
00303         uptime()
00304         loadavg()
00305         self_statm()
00306         self_stat()
00307         stat()
00308         meminfo()
00309     end = time.time()
00310     print end-start
00311     #import sys
00312     #sys.exit(0)
00313     for key, value in self_stat().items():
00314          print key, value
00315     for key, value in loadavg().items():
00316           print key, value
00317     for key, value in uptime().items():
00318           print key, value
00319     for key, value in stat().items():
00320           print key, value
00321     for key, value in meminfo().items():
00322           print key, value
00323     for key, value in self_statm().items():
00324           print key, value
00325 
00326 

Generated on Thu Apr 27 20:52:42 2006 for LICOS L02-01-00 by doxygen 1.4.6-NO