Last active
August 14, 2018 05:27
-
-
Save thatsdone/5108298 to your computer and use it in GitHub Desktop.
A python-daemon 'runner.DaemonRunner' class extension (v0.1) and a sample.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim: tabstop=4 shiftwidth=4 softtabstop=4 | |
#!/usr/bin/python | |
import sys | |
import time | |
import logging | |
from daemon import runner | |
# | |
# An example daemon main logic application class. | |
# Just keep writing timestamps to a log file periodically. | |
# | |
class App: | |
def __init__(self): | |
# python-daemon DaemonRunner requires the below. | |
self.stdin_path = '/dev/null' | |
self.stdout_path = '/dev/null' | |
self.stderr_path = '/dev/null' | |
# For debug, you can use '/dev/tty' for stdout/stderr instead. | |
#self.stdout_path = '/dev/tty' | |
#self.stderr_path = '/dev/tty' | |
self.pidfile_path = '/tmp/foo.pid' | |
self.pidfile_timeout = 5 | |
# The above 5 attributes are mandatory. | |
# | |
# The below are this App specific. (conf file is not implemented now) | |
self.log_file = '/tmp/foobar.log' | |
self.conf_file = '/etc/pdaemon.conf' | |
self.foreground = False | |
def run(self): | |
# Here is your main logic. | |
# Initializing code. | |
if not self.foreground: | |
logging.basicConfig(level=logging.DEBUG, | |
format='%(asctime)s %(levelname)s %(message)s', | |
filename=self.log_file, | |
filemode='a') | |
while True: | |
# the main loop code. | |
try: | |
str = time.asctime(time.localtime(time.time())) | |
if self.foreground: | |
print str | |
else: | |
logging.info('DEBUG: %s' % str) | |
time.sleep(1) | |
except: | |
logging.info(sys.exc_info()) | |
logging.info('Terminating.') | |
sys.exit(1) | |
# | |
# An example extension of runner.DaemonRunner class of python-daemon. | |
# Improvement points are: | |
# - Natual unix getopt style option. | |
class MyDaemonRunner(runner.DaemonRunner): | |
def __init__(self, app): | |
# workaround... :( | |
self.app_save = app | |
self.detach_process = True | |
runner.DaemonRunner.__init__(self, app) | |
def parse_args(self, argv=None): | |
# Note that DaemonRunner implements its own parse_args(), and | |
# it is called in __init__ of the class. | |
# Here, we override it following unix getopt style syntax. | |
import getopt | |
try: | |
opts, args = getopt.getopt(sys.argv[1:], | |
'skrl:p:fvh', | |
['start', 'kill', 'log_file=', | |
'pid_file=', 'foreground']) | |
except getopt.GetoptError: | |
print sys.exc_info() | |
print 'getopt error...' | |
sys.exit(2) | |
self.action = '' | |
for opt, arg in opts: | |
#print 'opt / arg :', opt, arg | |
if opt in ('-s'): | |
self.action = 'start' | |
elif opt in ('-k'): | |
self.action = 'stop' | |
elif opt in ('-r'): | |
self.action = 'restart' | |
elif opt in ('-l', '--log_file'): | |
# log_file is stored in the App object. But, here it's | |
# pointed by 'app_save' attribute of MyDaemonRunner, | |
# not by 'app'. This is because __init__ of DaemonRunner | |
# calls parse_args() BEFORE recording app reference... :( | |
self.app_save.log_file = arg | |
# print 'setting log_file :' , self.app_save.log_file | |
elif opt in ('-p', '--pidfile'): | |
self.app_save.pidfile_path = arg | |
#print 'arg is :', arg | |
elif opt in ('-f', '--foreground'): | |
self.detach_process = False | |
self.app_save.stdout_path = '/dev/tty' | |
self.app_save.stderr_path = '/dev/tty' | |
self.app_save.foreground = True | |
elif opt in ('-v'): | |
self.verbose = True | |
elif opt in ('-h', '--help'): | |
print 'show usage...' | |
sys.exit(2) | |
else: | |
print 'show usage' | |
sys.exit(2) | |
if not self.action: | |
print sys.argv[0] + ' (-s|-k|-r) [options]' | |
sys.exit(1) | |
# | |
# FYI: The original parse_args() in runner.DaemonRunner class. | |
# | |
def original_parse_args(self, argv=None): | |
""" Parse command-line arguments. | |
""" | |
if argv is None: | |
argv = sys.argv | |
min_args = 2 | |
if len(argv) < min_args: | |
self._usage_exit(argv) | |
self.action = argv[1] | |
if self.action not in self.action_funcs: | |
self._usage_exit(argv) | |
# | |
# | |
# | |
if __name__ == '__main__': | |
app = App() | |
daemon_runner = MyDaemonRunner(app) | |
if not app.foreground: | |
daemon_runner.do_action() | |
else: | |
app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment