Improved some error messages for command line processing.
[python/dscho.git] / Demo / scripts / ftpstats.py
blobe931751f8210157219b6b6ac01106cb504daab93
1 #! /usr/bin/env python
3 # Extract statistics from ftp daemon log.
5 # Usage:
6 # ftpstats [-m maxitems] [-s search] [file]
7 # -m maxitems: restrict number of items in "top-N" lists, default 25.
8 # -s string: restrict statistics to lines containing this string.
9 # Default file is /usr/adm/ftpd; a "-" means read stdandard input.
11 # The script must be run on the host where the ftp daemon runs.
12 # (At CWI this is currently buizerd.)
14 import os
15 import sys
16 import regex
17 import string
18 import getopt
20 pat = '^\([a-zA-Z0-9 :]*\)!\(.*\)!\(.*\)!\([<>].*\)!\([0-9]+\)!\([0-9]+\)$'
21 prog = regex.compile(pat)
23 def main():
24 maxitems = 25
25 search = None
26 try:
27 opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
28 except getopt.error, msg:
29 print msg
30 print 'usage: ftpstats [-m maxitems] [file]'
31 sys.exit(2)
32 for o, a in opts:
33 if o == '-m':
34 maxitems = string.atoi(a)
35 if o == '-s':
36 search = a
37 file = '/usr/adm/ftpd'
38 if args: file = args[0]
39 if file == '-':
40 f = sys.stdin
41 else:
42 try:
43 f = open(file, 'r')
44 except IOError, msg:
45 print file, ':', msg
46 sys.exit(1)
47 bydate = {}
48 bytime = {}
49 byfile = {}
50 bydir = {}
51 byhost = {}
52 byuser = {}
53 bytype = {}
54 lineno = 0
55 try:
56 while 1:
57 line = f.readline()
58 if not line: break
59 lineno = lineno + 1
60 if search and string.find(line, search) < 0:
61 continue
62 if prog.match(line) < 0:
63 print 'Bad line', lineno, ':', `line`
64 continue
65 items = prog.group(1, 2, 3, 4, 5, 6)
66 logtime, loguser, loghost, logfile, logbytes, logxxx2 = items
67 ## print logtime
68 ## print '-->', loguser
69 ## print '--> -->', loghost
70 ## print '--> --> -->', logfile
71 ## print '--> --> --> -->', logbytes
72 ## print '--> --> --> --> -->', logxxx2
73 ## for i in logtime, loghost, logbytes, logxxx2:
74 ## if '!' in i: print '???', i
75 add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
76 add(bytime, logtime[7:9] + ':00-59', items)
77 direction, logfile = logfile[0], logfile[1:]
78 # The real path probably starts at the last //...
79 while 1:
80 i = string.find(logfile, '//')
81 if i < 0: break
82 logfile = logfile[i+1:]
83 add(byfile, logfile + ' ' + direction, items)
84 logdir = os.path.dirname(logfile)
85 ## logdir = os.path.normpath(logdir) + '/.'
86 while 1:
87 add(bydir, logdir + ' ' + direction, items)
88 dirhead = os.path.dirname(logdir)
89 if dirhead == logdir: break
90 logdir = dirhead
91 add(byhost, loghost, items)
92 add(byuser, loguser, items)
93 add(bytype, direction, items)
94 except KeyboardInterrupt:
95 print 'Interrupted at line', lineno
96 show(bytype, 'by transfer direction', maxitems)
97 show(bydir, 'by directory', maxitems)
98 show(byfile, 'by file', maxitems)
99 show(byhost, 'by host', maxitems)
100 show(byuser, 'by user', maxitems)
101 showbar(bydate, 'by date')
102 showbar(bytime, 'by time of day')
104 def showbar(dict, title):
105 n = len(title)
106 print '='*((70-n)/2), title, '='*((71-n)/2)
107 list = []
108 keys = dict.keys()
109 keys.sort()
110 for key in keys:
111 n = len(str(key))
112 list.append((len(dict[key]), key))
113 maxkeylength = 0
114 maxcount = 0
115 for count, key in list:
116 maxkeylength = max(maxkeylength, len(key))
117 maxcount = max(maxcount, count)
118 maxbarlength = 72 - maxkeylength - 7
119 for count, key in list:
120 barlength = int(round(maxbarlength*float(count)/maxcount))
121 bar = '*'*barlength
122 print '%5d %-*s %s' % (count, maxkeylength, key, bar)
124 def show(dict, title, maxitems):
125 if len(dict) > maxitems:
126 title = title + ' (first %d)'%maxitems
127 n = len(title)
128 print '='*((70-n)/2), title, '='*((71-n)/2)
129 list = []
130 keys = dict.keys()
131 for key in keys:
132 list.append((-len(dict[key]), key))
133 list.sort()
134 for count, key in list[:maxitems]:
135 print '%5d %s' % (-count, key)
137 def add(dict, key, item):
138 if dict.has_key(key):
139 dict[key].append(item)
140 else:
141 dict[key] = [item]
143 main()