|
@@ -0,0 +1,161 @@
|
|
|
+import os
|
|
|
+import sys
|
|
|
+
|
|
|
+from optparse import OptionParser, BadOptionError, make_option as Option
|
|
|
+
|
|
|
+from celery import __version__
|
|
|
+from celery.platforms import create_daemon_context
|
|
|
+
|
|
|
+OPTION_LIST = (
|
|
|
+ Option('-f', '--logfile', default=None,
|
|
|
+ action="store", dest="logfile",
|
|
|
+ help="Path to the logfile"),
|
|
|
+ Option('--pidfile', default="celeryd.pid",
|
|
|
+ action="store", dest="pidfile",
|
|
|
+ help="Path to the pidfile."),
|
|
|
+ Option('--uid', default=None,
|
|
|
+ action="store", dest="uid",
|
|
|
+ help="Effective user id to run as when detached."),
|
|
|
+ Option('--gid', default=None,
|
|
|
+ action="store", dest="gid",
|
|
|
+ help="Effective group id to run as when detached."),
|
|
|
+ Option('--umask', default=0,
|
|
|
+ action="store", type="int", dest="umask",
|
|
|
+ help="Umask of the process when detached."),
|
|
|
+ Option('--workdir', default=None,
|
|
|
+ action="store", dest="working_directory",
|
|
|
+ help="Directory to change to when detached."),
|
|
|
+ Option('--chroot', default=None,
|
|
|
+ action="store", dest="chroot_directory",
|
|
|
+ help="Change root directory to this path when detached."),
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+class detached(object):
|
|
|
+
|
|
|
+ def __init__(self, path, argv, logfile=None, pidfile=None, uid=None,
|
|
|
+ gid=None, umask=0, working_directory=None, chroot_directory=None):
|
|
|
+ self.path = path
|
|
|
+ self.argv = argv
|
|
|
+ self.logfile = logfile
|
|
|
+ self.pidfile = pidfile
|
|
|
+ self.uid = uid
|
|
|
+ self.gid = gid
|
|
|
+ self.umask = umask
|
|
|
+ self.working_directory = working_directory
|
|
|
+ self.chroot_directory = chroot_directory
|
|
|
+
|
|
|
+ def start(self):
|
|
|
+ context, on_stop = create_daemon_context(
|
|
|
+ logfile=self.logfile,
|
|
|
+ pidfile=self.pidfile,
|
|
|
+ uid=self.uid,
|
|
|
+ gid=self.gid,
|
|
|
+ umask=self.umask,
|
|
|
+ working_directory=self.working_directory,
|
|
|
+ chroot_directory=self.chroot_directory)
|
|
|
+ context.open()
|
|
|
+ try:
|
|
|
+ os.execv(self.path, [self.path] + self.argv)
|
|
|
+ finally:
|
|
|
+ on_stop()
|
|
|
+
|
|
|
+
|
|
|
+class PartialOptionParser(OptionParser):
|
|
|
+
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
+ self.leftovers = []
|
|
|
+ OptionParser.__init__(self, *args, **kwargs)
|
|
|
+
|
|
|
+ def _process_long_opt(self, rargs, values):
|
|
|
+ arg = rargs.pop(0)
|
|
|
+
|
|
|
+ if "=" in arg:
|
|
|
+ opt, next_arg = arg.split("=", 1)
|
|
|
+ rargs.insert(0, next_arg)
|
|
|
+ had_explicit_value = True
|
|
|
+ else:
|
|
|
+ opt = arg
|
|
|
+ had_explicit_value = False
|
|
|
+
|
|
|
+ try:
|
|
|
+ opt = self._match_long_opt(opt)
|
|
|
+ option = self._long_opt.get(opt)
|
|
|
+ except BadOptionError:
|
|
|
+ option = None
|
|
|
+
|
|
|
+ if option:
|
|
|
+ if option.takes_value():
|
|
|
+ nargs = option.nargs
|
|
|
+ if len(rargs) < nargs:
|
|
|
+ if nargs == 1:
|
|
|
+ self.error(_("%s option requires an argument") % opt)
|
|
|
+ else:
|
|
|
+ self.error(_("%s option requires %d arguments")
|
|
|
+ % (opt, nargs))
|
|
|
+ elif nargs == 1:
|
|
|
+ value = rargs.pop(0)
|
|
|
+ else:
|
|
|
+ value = tuple(rargs[0:nargs])
|
|
|
+ del rargs[0:nargs]
|
|
|
+
|
|
|
+ elif had_explicit_value:
|
|
|
+ self.error(_("%s option does not take a value") % opt)
|
|
|
+ else:
|
|
|
+ value = None
|
|
|
+ option.process(opt, value, values, self)
|
|
|
+ else:
|
|
|
+ self.leftovers.append(arg)
|
|
|
+
|
|
|
+ def _process_short_opts(self, rargs, values):
|
|
|
+ arg = rargs[0]
|
|
|
+ try:
|
|
|
+ OptionParser._process_short_opts(self, rargs, values)
|
|
|
+ except BadOptionError:
|
|
|
+ self.leftovers.append(arg)
|
|
|
+ if rargs and not rargs[0][0] == "-":
|
|
|
+ self.leftovers.append(rargs.pop(0))
|
|
|
+
|
|
|
+
|
|
|
+class detached_celeryd(object):
|
|
|
+ option_list = OPTION_LIST
|
|
|
+ usage = "%%prog [options] [celeryd options]"
|
|
|
+ version = __version__
|
|
|
+ description = ("Detaches Celery worker nodes. See `celeryd --help` "
|
|
|
+ "for the list of supported worker arguments.")
|
|
|
+ command = sys.executable
|
|
|
+ execv_path = sys.executable
|
|
|
+ execv_argv = ["-m", "celery.bin.celeryd"]
|
|
|
+
|
|
|
+ def Parser(self, prog_name):
|
|
|
+ return PartialOptionParser(prog=prog_name,
|
|
|
+ option_list=self.option_list,
|
|
|
+ usage=self.usage,
|
|
|
+ description=self.description,
|
|
|
+ version=self.version)
|
|
|
+
|
|
|
+ def parse_options(self, prog_name, argv):
|
|
|
+ parser = self.Parser(prog_name)
|
|
|
+ options, values = parser.parse_args(argv)
|
|
|
+ if options.logfile:
|
|
|
+ parser.leftovers.append("--logfile=%s" % (options.logfile, ))
|
|
|
+ if options.pidfile:
|
|
|
+ parser.leftovers.append("--pidfile=%s" % (options.pidfile, ))
|
|
|
+ print("LEFTOVERS: %r" % (parser.leftovers, ))
|
|
|
+ return options, values, parser.leftovers
|
|
|
+
|
|
|
+ def execute_from_commandline(self, argv=None):
|
|
|
+ if argv is None:
|
|
|
+ argv = sys.argv
|
|
|
+ prog_name = os.path.basename(argv[0])
|
|
|
+ options, values, leftovers = self.parse_options(prog_name, argv[1:])
|
|
|
+ detached(path=self.execv_path,
|
|
|
+ argv=self.execv_argv + leftovers,
|
|
|
+ **vars(options)).start()
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ detached_celeryd().execute_from_commandline()
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|