|  | @@ -0,0 +1,224 @@
 | 
											
												
													
														|  | 
 |  | +#!/usr/bin/env python
 | 
											
												
													
														|  | 
 |  | +"""celerybeat
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. program:: celerybeat
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -f, --logfile
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Path to log file. If no logfile is specified, ``stderr`` is used.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -l, --loglevel
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Logging level, choose between ``DEBUG``, ``INFO``, ``WARNING``,
 | 
											
												
													
														|  | 
 |  | +    ``ERROR``, ``CRITICAL``, or ``FATAL``.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -p, --pidfile
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Path to pidfile.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -d, --detach, --daemon
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Run in the background as a daemon.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -u, --uid
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    User-id to run ``celerybeat`` as when in daemon mode.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: -g, --gid
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Group-id to run ``celerybeat`` as when in daemon mode.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: --umask
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    umask of the process when in daemon mode.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: --workdir
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Directory to change to when in daemon mode.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +.. cmdoption:: --chroot
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    Change root directory to this path when in daemon mode.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +"""
 | 
											
												
													
														|  | 
 |  | +import os
 | 
											
												
													
														|  | 
 |  | +import sys
 | 
											
												
													
														|  | 
 |  | +from celery.loaders import current_loader
 | 
											
												
													
														|  | 
 |  | +from celery.loaders import settings
 | 
											
												
													
														|  | 
 |  | +from celery import __version__
 | 
											
												
													
														|  | 
 |  | +from celery.log import emergency_error
 | 
											
												
													
														|  | 
 |  | +from celery import conf
 | 
											
												
													
														|  | 
 |  | +from celery import discovery
 | 
											
												
													
														|  | 
 |  | +from celery.task import discard_all
 | 
											
												
													
														|  | 
 |  | +from celery.worker import WorkController
 | 
											
												
													
														|  | 
 |  | +from celery import platform
 | 
											
												
													
														|  | 
 |  | +import traceback
 | 
											
												
													
														|  | 
 |  | +import optparse
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +STARTUP_INFO_FMT = """
 | 
											
												
													
														|  | 
 |  | +Configuration ->
 | 
											
												
													
														|  | 
 |  | +    * Broker -> amqp://%(vhost)s@%(host)s:%(port)s
 | 
											
												
													
														|  | 
 |  | +    * Exchange -> %(exchange)s (%(exchange_type)s)
 | 
											
												
													
														|  | 
 |  | +    * Consumer -> Queue:%(consumer_queue)s Routing:%(consumer_rkey)s
 | 
											
												
													
														|  | 
 |  | +""".strip()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +OPTION_LIST = (
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-f', '--logfile', default=conf.DAEMON_LOG_FILE,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="logfile",
 | 
											
												
													
														|  | 
 |  | +            help="Path to log file."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-l', '--loglevel', default=conf.DAEMON_LOG_LEVEL,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="loglevel",
 | 
											
												
													
														|  | 
 |  | +            help="Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL/FATAL."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-p', '--pidfile', default=conf.DAEMON_PID_FILE,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="pidfile",
 | 
											
												
													
														|  | 
 |  | +            help="Path to pidfile."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-d', '--detach', '--daemon', default=False,
 | 
											
												
													
														|  | 
 |  | +            action="store_true", dest="detach",
 | 
											
												
													
														|  | 
 |  | +            help="Run in the background as a daemon."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-u', '--uid', default=None,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="uid",
 | 
											
												
													
														|  | 
 |  | +            help="User-id to run celerybeat as when in daemon mode."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('-g', '--gid', default=None,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="gid",
 | 
											
												
													
														|  | 
 |  | +            help="Group-id to run celerybeat as when in daemon mode."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('--umask', default=0,
 | 
											
												
													
														|  | 
 |  | +            action="store", type="int", dest="umask",
 | 
											
												
													
														|  | 
 |  | +            help="umask of the process when in daemon mode."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('--workdir', default=None,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="working_directory",
 | 
											
												
													
														|  | 
 |  | +            help="Directory to change to when in daemon mode."),
 | 
											
												
													
														|  | 
 |  | +    optparse.make_option('--chroot', default=None,
 | 
											
												
													
														|  | 
 |  | +            action="store", dest="chroot",
 | 
											
												
													
														|  | 
 |  | +            help="Change root directory to this path when in daemon mode."),
 | 
											
												
													
														|  | 
 |  | +    )
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def run_clock(detach=False, loglevel=conf.DAEMON_LOG_LEVEL,
 | 
											
												
													
														|  | 
 |  | +        logfile=conf.DAEMON_LOG_FILE, pidfile=conf.DAEMON_PID_FILE,
 | 
											
												
													
														|  | 
 |  | +        umask=0, uid=None, gid=None, working_directory=None, chroot=None,
 | 
											
												
													
														|  | 
 |  | +        **kwargs):
 | 
											
												
													
														|  | 
 |  | +    """Starts the celerybeat clock server."""
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    print("Celery Beat %s is starting." % __version__)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    # set SIGCLD back to the default SIG_DFL (before python-daemon overrode
 | 
											
												
													
														|  | 
 |  | +    # it) lets the parent wait() for the terminated child process and stops
 | 
											
												
													
														|  | 
 |  | +    # the 'OSError: [Errno 10] No child processes' problem.
 | 
											
												
													
														|  | 
 |  | +    platform.reset_signal("SIGCLD")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if statistics is not None:
 | 
											
												
													
														|  | 
 |  | +        settings.CELERY_STATISTICS = statistics
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if conf.CELERY_BACKEND == "database" \
 | 
											
												
													
														|  | 
 |  | +            and settings.DATABASE_ENGINE == "sqlite3" and \
 | 
											
												
													
														|  | 
 |  | +            concurrency > 1:
 | 
											
												
													
														|  | 
 |  | +        import warnings
 | 
											
												
													
														|  | 
 |  | +        warnings.warn("The sqlite3 database engine doesn't support "
 | 
											
												
													
														|  | 
 |  | +                "concurrency. We'll be using a single process only.",
 | 
											
												
													
														|  | 
 |  | +                UserWarning)
 | 
											
												
													
														|  | 
 |  | +        concurrency = 1
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    # Setup logging
 | 
											
												
													
														|  | 
 |  | +    if not isinstance(loglevel, int):
 | 
											
												
													
														|  | 
 |  | +        loglevel = conf.LOG_LEVELS[loglevel.upper()]
 | 
											
												
													
														|  | 
 |  | +    if not detach:
 | 
											
												
													
														|  | 
 |  | +        logfile = None # log to stderr when not running in the background.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if discard:
 | 
											
												
													
														|  | 
 |  | +        discarded_count = discard_all()
 | 
											
												
													
														|  | 
 |  | +        what = discarded_count > 1 and "messages" or "message"
 | 
											
												
													
														|  | 
 |  | +        print("discard: Erased %d %s from the queue.\n" % (
 | 
											
												
													
														|  | 
 |  | +                discarded_count, what))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    # Dump configuration to screen so we have some basic information
 | 
											
												
													
														|  | 
 |  | +    # when users sends e-mails.
 | 
											
												
													
														|  | 
 |  | +    print(STARTUP_INFO_FMT % {
 | 
											
												
													
														|  | 
 |  | +            "vhost": getattr(settings, "AMQP_VHOST", "(default)"),
 | 
											
												
													
														|  | 
 |  | +            "host": getattr(settings, "AMQP_SERVER", "(default)"),
 | 
											
												
													
														|  | 
 |  | +            "port": getattr(settings, "AMQP_PORT", "(default)"),
 | 
											
												
													
														|  | 
 |  | +            "exchange": conf.AMQP_EXCHANGE,
 | 
											
												
													
														|  | 
 |  | +            "exchange_type": conf.AMQP_EXCHANGE_TYPE,
 | 
											
												
													
														|  | 
 |  | +            "consumer_queue": conf.AMQP_CONSUMER_QUEUE,
 | 
											
												
													
														|  | 
 |  | +            "consumer_rkey": conf.AMQP_CONSUMER_ROUTING_KEY,
 | 
											
												
													
														|  | 
 |  | +            "publisher_rkey": conf.AMQP_PUBLISHER_ROUTING_KEY,
 | 
											
												
													
														|  | 
 |  | +            "concurrency": concurrency,
 | 
											
												
													
														|  | 
 |  | +            "loglevel": loglevel,
 | 
											
												
													
														|  | 
 |  | +            "pidfile": pidfile,
 | 
											
												
													
														|  | 
 |  | +            "statistics": settings.CELERY_STATISTICS and "ON" or "OFF",
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    print("Celery has started.")
 | 
											
												
													
														|  | 
 |  | +    if detach:
 | 
											
												
													
														|  | 
 |  | +        from celery.log import setup_logger, redirect_stdouts_to_logger
 | 
											
												
													
														|  | 
 |  | +        context = platform.create_daemon_context(logfile, pidfile,
 | 
											
												
													
														|  | 
 |  | +                                        chroot_directory=chroot,
 | 
											
												
													
														|  | 
 |  | +                                        working_directory=working_directory,
 | 
											
												
													
														|  | 
 |  | +                                        umask=umask,
 | 
											
												
													
														|  | 
 |  | +                                        uid=uid,
 | 
											
												
													
														|  | 
 |  | +                                        gid=gid)
 | 
											
												
													
														|  | 
 |  | +        context.open()
 | 
											
												
													
														|  | 
 |  | +        logger = setup_logger(loglevel, logfile)
 | 
											
												
													
														|  | 
 |  | +        redirect_stdouts_to_logger(logger, loglevel)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    # Run the worker init handler.
 | 
											
												
													
														|  | 
 |  | +    # (Usually imports task modules and such.)
 | 
											
												
													
														|  | 
 |  | +    current_loader.on_worker_init()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def run_worker():
 | 
											
												
													
														|  | 
 |  | +        worker = WorkController(concurrency=concurrency,
 | 
											
												
													
														|  | 
 |  | +                                loglevel=loglevel,
 | 
											
												
													
														|  | 
 |  | +                                logfile=logfile,
 | 
											
												
													
														|  | 
 |  | +                                is_detached=detach)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # Install signal handler that restarts celeryd on SIGHUP,
 | 
											
												
													
														|  | 
 |  | +        # (only on POSIX systems)
 | 
											
												
													
														|  | 
 |  | +        install_worker_restart_handler(worker)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        try:
 | 
											
												
													
														|  | 
 |  | +            worker.start()
 | 
											
												
													
														|  | 
 |  | +        except Exception, e:
 | 
											
												
													
														|  | 
 |  | +            emergency_error(logfile, "celeryd raised exception %s: %s\n%s" % (
 | 
											
												
													
														|  | 
 |  | +                            e.__class__, e, traceback.format_exc()))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    try:
 | 
											
												
													
														|  | 
 |  | +        if supervised:
 | 
											
												
													
														|  | 
 |  | +            OFASupervisor(target=run_worker).start()
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            run_worker()
 | 
											
												
													
														|  | 
 |  | +    except:
 | 
											
												
													
														|  | 
 |  | +        if detach:
 | 
											
												
													
														|  | 
 |  | +            context.close()
 | 
											
												
													
														|  | 
 |  | +        raise
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def install_worker_restart_handler(worker):
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def restart_worker_sig_handler(signum, frame):
 | 
											
												
													
														|  | 
 |  | +        """Signal handler restarting the current python program."""
 | 
											
												
													
														|  | 
 |  | +        worker.logger.info("Restarting celeryd (%s)" % (
 | 
											
												
													
														|  | 
 |  | +            " ".join(sys.argv)))
 | 
											
												
													
														|  | 
 |  | +        if worker.is_detached:
 | 
											
												
													
														|  | 
 |  | +            pid = os.fork()
 | 
											
												
													
														|  | 
 |  | +            if pid:
 | 
											
												
													
														|  | 
 |  | +                worker.stop()
 | 
											
												
													
														|  | 
 |  | +                sys.exit(0)
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            worker.stop()
 | 
											
												
													
														|  | 
 |  | +        os.execv(sys.executable, [sys.executable] + sys.argv)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    platform.install_signal_handler("SIGHUP", restart_worker_sig_handler)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def parse_options(arguments):
 | 
											
												
													
														|  | 
 |  | +    """Parse the available options to ``celeryd``."""
 | 
											
												
													
														|  | 
 |  | +    parser = optparse.OptionParser(option_list=OPTION_LIST)
 | 
											
												
													
														|  | 
 |  | +    options, values = parser.parse_args(arguments)
 | 
											
												
													
														|  | 
 |  | +    return options
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +if __name__ == "__main__":
 | 
											
												
													
														|  | 
 |  | +    options = parse_options(sys.argv[1:])
 | 
											
												
													
														|  | 
 |  | +    run_worker(**vars(options))
 |