├── README.md ├── .gitignore ├── demonconfig.py ├── subd.py └── daemon.py /README.md: -------------------------------------------------------------------------------- 1 | PyDaemon 2 | ======== 3 | 4 | Light setting python daemon -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /demonconfig.py: -------------------------------------------------------------------------------- 1 | import sys, time 2 | 3 | class SigFunctionsCon: 4 | 5 | def __init__(self,ourdaemon): 6 | self.__ourdaemon = ourdaemon 7 | 8 | def SIGTERM(self): 9 | sys.stderr.write("BB!\n") 10 | sys.exit(0) 11 | return 12 | 13 | class ReactFunctionCon: 14 | 15 | def __init__(self,ourdaemon): 16 | self.__ourdaemon = ourdaemon 17 | 18 | def start(self): 19 | self.__ourdaemon.start() 20 | 21 | def stop(self): 22 | self.__ourdaemon.stop() 23 | 24 | def restart(self): 25 | self.__ourdaemon.restart() 26 | 27 | def stmess(self,message): 28 | print message 29 | self.__ourdaemon.start() 30 | 31 | class StatCon: 32 | 33 | strHelp = "Autmation has be applied to distribution sistem feeder for a long time, aspecially as related to protection and the restoration of some parts of the feeder." 34 | 35 | def run(self): 36 | while(True): 37 | time.sleep(1) 38 | 39 | pidFile = "/tmp/daemon-naprimer.pid" 40 | 41 | inputter = "/dev/null" 42 | 43 | outputter = "/dev/null" 44 | 45 | errorer = "/home/espresso/lid" 46 | -------------------------------------------------------------------------------- /subd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import time 4 | import signal 5 | import daemon 6 | import demonconfig 7 | 8 | StaticConfig = demonconfig.StatCon() 9 | 10 | class MyDaemon(daemon.Daemon): 11 | 12 | 13 | def run(self): 14 | StaticConfig.run() 15 | 16 | class DaemonConfigurator: 17 | 18 | 19 | def __init__(self,ourdaemon): 20 | self.ourdaemon = ourdaemon 21 | 22 | def getSignalsForDaemon(self): 23 | localCon = demonconfig.SigFunctionsCon(self.ourdaemon) 24 | sigDict={} 25 | for sig in dir(localCon): 26 | if sig[0:1]!='_': 27 | sigDict[getattr(signal, sig)]=getattr(localCon, sig) 28 | return sigDict 29 | 30 | def getReactsForDaemon(self): 31 | localCon = demonconfig.ReactFunctionCon(self.ourdaemon) 32 | reactDict={} 33 | for react in dir(localCon): 34 | if react[0:1]!='_': 35 | reactDict[react]=getattr(localCon, react) 36 | return reactDict 37 | 38 | 39 | if __name__ == "__main__": 40 | 41 | daemon = MyDaemon(StaticConfig.pidFile, StaticConfig.inputter, StaticConfig.outputter, StaticConfig.errorer) 42 | 43 | configer = DaemonConfigurator(daemon) 44 | SigDict = configer.getSignalsForDaemon() 45 | 46 | daemon.metaInit(SigDict) 47 | 48 | ReactDict = configer.getReactsForDaemon() 49 | 50 | if len(sys.argv) > 1: 51 | if sys.argv[1] in iter(ReactDict): 52 | try: 53 | ReactDict[sys.argv[1]](*sys.argv[2:len(sys.argv)]) 54 | sys.exit(0) 55 | except TypeError, error: 56 | print error 57 | print StaticConfig.strHelp 58 | sys.exit(2) 59 | else: 60 | print "usage: %s %s" % (sys.argv[0], ReactDict) 61 | sys.exit(2) 62 | -------------------------------------------------------------------------------- /daemon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import os 5 | import time 6 | import atexit 7 | import signal 8 | 9 | class SignalHandler: 10 | 11 | 12 | SIGNALS = () 13 | 14 | def register(self, signum, callback): 15 | self.SIGNALS += (SigAction(signum, callback), ) 16 | 17 | def getActions(self): 18 | return self.SIGNALS 19 | 20 | def handler(self, signum, frame): 21 | assert 0, "You must define a handler(signum, frame) method in %s" %(self) 22 | 23 | def __repr__(self): 24 | return "" %(self.__class__.__name__) 25 | 26 | class SigAction(SignalHandler): 27 | 28 | 29 | def __init__(self, signum, callback): 30 | self.signum = signum 31 | self.callback = callback 32 | signal.signal(self.signum, self.handler) 33 | 34 | def handler(self, signum, frame): 35 | self.callback() 36 | 37 | def __repr__(self): 38 | return "" %(self.__class__.__name__, self.signum) 39 | 40 | class Daemon: 41 | 42 | 43 | def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): 44 | self.stdin = stdin 45 | self.stdout = stdout 46 | self.stderr = stderr 47 | self.pidfile = pidfile 48 | 49 | def metaInit(self, sigdict): 50 | self.sigDict = sigdict 51 | 52 | def daemonize(self): 53 | """ 54 | do the UNIX double-fork magic, see Stevens' "Advanced 55 | Programming in the UNIX Environment" for details (ISBN 0201563177) 56 | http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 57 | """ 58 | try: 59 | pid = os.fork() 60 | if pid > 0: 61 | # exit first parent 62 | sys.exit(0) 63 | except OSError, e: 64 | sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) 65 | sys.exit(1) 66 | 67 | # decouple from parent environment 68 | os.chdir("/") 69 | os.setsid() 70 | os.umask(0) 71 | 72 | # do second fork 73 | try: 74 | pid = os.fork() 75 | if pid > 0: 76 | # exit from second parent 77 | sys.exit(0) 78 | except OSError, e: 79 | sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) 80 | sys.exit(1) 81 | 82 | # redirect standard file descriptors 83 | sys.stdout.flush() 84 | sys.stderr.flush() 85 | si = file(self.stdin, 'r') 86 | so = file(self.stdout, 'a+') 87 | se = file(self.stderr, 'a+', 0) 88 | os.dup2(si.fileno(), sys.stdin.fileno()) 89 | os.dup2(so.fileno(), sys.stdout.fileno()) 90 | os.dup2(se.fileno(), sys.stderr.fileno()) 91 | 92 | # write pidfile 93 | atexit.register(self.delpid) 94 | pid = str(os.getpid()) 95 | file(self.pidfile,'w+').write("%s\n" % pid) 96 | 97 | def delpid(self): 98 | os.remove(self.pidfile) 99 | 100 | def signalAssign(self): 101 | assignee = SignalHandler() 102 | for i in iter(self.sigDict): 103 | assignee.register(i,self.sigDict[i]) 104 | 105 | def start(self): 106 | """ 107 | Start the daemon 108 | """ 109 | # Check for a pidfile to see if the daemon already runs 110 | try: 111 | pf = file(self.pidfile,'r') 112 | pid = int(pf.read().strip()) 113 | pf.close() 114 | except IOError: 115 | pid = None 116 | 117 | if pid: 118 | message = "pidfile %s already exist. Daemon already running?\n" 119 | sys.stderr.write(message % self.pidfile) 120 | sys.exit(1) 121 | 122 | # Start the daemon 123 | self.daemonize() 124 | self.signalAssign() 125 | self.run() 126 | 127 | sigDict = {} 128 | 129 | def stop(self): 130 | """ 131 | Stop the daemon 132 | """ 133 | # Get the pid from the pidfile 134 | try: 135 | pf = file(self.pidfile,'r') 136 | pid = int(pf.read().strip()) 137 | pf.close() 138 | except IOError: 139 | pid = None 140 | 141 | if not pid: 142 | message = "pidfile %s does not exist. Daemon not running?\n" 143 | sys.stderr.write(message % self.pidfile) 144 | return # not an error in a restart 145 | 146 | # Try killing the daemon process 147 | try: 148 | while 1: 149 | os.kill(pid, signal.SIGTERM) 150 | time.sleep(0.1) 151 | except OSError, err: 152 | err = str(err) 153 | if err.find("No such process") > 0: 154 | if os.path.exists(self.pidfile): 155 | os.remove(self.pidfile) 156 | else: 157 | print str(err) 158 | sys.exit(1) 159 | 160 | def restart(self): 161 | """ 162 | Restart the daemon 163 | """ 164 | self.stop() 165 | self.start() 166 | 167 | def run(self): 168 | print "dummy" 169 | --------------------------------------------------------------------------------