source: cmfdeployment/branches/kenw-p4-wip/lib/linuxproc.py @ 2380

Last change on this file since 2380 was 2380, checked in by kenw, 8 years ago

Committing new branch intended for Plone 4 compatibility; mostly required imports of new zope packages

File size: 11.1 KB
Line 
1##############################################################################
2#
3# Zope Public License (ZPL) Version 1.0
4# -------------------------------------
5#
6# Copyright (c) Digital Creations.  All rights reserved.
7#
8# This license has been certified as Open Source(tm).
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are
12# met:
13#
14# 1. Redistributions in source code must retain the above copyright
15#    notice, this list of conditions, and the following disclaimer.
16#
17# 2. Redistributions in binary form must reproduce the above copyright
18#    notice, this list of conditions, and the following disclaimer in
19#    the documentation and/or other materials provided with the
20#    distribution.
21#
22# 3. Digital Creations requests that attribution be given to Zope
23#    in any manner possible. Zope includes a "Powered by Zope"
24#    button that is installed by default. While it is not a license
25#    violation to remove this button, it is requested that the
26#    attribution remain. A significant investment has been put
27#    into Zope, and this effort will continue if the Zope community
28#    continues to grow. This is one way to assure that growth.
29#
30# 4. All advertising materials and documentation mentioning
31#    features derived from or use of this software must display
32#    the following acknowledgement:
33#
34#      "This product includes software developed by Digital Creations
35#      for use in the Z Object Publishing Environment
36#      (http://www.zope.org/)."
37#
38#    In the event that the product being advertised includes an
39#    intact Zope distribution (with copyright and license included)
40#    then this clause is waived.
41#
42# 5. Names associated with Zope or Digital Creations must not be used to
43#    endorse or promote products derived from this software without
44#    prior written permission from Digital Creations.
45#
46# 6. Modified redistributions of any form whatsoever must retain
47#    the following acknowledgment:
48#
49#      "This product includes software developed by Digital Creations
50#      for use in the Z Object Publishing Environment
51#      (http://www.zope.org/)."
52#
53#    Intact (re-)distributions of any official Zope release do not
54#    require an external acknowledgement.
55#
56# 7. Modifications are encouraged but must be packaged separately as
57#    patches to official Zope releases.  Distributions that do not
58#    clearly separate the patches from the original work must be clearly
59#    labeled as unofficial distributions.  Modifications which do not
60#    carry the name Zope may be packaged in any form, as long as they
61#    conform to all of the clauses above.
62#
63#
64# Disclaimer
65#
66#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
67#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
70#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
71#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
72#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
73#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
74#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
75#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
76#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77#   SUCH DAMAGE.
78#
79#
80# This software consists of contributions made by Digital Creations and
81# many individuals on behalf of Digital Creations.  Specific
82# attributions are listed in the accompanying credits file.
83#
84##############################################################################
85""" module for investigating the Linux /proc filesystem
86
87"""
88import os, re, string
89__version__ = '1.0'
90
91DIGITS = {}
92for d  in "1234567890":
93    DIGITS[d] = 1
94
95# linux 2_2_18 /proc/self/stat format
96l2_2_18_procstat = [
97    'pid', 'comm', 'state', 'ppid', 'pgrp', 'session', 'tty', 'tty_pgrp',
98    'flags', 'min_flt', 'cmin_flt', 'maj_flt', 'cmaj_flt', 'utime',
99    'stime', 'cutime', 'cstime', 'priority', 'nice', 'NULL',
100    'it_real_value', 'start_time', 'vsize', 'rss', 'rlim', 'start_code',
101    'end_code', 'start_stack', 'esp', 'eip', 'signal',
102    'blocked', 'sigign', 'sigcatch', 'wchan', 'nswap', 'cnswap',
103    'exit_signal', 'processor'
104    ]
105
106# linux 2_2_18 /proc/loadavg format
107l2_2_18_loadavg = ['1min', '5min', '15min', 'running', 'cumulative']
108
109# linux 2_2_18 /proc/uptime format
110l2_2_18_uptime = ['uptime', 'idle']
111
112# linux 2_2_18 /proc/self/statm format
113l2_2_18_procstatm = ['size', 'resident', 'shared', 'trs', 'drs', 'lrs', 'dt']
114
115# linix 2_2_18 /proc/stat format
116l2_2_18_stat = {
117    'cpu'       : ['user', 'nice', 'system', 'idle'],
118    'disk'      : ['unknown1', 'unknown2', 'unknown3'],
119    'disk_rio'  : ['unknown1', 'unknown2', 'unknown3'],
120    'disk_wio'  : ['unknown1', 'unknown2', 'unknown3'],
121    'disk_rblk' : ['unknown1', 'unknown2', 'unknown3'],
122    'disk_wblk' : ['unknown1', 'unknown2', 'unknown3'],
123    'page'      : ['in', 'out'],
124    'swap'      : ['in', 'out'],
125    'intr'      : ['interrupts'],
126    'ctxt'      : ['context_switches'],
127    'btime'     : ['boot_time'],
128    'processes' : ['processes'],
129    }
130
131# Linux 2_4_2 /proc/stat info
132l2_4_2_stat = {
133    'cpu'       : ['user', 'nice', 'system', 'idle'],
134    'cpu0'      : ['user', 'nice', 'system', 'idle'],
135    'cpu1'      : ['user', 'nice', 'system', 'idle'],
136    'cpu2'      : ['user', 'nice', 'system', 'idle'],
137    'cpu3'      : ['user', 'nice', 'system', 'idle'],
138    'cpu4'      : ['user', 'nice', 'system', 'idle'],
139    'cpu5'      : ['user', 'nice', 'system', 'idle'],
140    'cpu6'      : ['user', 'nice', 'system', 'idle'],
141    'cpu7'      : ['user', 'nice', 'system', 'idle'],
142    'cpu8'      : ['user', 'nice', 'system', 'idle'],
143    'cpu9'      : ['user', 'nice', 'system', 'idle'],
144    'cpu10'     : ['user', 'nice', 'system', 'idle'],
145    'cpu11'     : ['user', 'nice', 'system', 'idle'],
146    'page'      : ['in', 'out'],
147    'swap'      : ['in', 'out'],
148    'intr'      : ['interrupts'],
149    'disk_io'   : ['unknown1', 'unknown2', 'unknown3'],
150    'ctxt'      : ['context_switches'],
151    'btime'     : ['boot_time'],
152    'processes' : ['processes'],
153    }
154
155version_map = {
156    ('2','2','18'): { 'procstat' : l2_2_18_procstat,
157                      'loadavg' : l2_2_18_loadavg,
158                      'uptime' : l2_2_18_uptime,
159                      'stat': l2_2_18_stat,
160                      'procstatm' : l2_2_18_procstatm,
161                      },
162    ('2','4','2') : { 'procstat' : l2_2_18_procstat,
163                      'loadavg' : l2_2_18_loadavg,
164                      'uptime' : l2_2_18_uptime,
165                      'stat': l2_4_2_stat,
166                      'procstatm' : l2_2_18_procstatm,
167                      },
168    }
169
170version_guess_map = {
171    ('2', '2')  :  ('2', '2', '18'),
172    ('2', '4')  :  ('2', '4', '2'),
173    }
174
175def get_struct(v, vmap=version_map.get, guess=version_guess_map.get):
176    return vmap(v) or vmap(guess(tuple(v[:2])))
177
178def get_kernel_version():
179    version_match = re.compile(r'(\d+)\.(\d+)\.(\d+)').search
180    s = open('/proc/version').readline()
181    match = version_match(s)
182    return (match.group(1), match.group(2), match.group(3))
183
184VERSION = get_kernel_version()
185
186def proc_statm(pid):
187    return get_dict('procstatm', '/proc/%s/statm' % pid)
188   
189def self_statm():
190    return get_dict('procstatm', '/proc/self/statm')
191
192def proc_stat(pid):
193    return get_dict('procstat', '/proc/%s/stat' % pid)
194
195def self_stat():
196    return get_dict('procstat', '/proc/self/stat')
197
198def loadavg():
199    return get_dict('loadavg', '/proc/loadavg')
200
201def uptime():
202    return get_dict('uptime', '/proc/uptime')
203
204def stat():
205    return get_multidict('stat', '/proc/stat')
206
207def meminfo():
208    """ very expensive on 2.2 kernels, not so on 2.4 kernels """
209    lines = []; dict = {}
210    for line in open('/proc/meminfo').readlines():
211        if line:
212            l = string.split(line)
213            name, value = l[0], l[1:]
214            if name in('total:', 'Mem:', 'Swap:'):
215                continue
216            key = string.lower(name)[:-1]
217            value = value[0]
218            if value and DIGITS.has_key(value[0]):
219                value = maybe_number(value)
220            dict[key] = value
221    return dict
222
223def getrunners(getsleepers=0, isdigit=DIGITS.has_key):
224    running = []; swapped = []; blocked = []; sleeping = []
225    addtorun   = running.append
226    addtoswap  = swapped.append
227    addtoblock = blocked.append
228    addtosleep = sleeping.append
229    names = os.listdir('/proc')
230    for name in names:
231        excp_happened = 0
232        if isdigit(name[0]):
233            try: stat = proc_stat(name)
234            except: excp_happened = 1
235            if excp_happened: continue
236            state = stat['state']
237            rss   = stat['rss']
238            if getsleepers and state == "S":
239                addtosleep(name)
240            elif state == "R":
241                if rss > 0: addtorun(name)
242                else: addtoswap(name)
243            elif state == "D":
244                if rss > 0: addtoblock(name)
245                else: addtoswap(name)
246    if getsleepers:
247        return running, blocked, swapped, sleeping
248    else:
249        return running, blocked, swapped
250
251def get_dict(structname, filename, isdigit=DIGITS.has_key,
252             find=string.find):
253    lookup = get_struct(VERSION)[structname]
254    d = {}; i = 0
255    raw = string.split(open(filename).readline())
256    for value in raw:
257        if value and isdigit(value[0]):
258            value = maybe_number(value)
259        name = lookup[i]
260        d[name] = value
261        i = i + 1
262    return d
263
264def get_multidict(structname, filename, isdigit=DIGITS.has_key,
265                  find=string.find):
266    dict = {}
267    lookup = get_struct(VERSION)[structname]
268    for line in open(filename, 'r').readlines():
269        l = string.split(line)
270        category = l[0]
271        if not lookup.has_key(category):
272            continue
273        items = l[1:]
274        d = {}; i = 0
275        for name in lookup[category]:
276            value = items[i]
277            if value and isdigit(value[0]):
278                value = maybe_number(value)
279            d[name] = value
280            i = i + 1
281        dict[category] = d
282    return dict
283
284def maybe_number(value, find=string.find, float=float, int=int):
285    try:
286        if find(value, '.') != -1:
287            return float(value)
288        else:
289            return int(value)
290    except ValueError:
291        return value
292
293if __name__ == '__main__':
294    import time
295    start = time.time()
296    for x in xrange(100):
297        print x
298        getrunners()
299        uptime()
300        loadavg()
301        self_statm()
302        self_stat()
303        stat()
304        meminfo()
305    end = time.time()
306    print end-start
307    #import sys
308    #sys.exit(0)
309    for key, value in self_stat().items():
310         print key, value
311    for key, value in loadavg().items():
312          print key, value
313    for key, value in uptime().items():
314          print key, value
315    for key, value in stat().items():
316          print key, value
317    for key, value in meminfo().items():
318          print key, value
319    for key, value in self_statm().items():
320          print key, value
321
322
Note: See TracBrowser for help on using the repository browser.