celeryd_detach.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. from __future__ import with_statement
  4. if __name__ == "__main__" and __package__ is None:
  5. __package__ = "celery.bin.celeryd_detach"
  6. import os
  7. import sys
  8. from optparse import OptionParser, BadOptionError
  9. from .. import __version__
  10. from ..platforms import detached
  11. from .base import daemon_options, Option
  12. OPTION_LIST = daemon_options(default_pidfile="celeryd.pid") + (
  13. Option("--fake",
  14. default=False, action="store_true", dest="fake",
  15. help="Don't fork (for debugging purposes)"), )
  16. def detach(path, argv, logfile=None, pidfile=None, uid=None,
  17. gid=None, umask=0, working_directory=None, fake=False, ):
  18. with detached(logfile, pidfile, uid, gid, umask, working_directory, fake):
  19. try:
  20. os.execv(path, [path] + argv)
  21. except Exception:
  22. import logging
  23. from ..log import setup_logger
  24. logger = setup_logger(logfile=logfile, loglevel=logging.ERROR)
  25. logger.critical("Can't exec %r", " ".join([path] + argv),
  26. exc_info=True)
  27. class PartialOptionParser(OptionParser):
  28. def __init__(self, *args, **kwargs):
  29. self.leftovers = []
  30. OptionParser.__init__(self, *args, **kwargs)
  31. def _process_long_opt(self, rargs, values):
  32. arg = rargs.pop(0)
  33. if "=" in arg:
  34. opt, next_arg = arg.split("=", 1)
  35. rargs.insert(0, next_arg)
  36. had_explicit_value = True
  37. else:
  38. opt = arg
  39. had_explicit_value = False
  40. try:
  41. opt = self._match_long_opt(opt)
  42. option = self._long_opt.get(opt)
  43. except BadOptionError:
  44. option = None
  45. if option:
  46. if option.takes_value():
  47. nargs = option.nargs
  48. if len(rargs) < nargs:
  49. if nargs == 1:
  50. self.error("%s option requires an argument" % opt)
  51. else:
  52. self.error("%s option requires %d arguments" % (
  53. opt, nargs))
  54. elif nargs == 1:
  55. value = rargs.pop(0)
  56. else:
  57. value = tuple(rargs[0:nargs])
  58. del rargs[0:nargs]
  59. elif had_explicit_value:
  60. self.error("%s option does not take a value" % opt)
  61. else:
  62. value = None
  63. option.process(opt, value, values, self)
  64. else:
  65. self.leftovers.append(arg)
  66. def _process_short_opts(self, rargs, values):
  67. arg = rargs[0]
  68. try:
  69. OptionParser._process_short_opts(self, rargs, values)
  70. except BadOptionError:
  71. self.leftovers.append(arg)
  72. if rargs and not rargs[0][0] == "-":
  73. self.leftovers.append(rargs.pop(0))
  74. class detached_celeryd(object):
  75. option_list = OPTION_LIST
  76. usage = "%prog [options] [celeryd options]"
  77. version = __version__
  78. description = ("Detaches Celery worker nodes. See `celeryd --help` "
  79. "for the list of supported worker arguments.")
  80. command = sys.executable
  81. execv_path = sys.executable
  82. execv_argv = ["-m", "celery.bin.celeryd"]
  83. def Parser(self, prog_name):
  84. return PartialOptionParser(prog=prog_name,
  85. option_list=self.option_list,
  86. usage=self.usage,
  87. description=self.description,
  88. version=self.version)
  89. def parse_options(self, prog_name, argv):
  90. parser = self.Parser(prog_name)
  91. options, values = parser.parse_args(argv)
  92. if options.logfile:
  93. parser.leftovers.append("--logfile=%s" % (options.logfile, ))
  94. if options.pidfile:
  95. parser.leftovers.append("--pidfile=%s" % (options.pidfile, ))
  96. return options, values, parser.leftovers
  97. def execute_from_commandline(self, argv=None):
  98. if argv is None:
  99. argv = sys.argv
  100. config = []
  101. seen_cargs = 0
  102. for arg in argv:
  103. if seen_cargs:
  104. config.append(arg)
  105. else:
  106. if arg == "--":
  107. seen_cargs = 1
  108. config.append(arg)
  109. prog_name = os.path.basename(argv[0])
  110. options, values, leftovers = self.parse_options(prog_name, argv[1:])
  111. detach(path=self.execv_path,
  112. argv=self.execv_argv + leftovers + config,
  113. **vars(options))
  114. def main():
  115. detached_celeryd().execute_from_commandline()
  116. if __name__ == "__main__":
  117. main()