Created
April 4, 2012 09:39
-
-
Save yyuu/2300009 to your computer and use it in GitHub Desktop.
a mon's alert plugin to manage syvinit/upstart/daemontools services
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
| #!/usr/bin/env python | |
| # | |
| # service2.alert - a mon's alert plugin to manage syvinit/upstart/daemontools services | |
| # | |
| # you have to permit mon user to run following commands via sudo without password. | |
| # | |
| # * /usr/sbin/service (for sysvinit) | |
| # * /sbin/initctl (for upstart) | |
| # * /usr/bin/svc (for daemontools) | |
| # * /usr/bin/svstat (for daemontools) | |
| # | |
| from __future__ import with_statement | |
| import logging | |
| import optparse | |
| import os | |
| import re | |
| import subprocess | |
| import sys | |
| import time | |
| class service(object): | |
| @classmethod | |
| def exists(cls, name): | |
| return os.path.isfile("/etc/init.d/%s" % (name,)) | |
| def __init__(self, name): | |
| assert self.exists(name), "not a %s service: %s" % (self.__class__.__name__, name) | |
| self.name = name | |
| def start(self, options): | |
| return self._system(self._cmdline('start'), options) | |
| def stop(self, options=None): | |
| retry = 3 | |
| if options is None: | |
| options = {} | |
| if options.force and not options.dry_run: | |
| for _ in xrange(retry): | |
| self._system(self._cmdline('stop'), options) | |
| if self.status(options) == 0: | |
| break | |
| else: | |
| time.sleep(3) | |
| if self.status(options) != 0: | |
| return 0 | |
| else: | |
| raise(RuntimeError("could not stop %s service in %d times" % (self.name, retry))) | |
| else: | |
| return self._system(self._cmdline('stop'), options) | |
| def restart(self, options=None): | |
| if options is None: | |
| options = {} | |
| if options.force: | |
| self.stop(options) | |
| return self.start(options) | |
| else: | |
| return self._system("%s || %s" % (self._cmdline('restart'), self._cmdline('start')), options) | |
| def reload(self, options=None): | |
| if options is None: | |
| options = {} | |
| if options.force: | |
| return self.restart(options) | |
| else: | |
| return self._system("%s || %s" % (self._cmdline('reload'), self._cmdline('start')), options) | |
| def status(self, options=None): | |
| return self._system(self._cmdline('status'), options) | |
| def _cmdline(self, action): | |
| return "sudo service %s %s" % (self.name, action) | |
| def _system(self, cmdline, options=None): | |
| if options is None: | |
| options = {} | |
| if options.dry_run: | |
| logging.info(cmdline) | |
| return 0 | |
| else: | |
| if options.verbose: | |
| logging.info(cmdline) | |
| return subprocess.call(["/bin/sh", "-e", "-c", cmdline]) | |
| class upstart(service): | |
| @classmethod | |
| def exists(cls, name): | |
| return os.path.isfile("/etc/init/%s.conf" % (name,)) | |
| def status(self, options=None): | |
| return self._system("sudo service %s status | grep -q running" % (self.name,), options) | |
| def _cmdline(self, action): | |
| return "sudo initctl %s %s" % (action, self.name) | |
| class daemontools(service): | |
| @classmethod | |
| def exists(cls, name): | |
| return os.path.isdir("/etc/service/%s" % (name,)) | |
| @property | |
| def dir(self): | |
| return "/etc/service/%s" % (self.name,) | |
| def status(self, options=None): | |
| return self._system("sudo svstat %s | grep -q '%s: *up'" % (self.dir, self.dir), options) | |
| def _cmdline(self, action): | |
| actions = { "start": "-u", "stop": "-d", "restart": "-t" , "reload": "-t" } | |
| if action in actions: | |
| return "sudo svc %s %s" % (actions[action], self.dir) | |
| else: | |
| raise(ValueError("unknown action for daemontools service of %s: %s" % (self.name, action))) | |
| def main(args): | |
| parser = optparse.OptionParser("usage %prog [OPTIONS]", add_help_option=False) | |
| parser.add_option('-T', '--trap', default=False, action='store_true', dest='trap', help='(if trap)') | |
| parser.add_option('-O', '--traptimeout', default=False, action='store_true', dest='traptimeout', help='(if traptimeout)') | |
| parser.add_option('--action', default='restart', dest='action', help='service action') | |
| parser.add_option('--dry-run', default=False, action='store_true', dest='dry_run', help='perform a trial run with no changes made') | |
| parser.add_option('-f', '--force', default=False, action='store_true', dest='force', help='performing actions forcively') | |
| parser.add_option('-g', '--group', dest='group', help='(will be ignored)') | |
| parser.add_option('-h', '--hosts', dest='hosts', help='(will be ignored)') | |
| parser.add_option('-s', '--service', dest='service', help='service') | |
| parser.add_option('-t', '--tmnow', type='int', dest='tmnow', help='(will be ignored)') | |
| parser.add_option('-u', '--upalert', default=False, action='store_true', dest='upalert', help='(if upalert)') | |
| parser.add_option('-v', '--verbose', default=False, action='store_true', dest='verbose', help='show verbose messages') | |
| (options, args) = parser.parse_args(args) | |
| if options.verbose: | |
| logging.basicConfig(level=logging.DEBUG) | |
| if options.service is None: | |
| raise ValueError("no service was specified") | |
| if re.match(r'force-', options.action): | |
| options.force = True | |
| options.action = re.sub(r'force-', '', options.action) | |
| svc = None | |
| for cls in [ daemontools, upstart, service ]: | |
| try: | |
| svc = cls(options.service) | |
| break | |
| except AssertionError: | |
| logging.debug("%s is not a %s service." % (options.service, cls.__name__)) | |
| if svc: | |
| logging.debug("%s is %s service." % (options.service, svc.__class__.__name__)) | |
| try: | |
| action = getattr(svc, options.action) | |
| except AttributeError: | |
| raise(RuntimeError("unknown action called for service %s: %s" % (options.service, options.action))) | |
| sys.exit(action(options)) | |
| else: | |
| logging.error("unknown service: %s" % (options.service,)) | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main(sys.argv) | |
| # vim:set ft=python : |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment