📄 xml_python_processors.txt
字号:
From - Thu May 31 22:07:39 2001X-UIDL: 991284065.4950.limousin.fr.clara.netX-Mozilla-Status: 0001X-Mozilla-Status2: 00000000Return-Path: <pureftpd-users-admin@lists.sourceforge.net>Delivered-To: jedi@claranet.frReceived: from usw-sf-list1.sourceforge.net (usw-sf-fw2.sourceforge.net [216.136.171.252]) by mail.fr.clara.net (Postfix) with ESMTP id 96251DB5B for <jedi@claranet.fr>; Thu, 31 May 2001 06:41:04 +0200 (CEST)Received: from localhost ([127.0.0.1] helo=usw-sf-list1.sourceforge.net) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.22 #1 (Debian)) id 155KEg-0005O4-00; Wed, 30 May 2001 21:39:02 -0700Received: from dsl-64-192-96-25.telocity.com ([64.192.96.25] helo=orr.falooley.org) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.22 #1 (Debian)) id 155KDt-0005Kt-00 for <pureftpd-users@lists.sourceforge.net>; Wed, 30 May 2001 21:38:13 -0700Received: from news by orr.falooley.org with local (Exim 3.22 #1 (Debian)) id 155KDi-0005lO-00 for <pureftpd-users@lists.sourceforge.net>; Thu, 31 May 2001 00:38:02 -0400From: j@falooley.org (Jason Lunz)To: pureftpd-users@lists.sourceforge.netMessage-Id: <E155KDi-0005lO-00@orr.falooley.org>Date: Thu, 31 May 2001 00:38:02 -0400Subject: [Pureftpd-users] xml toysSender: pureftpd-users-admin@lists.sourceforge.netErrors-To: pureftpd-users-admin@lists.sourceforge.netX-BeenThere: pureftpd-users@lists.sourceforge.netX-Mailman-Version: 2.0.5Precedence: bulkList-Help: <mailto:pureftpd-users-request@lists.sourceforge.net?subject=help>List-Post: <mailto:pureftpd-users@lists.sourceforge.net>List-Subscribe: <http://lists.sourceforge.net/lists/listinfo/pureftpd-users>, <mailto:pureftpd-users-request@lists.sourceforge.net?subject=subscribe>List-Id: Pure FTPd discussions <pureftpd-users.lists.sourceforge.net>List-Unsubscribe: <http://lists.sourceforge.net/lists/listinfo/pureftpd-users>, <mailto:pureftpd-users-request@lists.sourceforge.net?subject=unsubscribe>X-UIDL: 991284065.4950.limousin.fr.clara.netStatus: RO I've been fooling around with parsing the XML output of "pure-ftpwho -x"in python and doing things with it. The results could be useful to a lotof people, so I'm posting everything here. Maybe it can become part of acontrib/ dir in the distribution.mind you, none of this has been written with elegance or efficiency inmind. but it's a good basis for other work.Here's a python module that parses the XML pure-ftpwho data and returnsa list of dicts, with each dict representing a connected client'sattributes: #! /usr/bin/python2 import os from xml.sax import handler, make_parser class ftpwho_handler(handler.ContentHandler): def __init__(self): handler.ContentHandler.__init__(self) self.clear() def startElement(self, name, attrs): if name != 'client': return d = {} for (k, v) in attrs.items(): d[k] = v self.clients.append(d) def clear(self): self.clients = [] parser = make_parser() fh = ftpwho_handler() parser.setContentHandler(fh) def numberize(dicts): for c in dicts: for k in ('pid', 'time', 'localport', 'percentage', 'bandwidth'): if c.has_key(k): c[k] = int(c[k]) for k in ('current_size', 'resume', 'total_size'): if c.has_key(k): c[k] = long(c[k]) return dicts def clients(): fh.clear() parser.parse(os.popen('pure-ftpwho -x')) return numberize(fh.clients)Building on that, I wrote html_ftpwho.py, which turns the aforementionedclient list into HTML output. The output resembles what you get with"pure-ftpwho -w", but you can choose which columns you want in whichorder, and sort the rows on multiple fields. You also can see bandwidthtotals per account. #! /usr/bin/python2 # vim: sw=4 import getopt import pure_ftpwho import sys from string import capitalize, lower def range_idx(list, first = 1, cmp_func = cmp): for i in range(first+1, len(list)): if cmp_func(list[first], list[i]): return i return len(list) def dcmp(a, b, key): if a.has_key(key): if b.has_key(key): return cmp(a[key], b[key]) else: return 1 else: if b.has_key(key): return -1 else: return 0 def multisort(dicts, keys): if not keys: return dicts dicts.sort(lambda x, y, key=keys[0]: dcmp(x, y, key)) ret = [] first = last = 0 while last < len(dicts): last = range_idx(dicts, first, lambda x, y, k=keys[0]: dcmp(x, y, k)) add = multisort(dicts[first:last], keys[1:]) if(add): ret.extend(add) first = last return ret def col_heading(key): headings = {'pid' : 'PID'} if headings.has_key(key): return headings[key] else: return capitalize(lower(key)) def size_abbrev(num, order=-1): abbr = ['b', 'K', 'M', 'G', 'T'] if order == -1: q = 1 for i in range(len(abbr)): p = pow(1024, i+1) if num < p: return (float(num)/q, abbr[i], i) q = p else: return (float(num)/pow(1024, order), abbr[order], order) def celltext(dict, type): sizes = ['current_size', 'total_size', 'percentage', 'bandwidth'] align = '' ret = '' if type == 'stats': align = ' align="right"' if filter(lambda k, d=dict: d.has_key(k), sizes): bw, abbr, order = size_abbrev(dict['bandwidth']) if order == 0: format = '%d' else: format = '%.1f' sf = format + '/' + format sf += ' %s (%d%% - ' + format sf += ' %s/s)' ret = sf % (size_abbrev(dict['current_size'], order)[0], size_abbrev(dict['total_size'], order)[0], abbr, dict['percentage'], bw, abbr) elif not dict.has_key(type): ret = ' ' elif type in sizes: ret = size_abbrev(dict[type]) elif type == 'time': align = ' align="right"' str = '' minutes, seconds = divmod(dict[type], 60) hours, minutes = divmod(minutes, 60) days, hours = divmod(hours, 24) if(days): str += '%dd' % days if(hours): str += '%02d:' % hours ret = str + '%02d:%02d' % (minutes, seconds) else: ret = dict[type] return '<td%s>%s</td>' % (align, ret) def html(dicts, order, headings, stream, totals): sorted = multisort(dicts, order) stream.write('''<!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd"> <html> <title>Pure-FTPd server status</title> <body bgcolor="#ffffff" text="#000000"> ''') if(totals): stream.write('<table cellspacing="4" border="2" cellpadding="4">') stream.write('<tr><th>Account</th><th>Total Bandwidth</th></tr>') for k in totals.keys(): stream.write('<tr><td>%s</td>' % k) stream.write('<td>%d %s/s</td></tr>\n' % size_abbrev(totals[k])[:2]) stream.write('</table><BR>\n') stream.write('<div align="center">') stream.write('<table width="100%" cellspacing="4" border="2" cellpadding="4">') for k in headings: stream.write('<th>%s</th>' % col_heading(k)) stream.write('\n') for d in sorted: stream.write('<tr valign="middle">\n') for k in headings: stream.write('%s' % celltext(d, k)) stream.write('\n</tr>\n') stream.write('</table></div></body></html>\n') def arg_expand(list, opts): optmap = { 'A':'account', 'B':'bandwidth', 'C':'current_size', 'F':'file', 'H':'host', 'L':'localhost', 'O':'localport', 'P':'percentage', 'D':'pid', 'R':'resume', 'S':'state', 'T':'time', 'X':'stats', 'Z':'total_size' } for l in opts: if optmap.has_key(l): list.append(optmap[l]) else: print 'unrecognized column %s' % l sys.exit(1) def usage(): print '''usage: html_ftpwho.py [options] -c <orderstr> columns to output (default "AXTSHF") -o <orderstr> sort order (default "SABT") -t show totals per account <orderstr> is a string of letters, each representing a client attribute: A - account B - bandwidth C - current_size F - file H - host L - localhost O - localport P - percentage D - pid R - resume S - state T - time X - stats Z - total_size ''' sys.exit(1) try: optlist, args = getopt.getopt(sys.argv[1:], 'hc:o:t') except getopt.error, msg: print msg usage() ord_arg = '' col_arg = '' show_totals = 0 for opt in optlist: if '-c' == opt[0]: col_arg += opt[1] elif '-h' == opt[0]: usage() elif '-o' == opt[0]: ord_arg += opt[1] elif '-t' == opt[0]: show_totals = 1 else: print 'unrecognized option "%s"' % opt[0] usage() if not ord_arg: ord_arg = 'SABT' if not col_arg: col_arg = 'AXTSHF' order = [] columns = [] arg_expand(order, ord_arg) arg_expand(columns, col_arg) cl = pure_ftpwho.clients() totals = {} if show_totals: for c in cl: if c.has_key('bandwidth'): try: totals[c['account']] += c['bandwidth'] except KeyError: totals[c['account']] = c['bandwidth'] html(cl, order, columns, sys.stdout, totals)suggestions/patches welcome,Jason_______________________________________________Pureftpd-users mailing listPureftpd-users@lists.sourceforge.nethttp://lists.sourceforge.net/lists/listinfo/pureftpd-users
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -