<s> doc = """<STR_LIT>""" <EOL> import os <EOL> import sys <EOL> import time <EOL> from collections import namedtuple <EOL> from superlance . compat import maxint <EOL> from superlance . compat import xmlrpclib <EOL> from supervisor import childutils <EOL> from supervisor . datatypes import byte_size , SuffixMultiplier <EOL> def usage ( ) : <EOL> print ( doc ) <EOL> sys . exit ( <NUM_LIT:255> ) <EOL> def shell ( cmd ) : <EOL> with os . popen ( cmd ) as f : <EOL> return f . read ( ) <EOL> class Memmon : <EOL> def __init__ ( self , cumulative , programs , groups , any , sendmail , email , email_uptime_limit , name , rpc = None ) : <EOL> self . cumulative = cumulative <EOL> self . programs = programs <EOL> self . groups = groups <EOL> self . any = any <EOL> self . sendmail = sendmail <EOL> self . email = email <EOL> self . email_uptime_limit = email_uptime_limit <EOL> self . memmonName = name <EOL> self . rpc = rpc <EOL> self . stdin = sys . stdin <EOL> self . stdout = sys . stdout <EOL> self . stderr = sys . stderr <EOL> self . pscommand = '<STR_LIT>' <EOL> self . pstreecommand = '<STR_LIT>' <EOL> self . mailed = False <EOL> def runforever ( self , test = False ) : <EOL> while <NUM_LIT:1> : <EOL> headers , payload = childutils . listener . wait ( self . stdin , self . stdout ) <EOL> if not headers [ '<STR_LIT>' ] . startswith ( '<STR_LIT>' ) : <EOL> childutils . listener . ok ( self . stdout ) <EOL> if test : <EOL> break <EOL> continue <EOL> status = [ ] <EOL> if self . programs : <EOL> keys = sorted ( self . programs . keys ( ) ) <EOL> status . append ( <EOL> '<STR_LIT>' % '<STR_LIT:U+002CU+0020>' . join ( <EOL> [ '<STR_LIT>' % ( k , self . programs [ k ] ) for k in keys ] ) <EOL> ) <EOL> if self . groups : <EOL> keys = sorted ( self . groups . keys ( ) ) <EOL> status . append ( <EOL> '<STR_LIT>' % '<STR_LIT:U+002CU+0020>' . join ( <EOL> [ '<STR_LIT>' % ( k , self . groups [ k ] ) for k in keys ] ) <EOL> ) <EOL> if self . any is not None : <EOL> status . append ( '<STR_LIT>' % self . any ) <EOL> self . stderr . write ( '<STR_LIT:\n>' . join ( status ) + '<STR_LIT:\n>' ) <EOL> infos = self . rpc . supervisor . getAllProcessInfo ( ) <EOL> for info in infos : <EOL> pid = info [ '<STR_LIT>' ] <EOL> name = info [ '<STR_LIT:name>' ] <EOL> group = info [ '<STR_LIT>' ] <EOL> pname = '<STR_LIT>' % ( group , name ) <EOL> if not pid : <EOL> continue <EOL> rss = self . calc_rss ( pid ) <EOL> if rss is None : <EOL> continue <EOL> for n in name , pname : <EOL> if n in self . programs : <EOL> self . stderr . write ( '<STR_LIT>' % ( pname , rss ) ) <EOL> if rss > self . programs [ name ] : <EOL> self . restart ( pname , rss ) <EOL> continue <EOL> if group in self . groups : <EOL> self . stderr . write ( '<STR_LIT>' % ( pname , rss ) ) <EOL> if rss > self . groups [ group ] : <EOL> self . restart ( pname , rss ) <EOL> continue <EOL> if self . any is not None : <EOL> self . stderr . write ( '<STR_LIT>' % ( pname , rss ) ) <EOL> if rss > self . any : <EOL> self . restart ( pname , rss ) <EOL> continue <EOL> self . stderr . flush ( ) <EOL> childutils . listener . ok ( self . stdout ) <EOL> if test : <EOL> break <EOL> def restart ( self , name , rss ) : <EOL> info = self . rpc . supervisor . getProcessInfo ( name ) <EOL> uptime = info [ '<STR_LIT>' ] - info [ '<STR_LIT:start>' ] <EOL> self . stderr . write ( '<STR_LIT>' % name ) <EOL> memmonId = self . memmonName and "<STR_LIT>" % self . memmonName or "<STR_LIT>" <EOL> try : <EOL> self . rpc . supervisor . stopProcess ( name ) <EOL> except xmlrpclib . Fault as e : <EOL> msg = ( '<STR_LIT>' % <EOL> ( name , rss , e ) ) <EOL> self . stderr . write ( str ( msg ) ) <EOL> if self . email : <EOL> subject = '<STR_LIT>' % ( memmonId , name ) <EOL> self . mail ( self . email , subject , msg ) <EOL> raise <EOL> try : <EOL> self . rpc . supervisor . startProcess ( name ) <EOL> except xmlrpclib . Fault as e : <EOL> msg = ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( name , e ) ) <EOL> self . stderr . write ( str ( msg ) ) <EOL> if self . email : <EOL> subject = '<STR_LIT>' % ( memmonId , name ) <EOL> self . mail ( self . email , subject , msg ) <EOL> raise <EOL> if self . email and uptime <= self . email_uptime_limit : <EOL> now = time . asctime ( ) <EOL> msg = ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> name , now , rss ) <EOL> ) <EOL> subject = '<STR_LIT>' % ( memmonId , name ) <EOL> self . mail ( self . email , subject , msg ) <EOL> def calc_rss ( self , pid ) : <EOL> ProcInfo = namedtuple ( '<STR_LIT>' , [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> def find_children ( parent_pid , procs ) : <EOL> children = [ ] <EOL> for proc in procs : <EOL> pid , ppid , rss = proc <EOL> if ppid == parent_pid : <EOL> children . append ( proc ) <EOL> children . extend ( find_children ( pid , procs ) ) <EOL> return children <EOL> def cum_rss ( pid , procs ) : <EOL> parent_proc = [ p for p in procs if p . pid == pid ] [ <NUM_LIT:0> ] <EOL> children = find_children ( pid , procs ) <EOL> tree = [ parent_proc ] + children <EOL> total_rss = sum ( map ( int , [ p . rss for p in tree ] ) ) <EOL> return total_rss <EOL> def get_all_process_infos ( data ) : <EOL> data = data . strip ( ) <EOL> procs = [ ] <EOL> for line in data . splitlines ( ) : <EOL> pid , ppid , rss = map ( int , line . split ( ) ) <EOL> procs . append ( ProcInfo ( pid = pid , ppid = ppid , rss = rss ) ) <EOL> return procs <EOL> if self . cumulative : <EOL> data = shell ( self . pstreecommand ) <EOL> procs = get_all_process_infos ( data ) <EOL> try : <EOL> rss = cum_rss ( pid , procs ) <EOL> except ( ValueError , IndexError ) : <EOL> return None <EOL> else : <EOL> data = shell ( self . pscommand % pid ) <EOL> if not data : <EOL> return None <EOL> try : <EOL> rss = data . lstrip ( ) . rstrip ( ) <EOL> rss = int ( rss ) <EOL> except ValueError : <EOL> return None <EOL> rss = rss * <NUM_LIT> <EOL> return rss <EOL> def mail ( self , email , subject , msg ) : <EOL> body = '<STR_LIT>' % self . email <EOL> body += '<STR_LIT>' % subject <EOL> body += '<STR_LIT:\n>' <EOL> body += msg <EOL> with os . popen ( self . sendmail , '<STR_LIT:w>' ) as m : <EOL> m . write ( body ) <EOL> self . mailed = body <EOL> def parse_namesize ( option , value ) : <EOL> try : <EOL> name , size = value . split ( '<STR_LIT:=>' ) <EOL> except ValueError : <EOL> print ( '<STR_LIT>' % ( value , option ) ) <EOL> usage ( ) <EOL> size = parse_size ( option , size ) <EOL> return name , size <EOL> def parse_size ( option , value ) : <EOL> try : <EOL> size = byte_size ( value ) <EOL> except : <EOL> print ( '<STR_LIT>' % ( value , option ) ) <EOL> usage ( ) <EOL> return size <EOL> seconds_size = SuffixMultiplier ( { '<STR_LIT:s>' : <NUM_LIT:1> , <EOL> '<STR_LIT:m>' : <NUM_LIT> , <EOL> '<STR_LIT:h>' : <NUM_LIT> * <NUM_LIT> , <EOL> '<STR_LIT:d>' : <NUM_LIT> * <NUM_LIT> * <NUM_LIT> <EOL> } ) <EOL> def parse_seconds ( option , value ) : <EOL> try : <EOL> seconds = seconds_size ( value ) <EOL> except : <EOL> print ( '<STR_LIT>' % ( value , option ) ) <EOL> usage ( ) <EOL> return seconds <EOL> def memmon_from_args ( arguments ) : <EOL> import getopt <EOL> short_args = "<STR_LIT>" <EOL> long_args = [ <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> ] <EOL> if not arguments : <EOL> return None <EOL> try : <EOL> opts , args = getopt . getopt ( arguments , short_args , long_args ) <EOL> except : <EOL> return None <EOL> cumulative = False <EOL> programs = { } <EOL> groups = { } <EOL> any = None <EOL> sendmail = '<STR_LIT>' <EOL> email = None <EOL> uptime_limit = maxint <EOL> name = None <EOL> for option , value in opts : <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> return None <EOL> if option in ( '<STR_LIT:-c>' , '<STR_LIT>' ) : <EOL> cumulative = True <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> name , size = parse_namesize ( option , value ) <EOL> programs [ name ] = size <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> name , size = parse_namesize ( option , value ) <EOL> groups [ name ] = size <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> size = parse_size ( option , value ) <EOL> any = size <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> sendmail = value <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> email = value <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> uptime_limit = parse_seconds ( option , value ) <EOL> if option in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> name = value <EOL> memmon = Memmon ( cumulative = cumulative , <EOL> programs = programs , <EOL> groups = groups , <EOL> any = any , <EOL> sendmail = sendmail , <EOL> email = email , <EOL> email_uptime_limit = uptime_limit , <EOL> name = name ) <EOL> return memmon <EOL> def main ( ) : <EOL> memmon = memmon_from_args ( sys . argv [ <NUM_LIT:1> : ] ) <EOL> if memmon is None : <EOL> usage ( ) <EOL> memmon . rpc = childutils . getRPCInterface ( os . environ ) <EOL> memmon . runforever ( ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> main ( ) </s>
