Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added python 1.5 version and few fixes.

  • Loading branch information...
commit 84e1f26d1fe842316b18a9ef89b258f879740f1d 1 parent 38094bf
@dagwieers authored
Showing with 1,148 additions and 6 deletions.
  1. +4 −1 ChangeLog
  2. +8 −5 dstat
  3. +1,136 −0 dstat15
View
5 ChangeLog
@@ -1,3 +1,6 @@
+* 0.5.4
+- Added a python 1.5 version of dstat (Ville Herva)
+
* 0.5.3
- Added -M or --mods option to allow modules
- Added --full option to expand the -D, -I and -N discovery lists
@@ -8,7 +11,7 @@
- Added --tcp and --udp stats (may be improved later ?)
- Fixes to disk24old and new cpu24 (for Debian 2.4.26 kernel)
- Signal handling cleanup
-- Partitions are excluded from discovered on 2.4 kernels
+- Partitions are excluded from discovery on 2.4 kernels
* 0.5.2
- Improved disk and net discovery functions (Ville Herva)
View
13 dstat
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as published by
@@ -356,7 +356,7 @@ class dstat_disk(dstat):
if name in self.vars:
self.cn2[name] = ( self.cn2[name][0] + long(l[5]), self.cn2[name][1] + long(l[9]) )
for set in self.vars:
- if set in self.diskset and name in self.diskset[set]:
+ if set in self.diskset.keys() and name in self.diskset[set]:
self.cn2[set] = ( self.cn2[set][0] + long(l[5]), self.cn2[set][1] + long(l[9]) )
self.cn2['total'] = ( self.cn2['total'][0] + long(l[5]), self.cn2['total'][1] + long(l[9]) )
if update:
@@ -917,8 +917,11 @@ def getwinsize():
s = struct.pack("HHHH", 0, 0, 0, 0)
x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
return struct.unpack("HHHH", x)[:2]
- except IOError:
- return (25, 80)
+ except:
+ try:
+ return (int(os.environ['LINES']), int(os.environ['COLUMNS']))
+ except:
+ return (25, 80)
def getcpunr():
procs = 0
@@ -1037,7 +1040,7 @@ def main():
plist.append(o)
### Check when to display the header
- if oldplist != plist or (loop == 0 or op.header) and step == op.delay and loop % (rows-1) == 0:
+ if oldplist != plist or (loop == 0 or op.header) and step == op.delay and loop % (rows - 1) == 0:
for o in plist:
sys.stdout.write(o.title1)
if o != plist[-1]:
View
1,136 dstat15
@@ -0,0 +1,1136 @@
+#!/usr/bin/env python
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; version 2 only
+#
+# This program 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 Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Copyright 2004 Dag Wieers <dag@wieers.com>
+
+#from __future__ import generators
+import fcntl, struct, termios
+import os, sys, re, getopt, time, string
+import ConfigParser, urlparse, signal, resource
+
+VERSION = "0.5.3"
+
+enable = ('yes', 'on', 'true', '1')
+disable = ('no', 'off', 'false', '0')
+
+class Options:
+ def __init__(self, args):
+ self.count = -1
+ self.delay = 1
+ self.disklist = None
+ self.full = False
+ self.integer = False
+ self.intlist = None
+ self.netlist = None
+ self.color = True
+ self.update = True
+ self.header = True
+
+ try:
+ opts, args = getopt.getopt (args, 'acdghilmnpstvyD:I:M:N:',
+ ['all', 'cpu', 'disk', 'help', 'int', 'load', 'mem', 'net', 'page',
+ 'proc', 'swap', 'sys', 'tcp', 'time', 'udp', 'version', 'vmstat',
+ 'full', 'integer', 'mods', 'modules', 'nocolor', 'noheader', 'noupdate'])
+ except getopt.error, exc:
+ print 'dstat: %s, try dstat -h for a list of all the options' % str(exc)
+ sys.exit(1)
+
+ self.modlist = []
+
+ for opt, arg in opts:
+ if opt in ['-c', '--cpu']:
+ self.modlist.append('cpu')
+ elif opt in ['-d', '--disk']:
+ self.modlist.append('disk')
+ elif opt in ['-D']:
+ self.disklist = string.split(arg,',')
+ elif opt in ['-i', '--int']:
+ self.modlist.append('int')
+ elif opt in ['-g', '--page']:
+ self.modlist.append('page')
+ elif opt in ['-I']:
+ self.intlist = string.split(arg, ',')
+ elif opt in ['-m', '--mem']:
+ self.modlist.append('mem')
+ elif opt in ['-M', '--mods', '--modules']:
+ self.modlist = self.modlist + string.split(arg, ',')
+ elif opt in ['-l', '--load']:
+ self.modlist.append('load')
+ elif opt in ['-n', '--net']:
+ self.modlist.append('net')
+ elif opt in ['-N']:
+ self.netlist = string.split(arg, ',')
+ elif opt in ['-p', '--proc']:
+ self.modlist.append('proc')
+ elif opt in ['-s', '--swap']:
+ self.modlist.append('swap')
+ elif opt in ['--tcp']:
+ self.modlist.append('tcp')
+ elif opt in ['-t', '--time']:
+ self.modlist.append('time')
+ elif opt in ['--udp']:
+ self.modlist.append('udp')
+ elif opt in ['-y', '--sys']:
+ self.modlist.append('sys')
+
+ elif opt in ['-a', '--all']:
+ self.modlist = self.modlist + [ 'cpu', 'disk', 'net', 'page', 'sys', 'load' ]
+ elif opt in ['-v', '--vmstat']:
+ self.modlist = self.modlist + [ 'proc', 'mem', 'page', 'disk', 'sys', 'cpu' ]
+ self.disklist = ('total',)
+
+ elif opt in ['--full']:
+ self.full = True
+ elif opt in ['--integer']:
+ self.integer = True
+ elif opt in ['--nocolor']:
+ self.color = False
+ elif opt in ['--noheader']:
+ self.header = False
+ elif opt in ['--noupdate']:
+ self.update = False
+
+ elif opt in ['-h', '--help']:
+ self.usage()
+ self.help()
+ sys.exit(0)
+ elif opt in ['-v', '--version']:
+ self.version()
+ sys.exit(0)
+
+ if not self.modlist:
+ self.modlist = [ 'cpu', 'disk', 'net', 'sys', 'page' ]
+
+ if len(args) > 0:
+ self.delay = int(args[0])
+
+ if len(args) > 1:
+ self.count = int(args[1])
+
+ if self.delay == 0:
+ die(6, 'Delay must be an integer, greater than zero')
+
+ def version(self):
+ print 'Dstat %s' % VERSION
+ print 'Written by Dag Wieers <dag@wieers.com>'
+ print 'Homepage at http://dag.wieers.com/home-made/dstat/'
+ print
+ print 'Platform %s/%s' % (os.name, sys.platform)
+ print 'Kernel %s' % os.uname()[2]
+ print 'Python %s' % sys.version
+
+ def usage(self):
+ print 'usage: dstat [-av] [-cdgilmnpsty] [-D dev1..] [-I #..] [-N if1..] [delay [count]]'
+
+ def help(self):
+ print '''Versatile tool for generating system resource statistics
+
+Dstat options:
+ -c, --cpu enable cpu stats
+ -d, --disk enable disk stats
+ -D total,hda include hda and total
+ -g, --page enable page stats
+ -i, --int enable interrupt stats
+ -I 5,eth2 include int5 and interrupt used by eth2
+ -l, --load enable load stats
+ -m, --mem enable memory stats
+ -n, --net enable network stats
+ -N eth1,total include eth1 and total
+ -p, --proc enable process stats
+ -s, --swap enable swap stats
+ -t, --time enable time counter
+ -y, --sys enable system stats
+
+ -M stat1,stat2 enable specific stats
+ --mods stat1,stat2
+
+ Possible stats are:
+ cpu, disk, page, int, load, mem, net, proc,
+ swap, sys, tcp, time, udp
+
+ -a, --all equals -cdngyl
+ -v, --vmstat equals -pmgdsc -D total
+
+ --full expand -D, -I and -N disovery lists
+ --integer show integer values
+ --nocolor disable colors
+ --noheader disable repetitive headers
+ --noupdate disable intermediate updates when delay > 1
+'''
+
+class Config:
+ def __init__(self):
+ self.configfile = op.configfile
+ self.cfg = ConfigParser.ConfigParser()
+
+ (s,b,p,q,f,o) = urlparse.urlparse(self.configfile)
+ if s in ('http', 'ftp', 'file'):
+ configfh = urllib.urlopen(self.configfile)
+ try:
+ self.cfg.readfp(configfh)
+ except ConfigParser.MissingSectionHeaderError, e:
+ die(6, 'Error accessing URL: %s' % self.configfile)
+ else:
+ if os.access(self.configfile, os.R_OK):
+ try:
+ self.cfg.read(self.configfile)
+ except:
+ die(7, 'Syntax error reading file: %s' % self.configfile)
+ else:
+ die(6, 'Error accessing file: %s' % self.configfile)
+
+ def getoption(self, section, option, var):
+ "Get an option from a section from configfile"
+ try:
+ var = self.cfg.get(section, option)
+ info(3, 'Setting option %s in section [%s] to: %s' % (option, section, var))
+ except ConfigParser.NoSectionError, e:
+ info(4, 'Failed to find section [%s] in %s' % (section, op.configfile))
+ except ConfigParser.NoOptionError, e:
+# info(4, 'Failed to find option %s in [%s], set to default: %s' % (option, section, var))
+ info(4, 'Setting option %s in section [%s] to: %s (default)' % (option, section, var))
+ return var
+
+class dstat:
+ def init(self):
+# if not self.check(): return
+
+ self.title1 = self.title1()
+ self.title2 = self.title2()
+
+ ### Initialise default variables
+ self.val = {}
+ self.cn1 = {}
+ self.cn2 = {}
+ for i in self.vars: self.val[i] = self.cn1[i] = self.cn2[i] = 0
+
+ def width(self):
+ return len(self.vars) * self.len + len(self.vars) - 1
+
+ def title1(self):
+ max = self.width()
+ return ansi['darkblue'] + string.replace(string.center(self.name[0:max-2],max), ' ', '-') + ansi['default']
+
+ def title2(self):
+ ret = ''
+ for str in self.nick:
+ ret = ret + string.replace(string.center(str[0:self.len], self.len), ' ', '_')
+ if str != self.nick[-1]: ret = ret + ' '
+ return ansi['blue'] + ret + ansi['default']
+
+ def check(self):
+ return True
+
+ def stats(self):
+ pass
+
+ def show(self):
+ sep = ' '
+ for name in self.vars:
+ if self.format == '%s':
+ sys.stdout.write(self.format % conv(self.len, self.val[name]))
+ elif self.format in ('%s %s', '%s:%s', '%s-%s'):
+ sys.stdout.write(self.format % convlist(self.len, self.val[name]))
+ sep = '|'
+ else:
+ sys.stdout.write(self.format % self.val[name])
+ if name != self.vars[-1]:
+ sys.stdout.write(sep)
+
+class dstat_cpu(dstat):
+ def __init__(self):
+ self.name = 'cpu usage'
+ self.vars = ('user', 'sys', 'idle', 'wait')
+ self.len = 3
+ self.format = '%3d'
+ self.nick = ( 'usr', 'sys', 'idl', 'wai' )
+ self.init()
+ self.cn1['total'] = 0
+
+ def check(self):
+ if os.path.exists('/proc/stat'):
+ l = string.split(open('/proc/stat', 'r').readline())
+ if len(l) > 5:
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line)
+ if len(l) <= 5 or l[0] != 'cpu': continue
+ self.cn2['user'] = long(l[1]) + long(l[2])
+ self.cn2['sys'] = long(l[3])
+ self.cn2['idle'] = long(l[4])
+ self.cn2['wait'] = long(l[5])
+ self.cn2['total'] = self.cn2['user'] + self.cn2['sys'] + self.cn2['idle'] + self.cn2['wait']
+ for name in self.vars:
+ self.val[name] = (100.0 * (self.cn2[name] - self.cn1[name]) + (self.cn2['total'] - self.cn1['total']) / 2) / (self.cn2['total'] - self.cn1['total'])
+ self.cn1.update(self.cn2)
+
+class dstat_cpu24(dstat):
+ def __init__(self):
+ self.name = 'cpu usage'
+ self.vars = ('user', 'sys', 'idle')
+ self.len = 3
+ self.format = '%3d'
+ self.nick = ( 'usr', 'sys', 'idl')
+ self.init()
+ self.cn1['total'] = 0
+
+ def check(self):
+ if os.path.exists('/proc/stat'):
+ l = string.split(open('/proc/stat', 'r').readline())
+ if len(l) == 5:
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 4 or l[0] != 'cpu': continue
+ self.cn2['user'] = long(l[1]) + long(l[2])
+ self.cn2['sys'] = long(l[3])
+ self.cn2['idle'] = long(l[4])
+ self.cn2['total'] = self.cn2['user'] + self.cn2['sys'] + self.cn2['idle']
+ for name in self.vars:
+ self.val[name] = (100.0 * (self.cn2[name] - self.cn1[name]) + (self.cn2['total'] - self.cn1['total']) / 2) / (self.cn2['total'] - self.cn1['total'])
+ self.cn1.update(self.cn2)
+
+class dstat_disk(dstat):
+ def __init__(self):
+ if not self.check(): return
+ self.format = '%s %s'
+ self.len = 11
+ self.name = 'disk i/o'
+ if op.disklist:
+ self.vars = op.disklist
+ else:
+ self.vars = self.discover()
+ ### Temporary hardcoded for my own project
+ self.diskset = {
+ 'local': ('sda', 'hda', 'hdc'),
+ 'lores': ('sdb', 'sdc', 'sdd', 'sde', 'sdf', 'sdg', 'sdh', 'sdi', 'sdj', 'sdk', 'sdl', 'sdm', 'sdn', 'sdo', 'sdp', 'sdq', 'sdr', 'sds', 'sdt'),
+ 'hires': ('sdu', 'sdv', 'sdw', 'sdx', 'sdy', 'sdz', 'sdaa', 'sdab', 'sdac', 'sdad' ),
+ }
+ self.nick = self.vars
+ self.init()
+
+ for name in self.vars: self.cn1[name] = (0, 0); self.cn1['total'] = (0, 0)
+ for name in self.vars: self.cn2[name] = (0, 0); self.cn2['total'] = (0, 0)
+ for name in self.vars: self.val[name] = (0, 0); self.val['total'] = (0, 0)
+
+ def discover(self):
+ retlist = []
+ for line in open('/proc/diskstats', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 13 or l[3] == '0': continue
+ name = l[2]
+ if not re.match('^(ram\d+|loop\d+)$', name):
+ retlist.append(name)
+ if not op.full and len(retlist) > 2: retlist = retlist[0:2]
+ retlist.sort()
+ return retlist
+
+ def check(self):
+ if os.path.exists('/proc/diskstats'):
+ return True
+ return False
+
+ def stats(self):
+ for name in self.vars: self.cn2[name] = (0, 0)
+ for line in open('/proc/diskstats', 'r').readlines():
+ l = string.split(line);
+ if len(l) < 13: continue
+ name = l[2]
+ if name in self.vars:
+ self.cn2[name] = ( self.cn2[name][0] + long(l[5]), self.cn2[name][1] + long(l[9]) )
+ for set in self.vars:
+ if set in self.diskset.keys() and name in self.diskset[set]:
+ self.cn2[set] = ( self.cn2[set][0] + long(l[5]), self.cn2[set][1] + long(l[9]) )
+ self.cn2['total'] = ( self.cn2['total'][0] + long(l[5]), self.cn2['total'][1] + long(l[9]) )
+ if update:
+ for name in self.cn2.keys():
+ self.val[name] = (
+ (self.cn2[name][0]-self.cn1[name][0]) * 512.0 / step,
+ (self.cn2[name][1]-self.cn1[name][1]) * 512.0 / step,
+ )
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_disk24(dstat_disk):
+ def discover(self):
+ retlist = []
+ for line in open('/proc/partitions', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 15 or l[0] == 'major' or int(l[1]) % 16 != 0: continue
+ name = l[3]
+ if not re.match('^(ram[0-9]+|loop[0-9]+|name)$', name):
+ retlist.append(name)
+ if not op.full and len(retlist) > 2: retlist = retlist[0:2]
+ retlist.sort()
+ return retlist
+
+ def check(self):
+ if os.path.exists('/proc/partitions') and not os.path.exists('/proc/diskstats'):
+ l = string.split(open('/proc/partitions', 'r').readline())
+ if len(l) > 4:
+ return True
+ return False
+
+ def stats(self):
+ for name in self.vars: self.cn2[name] = (0, 0)
+ for line in open('/proc/partitions', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 15: continue
+ name = l[3]
+ if name == 'name': continue
+ if name in self.vars:
+ self.cn2[name] = ( self.cn2[name][0] + long(l[6]), self.cn2[name][1] + long(l[10]) )
+ for set in self.vars:
+ if set in self.diskset and name in self.diskset[set]:
+ self.cn2[set] = ( self.cn2[set][0] + long(l[6]), self.cn2[set][1] + long(l[10]) )
+ self.cn2['total'] = ( self.cn2['total'][0] + long(l[6]), self.cn2['total'][1] + long(l[10]))
+ if update:
+ for name in self.cn2.keys():
+ self.val[name] = (
+ (self.cn2[name][0]-self.cn1[name][0]) * 512.0 / step,
+ (self.cn2[name][1]-self.cn1[name][1]) * 512.0 / step,
+ )
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_disk24old(dstat_disk24):
+ def discover(self):
+ retlist = []
+ for line in open('/proc/partitions', 'r').readlines():
+ l = string.split(line)
+ if len(l) != 4 or l[0] == 'major' or int(l[1]) % 16 != 0: continue
+ name = l[3]
+ if not re.match('^(ram[0-9]+|loop[0-9]+|name)$', name):
+ retlist.append(name)
+ if not op.full and len(retlist) > 2: retlist = retlist[0:2]
+ retlist.sort()
+ return retlist
+
+ def check(self):
+ if os.path.exists('/proc/stat') and \
+ not os.path.exists('/proc/diskstats'):
+ if os.path.exists('/proc/partitions'):
+ l = string.split(open('/proc/partitions', 'r').readline())
+ if len(l) <= 4:
+ return True
+ else:
+ return True
+ return False
+
+ def stats(self):
+ for name in self.vars: self.cn2[name] = (0, 0)
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line, ':');
+ if len(l) < 3: continue
+ name = l[0]
+ if name == 'disk_io':
+ for pair in string.split(line)[1:]:
+ m = re.match('^\((\d+),(\d+)\):\(\d+,\d+,(\d+),\d+,(\d+)\)$', pair)
+ if m:
+ l = m.groups()
+ name = dev(int(l[0]), int(l[1]))
+ self.cn2[name] = ( long(l[2]), long(l[3]) )
+ for set in self.vars:
+ if set in self.diskset.keys() and name in self.diskset[set]:
+ self.cn2[set] = ( self.cn2[set][0] + long(l[2]), self.cn2[set][1] + long(l[3]) )
+ self.cn2['total'] = ( self.cn2['total'][0] + long(l[2]), self.cn2['total'][1] + long(l[3]) )
+ if update:
+ for name in self.cn2.keys():
+ self.val[name] = (
+ (self.cn2[name][0]-self.cn1[name][0]) * 512.0 / step,
+ (self.cn2[name][1]-self.cn1[name][1]) * 512.0 / step,
+ )
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_int(dstat):
+ def __init__(self):
+ self.len = 5
+ self.format = '%5d'
+ self.name = 'interrupts'
+ if op.intlist:
+ self.vars = op.intlist
+ else:
+ self.vars = self.discover()
+ self.nick = self.vars
+ self.init()
+
+ def discover(self):
+ retlist = []
+ for line in open('/proc/interrupts', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 1: continue
+ name = string.split(l[0], ':')[0]
+ if name in ('0', '1', '2', '8', 'NMI', 'LOC', 'MIS', 'CPU0'): continue
+ if len(l) > 1 and l[1] != '0':
+ retlist.append(name)
+ if not op.full and len(retlist) > 3: retlist = retlist[-4:-1]
+ return retlist
+
+ def check(self):
+ if os.path.exists('/proc/interrupts'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/interrupts', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 2: continue
+ name = string.split(l[0], ':')[0]
+ if name in self.vars:
+ self.cn2[name] = long(l[1])
+ elif len(l) > 2 + procs:
+ for hw in self.vars:
+ for mod in l[2+procs:]:
+ self.cn2[mod] = long(l[1])
+ if update:
+ for name in self.cn2.keys():
+ self.val[name] = (self.cn2[name]-self.cn1[name]) * 1.0 / step
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_load(dstat):
+ def __init__(self):
+ self.len = 5
+ self.format = '%5.2f'
+ self.name = 'load avg'
+ self.nick = ('1m', '5m', '15m')
+ self.vars = ('load1', 'load5', 'load15')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/loadavg'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/loadavg', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 3: continue
+ self.val['load1'] = float(l[0])
+ self.val['load5'] = float(l[1])
+ self.val['load15'] = float(l[2])
+
+class dstat_mem(dstat):
+ def __init__(self):
+ self.name = 'memory usage'
+ self.len = 5
+ self.format = '%s'
+ self.nick = ('used', 'free', 'buff', 'cach')
+ self.vars = ('MemUsed', 'MemFree', 'Buffers', 'Cached')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/meminfo'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/meminfo', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 2: continue
+ name = string.split(l[0], ':')[0]
+ if name in self.vars + ('MemTotal',):
+ self.val[name] = long(l[1]) * 1024.0
+ self.val['MemUsed'] = self.val['MemTotal'] - self.val['MemFree'] - self.val['Buffers'] - self.val['Cached']
+
+class dstat_net(dstat):
+ def __init__(self):
+ self.name = 'network'
+ self.len = 11
+ self.format = '%s %s'
+ if op.netlist:
+ self.vars = op.netlist
+ else:
+ self.vars = self.discover()
+ self.nick = self.vars
+ self.init()
+
+ for name in self.vars: self.cn1[name] = (0, 0); self.cn1['total'] = (0, 0)
+ for name in self.vars: self.cn2[name] = (0, 0); self.cn2['total'] = (0, 0)
+ for name in self.vars: self.val[name] = (0, 0); self.val['total'] = (0, 0)
+
+ def discover(self):
+ retlist = []
+ for line in open('/proc/net/dev', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 2: continue
+ name = string.split(l[0],':')[0]
+ if l[1] == '0': continue
+ if not re.match('^(Inter-\||face|lo)$', name):
+ retlist.append(name)
+ if not op.full and len(retlist) > 2: retlist = retlist[0:2]
+ retlist.sort()
+ return retlist
+
+ def check(self):
+ if os.path.exists('/proc/net/dev'):
+ return True
+ return False
+
+ def stats(self):
+ self.cn2['total'] = (0, 0)
+ for line in open('/proc/net/dev', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 1: continue
+ l2 = string.split(l[0], ':')
+ if len(l2) < 1: continue
+ name = l2[0]
+ if len(l2) > 1 and string.strip(l2[1]):
+ l = l2[1:] + l[1:]
+ else:
+ l = l[1:]
+ if name in (self.vars) :
+ self.cn2[name] = ( long(l[0]), long(l[8]) )
+ if not re.match('^(Inter-\||face|lo)$', name):
+ self.cn2['total'] = ( self.cn2['total'][0] + long(l[0]), self.cn2['total'][1] + long(l[8]))
+ if update:
+ for name in self.cn2.keys():
+ self.val[name] = (
+ (self.cn2[name][0]-self.cn1[name][0]) * 1.0 / step,
+ (self.cn2[name][1]-self.cn1[name][1]) * 1.0 / step,
+ )
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_page(dstat):
+ def __init__(self):
+ self.name = 'paging'
+ self.format = '%s'
+ self.len = 5
+ self.vars = ('pswpin', 'pswpout')
+ self.nick = ('in', 'out')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/vmstat'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/vmstat', 'r').readlines():
+ l = string.split(line);
+ if len(l) < 2: continue
+ name = l[0]
+ if name in self.vars:
+ self.cn2[name] = long(l[1])
+ if update:
+ for name in self.vars:
+ self.val[name] = (self.cn2[name]-self.cn1[name]) * pagesize * 1.0 / step
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_page24(dstat_page):
+ def check(self):
+ if os.path.exists('/proc/stat') and not os.path.exists('/proc/vmstat'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line);
+ if len(l) < 3: continue
+ name = l[0]
+ if name == 'swap':
+ self.cn2['pswpin'] = long(l[1])
+ self.cn2['pswpout'] = long(l[2])
+ if update:
+ for name in self.vars:
+ self.val[name] = (self.cn2[name]-self.cn1[name]) * pagesize * 1.0 / step
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_proc(dstat):
+ def __init__(self):
+# self.name = 'procs'
+ self.name = 'procs'
+ self.format = '%2d'
+ self.len = 2
+ self.vars = ('procs_running', 'procs_blocked', 'processes')
+# self.vars = ('procs_running', 'procs_blocked')
+ self.nick = ('ru', 'bl', 'nw')
+# self.nick = ('ru', 'bl')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/stat'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 2: continue
+ name = l[0]
+ if name in self.vars:
+ self.val[name] = long(l[1])
+ if name in ('processes',):
+ self.val['processes'] = 0
+ self.cn2[name] = long(l[1])
+ if self.val['procs_running'] > 0:
+ self.val['procs_running'] = self.val['procs_running'] - 1
+ if update:
+ self.val['processes'] = (self.cn2['processes'] - self.cn1['processes']) / step
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+class dstat_swap(dstat):
+ def __init__(self):
+ self.name = 'swap'
+ self.len = 5
+ self.format = '%s'
+ self.nick = ('used', 'free')
+ self.vars = ('SwapUsed', 'SwapFree')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/meminfo'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/meminfo', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 2: continue
+ name = string.split(l[0], ':')[0]
+ if name in self.vars + ('SwapTotal',):
+ self.val[name] = long(l[1]) * 1024.0
+ self.val['SwapUsed'] = self.val['SwapTotal'] - self.val['SwapFree']
+
+class dstat_sys(dstat):
+ def __init__(self):
+ self.name = 'system'
+ self.format = '%5d'
+ self.len = 5
+ self.nick = ('int', 'csw')
+ self.vars = ('intr', 'ctxt')
+ self.names = { 'intr': 'int', 'ctxt': 'csw' }
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/stat'):
+ return True
+ return False
+
+ def stats(self):
+ for line in open('/proc/stat', 'r').readlines():
+ l = string.split(line);
+ if len(l) < 2: continue
+ name = l[0]
+ if name in self.vars:
+ self.cn2[name] = long(l[1])
+ if update:
+ for name in self.vars:
+ self.val[name] = (self.cn2[name]-self.cn1[name]) * 1.0 / step
+ if step == op.delay:
+ self.cn1.update(self.cn2)
+
+ def show(self):
+ for name in self.vars:
+ sys.stdout.write(self.format % self.val[name])
+ if name != self.vars[-1]:
+ sys.stdout.write(' ')
+
+class dstat_tcp(dstat):
+ def __init__(self):
+ self.name = 'tcp'
+ self.format = '%3d'
+ self.len = 3
+ self.nick = ('lis', 'act', 'syn', 'tim')
+ self.vars = ('listen', 'established', 'syn_sent', 'time_wait')
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/net/tcp'):
+ return True
+ return False
+
+ def stats(self):
+ self.val['listen'] = self.val['established'] = self.val['syn_sent'] = self.val['time_wait'] = 0
+ for line in open('/proc/net/tcp', 'r').readlines():
+ l = string.split(line)
+ if len(l) < 12: continue
+ if l[3] == '0A': self.val['listen'] = self.val['listen'] + 1
+ elif l[3] == '01': self.val['established'] = self.val['established'] + 1
+ elif l[3] == '02': self.val['syn_sent'] = self.val['syn_sent'] + 1
+ elif l[3] == '06': self.val['time_wait'] = self.val['time_wait'] + 1
+
+ def show(self):
+ for name in self.vars:
+ sys.stdout.write(self.format % self.val[name])
+ if name != self.vars[-1]:
+ sys.stdout.write(' ')
+
+class dstat_time(dstat):
+ def __init__(self):
+ self.name = 'time'
+ self.format = '%10d'
+ self.len = 10
+ ### Nice for debugging timer
+# self.format = '%13.3f'
+# self.len = 14
+ self.nick = ('epoch',)
+ self.vars = ('epoch',)
+ self.init()
+
+ def stats(self):
+ self.val['epoch'] = time.time()
+
+ def show(self):
+ sys.stdout.write(self.format % self.val['epoch'])
+
+class dstat_udp(dstat):
+ def __init__(self):
+ self.name = 'udp'
+ self.format = '%3d'
+ self.len = 3
+ self.nick = ('con', )
+ self.vars = ('connections', )
+ self.init()
+
+ def check(self):
+ if os.path.exists('/proc/net/udp'):
+ return True
+ return False
+
+ def stats(self):
+ self.val['connections'] = 0
+ for line in open('/proc/net/udp', 'r').readlines():
+ l = string.split(line)
+ if l[3] == '07': self.val['connections'] = self.val['connections'] + 1
+
+ def show(self):
+ for name in self.vars:
+ sys.stdout.write(self.format % self.val[name])
+ if name != self.vars[-1]:
+ sys.stdout.write(' ')
+
+ansi = {
+ 'black': '\033[0;30m',
+ 'darkred': '\033[0;31m',
+ 'darkgreen': '\033[0;32m',
+ 'darkyellow': '\033[0;33m',
+ 'darkblue': '\033[0;34m',
+ 'darkmagenta': '\033[0;35m',
+ 'darkcyan': '\033[0;36m',
+ 'silver': '\033[0;37m',
+
+ 'gray': '\033[1;30m',
+ 'red': '\033[1;31m',
+ 'green': '\033[1;32m',
+ 'yellow': '\033[1;33m',
+ 'blue': '\033[1;34m',
+ 'magenta': '\033[1;35m',
+ 'cyan': '\033[1;36m',
+ 'white': '\033[1;37m',
+
+ 'blackbg': '\033[40m',
+ 'redbg': '\033[41m',
+ 'greenbg': '\033[42m',
+ 'yellowbg': '\033[43m',
+ 'bluebg': '\033[44m',
+ 'magentabg': '\033[45m',
+ 'cyanbg': '\033[46m',
+ 'whitebg': '\033[47m',
+
+ 'reset': '\033[0;0m',
+ 'bold': '\033[1m',
+ 'reverse': '\033[2m',
+ 'underline': '\033[4m',
+
+ 'clear': '\033[2J',
+ 'clearline': '\033[K',
+ 'save': '\033[s',
+ 'restore': '\033[u',
+
+ 'up': '\033[1A',
+
+ 'default': '\033[0;0m',
+}
+
+def convlist(max, list):
+ max = max / len(list)
+ retlist = ()
+ for var in list:
+ retlist = retlist + (conv(max, var), )
+ return retlist
+
+#def convlist(max, list):
+# return map(conv, list)
+
+def conv(max, var, base = 1024):
+ ### lowercase (b) is better for the eyes than uppercase
+ unit = ('B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
+ if step == op.delay:
+ color = ('red', 'yellow', 'green', 'blue', 'magenta', 'cyan', 'white', 'darkred', 'darkgreen')
+ else:
+ color = ('darkred', 'darkyellow', 'darkgreen', 'darkblue', 'darkmagenta', 'darkcyan', 'silver', 'red', 'geen')
+
+ if var < 0: return ' ' * (max-2) + '- '
+
+ c = 0
+ while True:
+ if len('%d' % round(long(var))) < max:
+ if not op.integer and len('%1.2f' % var) < max:
+ ret = '%1.2f' % var
+ elif not op.integer and len('%1.1f' % var) < max:
+ ret = '%1.1f' % var
+ else:
+ ret = '%d' % round(long(var))
+ break
+ var = var / base
+ c = c + 1
+ if var != 0:
+ return ansi[color[c]] + string.rjust(ret,max-1) + unit[c] + ansi['default']
+ else:
+ return ' ' * (max-2) + '0 '
+
+def info(level, str):
+ "Output info message"
+# if level <= op.verbose:
+ print str
+
+def die(ret, str):
+ "Print error and exit with errorcode"
+ info(0, str)
+ sys.exit(ret)
+
+def getwinsize():
+ try:
+ s = struct.pack("HHHH", 0, 0, 0, 0)
+ x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
+ return struct.unpack("HHHH", x)[:2]
+ except:
+ try:
+ return (int(os.environ['LINES']), int(os.environ['COLUMNS']))
+ except:
+ return (25, 80)
+
+def getcpunr():
+ procs = 0
+ for line in open('/proc/stat', 'r').readlines():
+ name = string.split(line)[0]
+ if len(name) == 4 and name[0:3] == 'cpu':
+ procs = procs + 1
+ return procs
+
+def scsidev(nr):
+ if nr < 26:
+ return 'sd' + chr(ord('a') + nr)
+ else:
+ return 'sd' + chr(ord('a') - 1 + nr / 26) + chr(ord('a') + nr % 26)
+
+def dev(maj, min):
+ scsi = [8, 65, 66, 67, 68, 69, 70, 71, 128, 129, 130, 131, 132, 133, 134, 135]
+ ide = [3, 22, 33, 34, 56, 57, 88, 89, 90, 91]
+ if maj in scsi:
+ nr = scsi.index(maj) * 16 + min
+# nr = scsi.index(maj) * 16 + min / 16
+ return scsidev(nr)
+ elif maj in ide:
+ nr = ide.index(maj) * 2 + min / 64
+ return 'hd' + chr(ord('a') + nr)
+
+#def mountpoint(dev):
+# "Return the mountpoint of a mounted device/file"
+# for entry in open('/etc/mtab', 'r').readlines():
+# if entry:
+# list = string.split(entry)
+# if dev == list[0]:
+# return list[1]
+
+def signaler(signum, frame):
+ signal.alarm(interval)
+
+def main():
+ global update, loop, step, pagesize, procs, ansi, interval
+
+ loop = update = 0
+ step = op.delay
+ pagesize = resource.getpagesize()
+ procs = getcpunr()
+# hz = os.sysconf('SC_CLK_TCK')
+ interval = 1
+
+ if not op.update:
+ interval = op.delay
+
+ ### Empty ansi database if no colors are requested
+ if not op.color:
+ op.update = False
+ for key in ansi.keys():
+ ansi[key] = ''
+
+ ### Build list of requested modules
+ olist = []
+ for mod in op.modlist:
+ if mod == 'cpu':
+ olist.append(dstat_cpu())
+ olist.append(dstat_cpu24())
+ elif mod == 'disk':
+ olist.append(dstat_disk())
+ olist.append(dstat_disk24())
+ olist.append(dstat_disk24old())
+ elif mod == 'int': olist.append(dstat_int())
+ elif mod == 'load': olist.append(dstat_load())
+ elif mod == 'mem': olist.append(dstat_mem())
+ elif mod == 'net': olist.append(dstat_net())
+ elif mod == 'page':
+ olist.append(dstat_page())
+ olist.append(dstat_page24())
+ elif mod == 'proc': olist.append(dstat_proc())
+ elif mod == 'swap': olist.append(dstat_swap())
+ elif mod == 'sys': olist.append(dstat_sys())
+ elif mod == 'tcp': olist.append(dstat_tcp())
+ elif mod == 'time': olist.append(dstat_time())
+ elif mod == 'udp': olist.append(dstat_udp())
+ else:
+ info(1, 'Module \'%s\' does not exist or failed to load.' % mod)
+
+ (rows, cols) = getwinsize()
+
+ ### Remove defect objects and calculate line length
+ linewidth = 0
+ for o in olist + []:
+ if not o.check():
+ olist.remove(o)
+ else:
+ linewidth = linewidth + o.width() + 1
+
+ if linewidth > cols:
+ print 'Screen width too small, trimming output.'
+
+ oldplist = []
+
+ ### Increase precision if we're root (does not have effect)
+# if os.geteuid() == 0:
+# os.nice(-20)
+# sys.setcheckinterval(op.delay / 10000)
+
+ signal.signal(signal.SIGALRM, signaler)
+ signal.alarm(interval)
+
+ ### Let the games begin
+ while loop != op.count:
+
+ ### Trim object list to what is visible on screen
+ (rows, cols) = getwinsize()
+ plist = []
+ curwidth = 0
+ for o in olist:
+ if curwidth + o.width() + 1 <= cols:
+ curwidth = curwidth + o.width() + 1
+ plist.append(o)
+
+ ### Check when to display the header
+ if oldplist != plist or (loop == 0 or op.header) and step == op.delay and loop % (rows - 1) == 0:
+ for o in plist:
+ sys.stdout.write(o.title1)
+ if o != plist[-1]:
+ sys.stdout.write(ansi['darkblue'] + ' ' + ansi['default'])
+ elif olist != plist:
+ sys.stdout.write(ansi['darkblue'] + '>' + ansi['default'])
+ sys.stdout.write('\n')
+
+ for o in plist:
+ sys.stdout.write(o.title2)
+ if o != plist[-1]:
+ sys.stdout.write(ansi['silver'] + '|' + ansi['default'])
+ elif olist != plist:
+ sys.stdout.write(ansi['darkblue'] + '>' + ansi['default'])
+ sys.stdout.write('\n')
+
+ oldplist = plist
+
+ ### Prepare the colors for intermediate updates, last step in a loop is normal
+ if step != op.delay:
+ ansi['default'] = ansi['gray']
+ else:
+ ansi['default'] = ansi['reset']
+ sys.stdout.write(ansi['default'])
+
+ ### Debugging info
+# sys.stdout.write('[%d:%d:%d]' % (loop,step,update))
+
+ ### Show the stats, calculate all objects (visible, invisible)
+ for o in olist:
+ o.stats()
+ if o in plist:
+ o.show()
+ if o != plist[-1]:
+ sys.stdout.write(ansi['default'] + '|' + ansi['default'])
+ elif o != olist[-1]:
+ sys.stdout.write(ansi['default'] + '>' + ansi['default'])
+
+ ### If intermediate results, update increases with 1 sec (=interval)
+ update = update + interval
+ loop = update / op.delay
+ oldstep = step
+ step = ((update - 1) % op.delay) + 1
+
+ ### Do not pause when this is the final loop
+ if loop != op.count:
+ signal.pause()
+
+ ### The last step in a loop is to show the definitive line on a new line
+ if oldstep == op.delay:
+ sys.stdout.write('\n' + ansi['clearline'] + ansi['save'])
+ else:
+ sys.stdout.write(ansi['restore'] + ansi['clearline'])
+
+### Unbuffered sys.stdout
+sys.stdout = os.fdopen(1, 'w', 0)
+
+### Workaround for python <= 2.2.1
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+Yes = yes = On = on = True
+No = no = Off = off = False
+
+### Workaround for python < 2.3
+#def enumerate(sequence):
+# index = 0
+# for item in sequence:
+# yield index, item
+# index = index + 1
+
+### Main entrance
+if __name__ == '__main__':
+ op=Options(sys.argv[1:])
+# cf=Config()
+ try:
+ main()
+ except KeyboardInterrupt, e:
+ signal.signal(signal.SIGALRM, signal.SIG_DFL)
+ print
+ print ansi['reset'] + 'Exiting on user request'
+ sys.exit(6)
+ except OSError, e:
+ signal.signal(signal.SIGALRM, signal.SIG_DFL)
+# print e.errno
+ print
+ print ansi['reset'] + 'OSError: %s' %e
+ sys.exit(7)
+
+
+# vim:ts=4:sw=4
Please sign in to comment.
Something went wrong with that request. Please try again.