|  | @@ -2,12 +2,12 @@
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  Some examples:
 |  |  Some examples:
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    # The "start" command just prints the commands needed to start the workers.
 |  | 
 | 
											
												
													
														|  | 
 |  | +    # The "show" command just prints the commands needed to start the workers.
 | 
											
												
													
														|  |      # Advanced example with 10 workers:
 |  |      # Advanced example with 10 workers:
 | 
											
												
													
														|  |      #   * Three of the workers processes the images and video queue
 |  |      #   * Three of the workers processes the images and video queue
 | 
											
												
													
														|  |      #   * Two of the workers processes the data queue with loglevel DEBUG
 |  |      #   * Two of the workers processes the data queue with loglevel DEBUG
 | 
											
												
													
														|  |      #   * the rest processes the default' queue.
 |  |      #   * the rest processes the default' queue.
 | 
											
												
													
														|  | -    $ celeryd-multi start 10 -l INFO -Q:1-3 images,video -Q:4,5:data
 |  | 
 | 
											
												
													
														|  | 
 |  | +    $ celeryd-multi show 10 -l INFO -Q:1-3 images,video -Q:4,5:data
 | 
											
												
													
														|  |          -Q default -L:4,5 DEBUG
 |  |          -Q default -L:4,5 DEBUG
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      # To actually start the workers into the background you need to
 |  |      # To actually start the workers into the background you need to
 | 
											
										
											
												
													
														|  | @@ -72,42 +72,80 @@ import socket
 | 
											
												
													
														|  |  import sys
 |  |  import sys
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  from subprocess import Popen
 |  |  from subprocess import Popen
 | 
											
												
													
														|  | 
 |  | +from time import sleep
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +from celery import __version__
 | 
											
												
													
														|  | 
 |  | +from celery.utils import term
 | 
											
												
													
														|  |  from celery.utils.compat import defaultdict
 |  |  from celery.utils.compat import defaultdict
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  SIGNAMES = set(sig for sig in dir(signal)
 |  |  SIGNAMES = set(sig for sig in dir(signal)
 | 
											
												
													
														|  |                          if sig.startswith("SIG") and "_" not in sig)
 |  |                          if sig.startswith("SIG") and "_" not in sig)
 | 
											
												
													
														|  | 
 |  | +SIGMAP = dict((getattr(signal, name), name) for name in SIGNAMES)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +USAGE = """\
 | 
											
												
													
														|  | 
 |  | +usage: %(prog_name)s detach <node1 node2 nodeN|range> [celeryd options]
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s stop <n1 n2 nN|range> [-SIG (default: -TERM)]
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s restart <n1 n2 nN|range> [-SIG] [celeryd options]
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s kill <n1 n2 nN|range>
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s show <n1 n2 nN|range> [celeryd options]
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s get hostname <n1 n2 nN|range> [-qv] [celeryd options]
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s names <n1 n2 nN|range>
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s expand template <n1 n2 nN|range> 
 | 
											
												
													
														|  | 
 |  | +       %(prog_name)s help
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +additional options (must appear after command name):
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    * --quiet:      Don't show as much output.
 | 
											
												
													
														|  | 
 |  | +    * --verbose:    Show more output.
 | 
											
												
													
														|  | 
 |  | +    * --no-color:   Don't display colors.
 | 
											
												
													
														|  | 
 |  | +"""
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  def main():
 |  |  def main():
 | 
											
												
													
														|  | -    sys.exit(MultiTool()(sys.argv[1:]))
 |  | 
 | 
											
												
													
														|  | 
 |  | +    sys.exit(MultiTool().execute_from_commandline(sys.argv))
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  class MultiTool(object):
 |  |  class MultiTool(object):
 | 
											
												
													
														|  |      retcode = 0  # Final exit code.
 |  |      retcode = 0  # Final exit code.
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def __init__(self):
 |  |      def __init__(self):
 | 
											
												
													
														|  | -        self.commands = {"start": self.start,
 |  | 
 | 
											
												
													
														|  | -                         "stop": self.stop,
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.commands = {"start": self.show, # XXX Deprecate
 | 
											
												
													
														|  | 
 |  | +                         "show": self.show,
 | 
											
												
													
														|  |                           "detach": self.detach,
 |  |                           "detach": self.detach,
 | 
											
												
													
														|  | 
 |  | +                         "stop": self.stop,
 | 
											
												
													
														|  | 
 |  | +                         "restart": self.restart,
 | 
											
												
													
														|  | 
 |  | +                         "kill": self.kill,
 | 
											
												
													
														|  |                           "names": self.names,
 |  |                           "names": self.names,
 | 
											
												
													
														|  |                           "expand": self.expand,
 |  |                           "expand": self.expand,
 | 
											
												
													
														|  |                           "get": self.get,
 |  |                           "get": self.get,
 | 
											
												
													
														|  |                           "help": self.help}
 |  |                           "help": self.help}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def __call__(self, argv, cmd="celeryd"):
 |  | 
 | 
											
												
													
														|  | -        if len(argv) == 0 or argv[0][0] == "-":
 |  | 
 | 
											
												
													
														|  | -            return self.error()
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def execute_from_commandline(self, argv, cmd="celeryd"):
 | 
											
												
													
														|  | 
 |  | +        argv = list(argv)   # don't modify callers argv.
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        # Reserve the --quite|-q/--verbose options.
 |  | 
 | 
											
												
													
														|  | 
 |  | +        # Reserve the --quiet|-q/--verbose options.
 | 
											
												
													
														|  |          self.quiet = False
 |  |          self.quiet = False
 | 
											
												
													
														|  |          self.verbose = False
 |  |          self.verbose = False
 | 
											
												
													
														|  | 
 |  | +        self.no_color = False
 | 
											
												
													
														|  |          if "--quiet" in argv:
 |  |          if "--quiet" in argv:
 | 
											
												
													
														|  |              self.quiet = argv.pop(argv.index("--quiet"))
 |  |              self.quiet = argv.pop(argv.index("--quiet"))
 | 
											
												
													
														|  |          if "-q" in argv:
 |  |          if "-q" in argv:
 | 
											
												
													
														|  |              self.quiet = argv.pop(argv.index("-q"))
 |  |              self.quiet = argv.pop(argv.index("-q"))
 | 
											
												
													
														|  |          if "--verbose" in argv:
 |  |          if "--verbose" in argv:
 | 
											
												
													
														|  |              self.verbose = argv.pop(argv.index("--verbose"))
 |  |              self.verbose = argv.pop(argv.index("--verbose"))
 | 
											
												
													
														|  | 
 |  | +        if "--no-color" in argv:
 | 
											
												
													
														|  | 
 |  | +            self.no_color = argv.pop(argv.index("--no-color"))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        self.colored = term.colored(enabled=not self.no_color)
 | 
											
												
													
														|  | 
 |  | +        self.OK = str(self.colored.green("OK"))
 | 
											
												
													
														|  | 
 |  | +        self.FAILED = str(self.colored.red("FAILED"))
 | 
											
												
													
														|  | 
 |  | +        self.DOWN = str(self.colored.magenta("DOWN"))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        self.prog_name = os.path.basename(argv.pop(0))
 | 
											
												
													
														|  | 
 |  | +        if len(argv) == 0 or argv[0][0] == "-":
 | 
											
												
													
														|  | 
 |  | +            return self.error()
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          try:
 |  |          try:
 | 
											
												
													
														|  |              self.commands[argv[0]](argv[1:], cmd)
 |  |              self.commands[argv[0]](argv[1:], cmd)
 | 
											
										
											
												
													
														|  | @@ -125,50 +163,150 @@ class MultiTool(object):
 | 
											
												
													
														|  |          wanted = argv[0]
 |  |          wanted = argv[0]
 | 
											
												
													
														|  |          p = NamespacedOptionParser(argv[1:])
 |  |          p = NamespacedOptionParser(argv[1:])
 | 
											
												
													
														|  |          for name, worker, _ in multi_args(p, cmd):
 |  |          for name, worker, _ in multi_args(p, cmd):
 | 
											
												
													
														|  | 
 |  | +            print("NAME: %s WANTED: %s" % (name, wanted))
 | 
											
												
													
														|  |              if name == wanted:
 |  |              if name == wanted:
 | 
											
												
													
														|  |                  print(" ".join(worker))
 |  |                  print(" ".join(worker))
 | 
											
												
													
														|  |                  return
 |  |                  return
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def start(self, argv, cmd):
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def show(self, argv, cmd):
 | 
											
												
													
														|  |          p = NamespacedOptionParser(argv)
 |  |          p = NamespacedOptionParser(argv)
 | 
											
												
													
														|  | 
 |  | +        self.note("> Starting nodes...")
 | 
											
												
													
														|  |          print("\n".join(" ".join(worker)
 |  |          print("\n".join(" ".join(worker)
 | 
											
												
													
														|  |                          for _, worker, _ in multi_args(p, cmd)))
 |  |                          for _, worker, _ in multi_args(p, cmd)))
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def detach(self, argv, cmd):
 |  |      def detach(self, argv, cmd):
 | 
											
												
													
														|  | 
 |  | +        self.splash()
 | 
											
												
													
														|  |          p = NamespacedOptionParser(argv)
 |  |          p = NamespacedOptionParser(argv)
 | 
											
												
													
														|  | 
 |  | +        self.with_detacher_default_options(p)
 | 
											
												
													
														|  | 
 |  | +        retcodes = []
 | 
											
												
													
														|  | 
 |  | +        self.note("> Starting nodes...")
 | 
											
												
													
														|  | 
 |  | +        for nodename, argv, _ in multi_args(p, cmd):
 | 
											
												
													
														|  | 
 |  | +            self.note("\t> %s: " % (nodename, ), newline=False)
 | 
											
												
													
														|  | 
 |  | +            retcode = self.waitexec(argv)
 | 
											
												
													
														|  | 
 |  | +            self.note(retcode and self.FAILED or self.OK)
 | 
											
												
													
														|  | 
 |  | +            retcodes.append(retcode)
 | 
											
												
													
														|  | 
 |  | +        self.retcode = int(any(retcodes))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def with_detacher_default_options(self, p):
 | 
											
												
													
														|  |          p.options.setdefault("--pidfile", "celeryd@%n.pid")
 |  |          p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
											
												
													
														|  |          p.options.setdefault("--logfile", "celeryd@%n.log")
 |  |          p.options.setdefault("--logfile", "celeryd@%n.log")
 | 
											
												
													
														|  |          p.options.setdefault("--cmd", "-m celery.bin.celeryd_detach")
 |  |          p.options.setdefault("--cmd", "-m celery.bin.celeryd_detach")
 | 
											
												
													
														|  | -        retcodes = []
 |  | 
 | 
											
												
													
														|  | -        for nodename, argv, _ in multi_args(p, cmd):
 |  | 
 | 
											
												
													
														|  | -            self.note("> Starting node %s..." % (nodename, ))
 |  | 
 | 
											
												
													
														|  | -            retcodes.append(self.waitexec(argv))
 |  | 
 | 
											
												
													
														|  | -        self.retcode = not any(retcodes)
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def stop(self, argv, cmd):
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def signal_node(self, nodename, pid, sig):
 | 
											
												
													
														|  | 
 |  | +        try:
 | 
											
												
													
														|  | 
 |  | +            os.kill(pid, sig)
 | 
											
												
													
														|  | 
 |  | +        except OSError, exc:
 | 
											
												
													
														|  | 
 |  | +            if os.errno != errno.ESRCH:
 | 
											
												
													
														|  | 
 |  | +                raise
 | 
											
												
													
														|  | 
 |  | +            self.note("Could not signal %s (%s): No such process" % (
 | 
											
												
													
														|  | 
 |  | +                        nodename, pid))
 | 
											
												
													
														|  | 
 |  | +            return False
 | 
											
												
													
														|  | 
 |  | +        return True
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def node_alive(self, pid):
 | 
											
												
													
														|  | 
 |  | +        try:
 | 
											
												
													
														|  | 
 |  | +            os.kill(pid, 0)
 | 
											
												
													
														|  | 
 |  | +        except OSError, exc:
 | 
											
												
													
														|  | 
 |  | +            if exc.errno == errno.ESRCH:
 | 
											
												
													
														|  | 
 |  | +                return False
 | 
											
												
													
														|  | 
 |  | +            raise
 | 
											
												
													
														|  | 
 |  | +        return True
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def shutdown_nodes(self, nodes, sig=signal.SIGTERM, retry=None,
 | 
											
												
													
														|  | 
 |  | +            callback=None):
 | 
											
												
													
														|  | 
 |  | +        if not nodes:
 | 
											
												
													
														|  | 
 |  | +            return
 | 
											
												
													
														|  | 
 |  | +        P = set(nodes)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        def on_down(node):
 | 
											
												
													
														|  | 
 |  | +            P.discard(node)
 | 
											
												
													
														|  | 
 |  | +            if callback:
 | 
											
												
													
														|  | 
 |  | +                callback(*node)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        self.note(self.colored.blue("> Stopping nodes..."))
 | 
											
												
													
														|  | 
 |  | +        for node in P:
 | 
											
												
													
														|  | 
 |  | +            nodename, _, pid = node
 | 
											
												
													
														|  | 
 |  | +            self.note("\t> %s: %s -> %s" % (nodename, SIGMAP[sig][3:], pid))
 | 
											
												
													
														|  | 
 |  | +            if not self.signal_node(nodename, pid, sig):
 | 
											
												
													
														|  | 
 |  | +                on_down(node)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        def note_waiting():
 | 
											
												
													
														|  | 
 |  | +            left = len(P)
 | 
											
												
													
														|  | 
 |  | +            if left:
 | 
											
												
													
														|  | 
 |  | +                self.note(self.colored.blue("> Waiting for %s %s..." % (
 | 
											
												
													
														|  | 
 |  | +                    left, left > 1 and "nodes" or "node")), newline=False)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        if retry:
 | 
											
												
													
														|  | 
 |  | +            note_waiting()
 | 
											
												
													
														|  | 
 |  | +            its = 0
 | 
											
												
													
														|  | 
 |  | +            while P:
 | 
											
												
													
														|  | 
 |  | +                for node in P:
 | 
											
												
													
														|  | 
 |  | +                    its += 1
 | 
											
												
													
														|  | 
 |  | +                    self.note(".", newline=False)
 | 
											
												
													
														|  | 
 |  | +                    nodename, _, pid = node
 | 
											
												
													
														|  | 
 |  | +                    if not self.node_alive(pid):
 | 
											
												
													
														|  | 
 |  | +                        self.note("\n\t> %s: %s" % (nodename, self.OK))
 | 
											
												
													
														|  | 
 |  | +                        on_down(node)
 | 
											
												
													
														|  | 
 |  | +                        note_waiting()
 | 
											
												
													
														|  | 
 |  | +                        break
 | 
											
												
													
														|  | 
 |  | +                if P and not its % len(P):
 | 
											
												
													
														|  | 
 |  | +                    sleep(float(retry))
 | 
											
												
													
														|  | 
 |  | +            self.note("")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def getpids(self, p, cmd, callback=None):
 | 
											
												
													
														|  |          from celery import platforms
 |  |          from celery import platforms
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        p = NamespacedOptionParser(argv)
 |  | 
 | 
											
												
													
														|  | -        restargs = p.args[len(p.values):]
 |  | 
 | 
											
												
													
														|  | -        sig = findsig(restargs)
 |  | 
 | 
											
												
													
														|  |          pidfile_template = p.options.setdefault("--pidfile", "celeryd@%n.pid")
 |  |          pidfile_template = p.options.setdefault("--pidfile", "celeryd@%n.pid")
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        for nodename, _, expander in multi_args(p, cmd):
 |  | 
 | 
											
												
													
														|  | 
 |  | +        nodes = []
 | 
											
												
													
														|  | 
 |  | +        for nodename, argv, expander in multi_args(p, cmd):
 | 
											
												
													
														|  |              pidfile = expander(pidfile_template)
 |  |              pidfile = expander(pidfile_template)
 | 
											
												
													
														|  |              try:
 |  |              try:
 | 
											
												
													
														|  |                  pid = platforms.read_pid_from_pidfile(pidfile)
 |  |                  pid = platforms.read_pid_from_pidfile(pidfile)
 | 
											
												
													
														|  |              except ValueError:
 |  |              except ValueError:
 | 
											
												
													
														|  |                  pass
 |  |                  pass
 | 
											
												
													
														|  |              if pid:
 |  |              if pid:
 | 
											
												
													
														|  | -                self.note("> Stopping node %s (%s)..." % (nodename, pid))
 |  | 
 | 
											
												
													
														|  | -                try:
 |  | 
 | 
											
												
													
														|  | -                    os.kill(pid, sig)
 |  | 
 | 
											
												
													
														|  | -                except OSError, exc:
 |  | 
 | 
											
												
													
														|  | -                    if exc.errno != errno.ESRCH:
 |  | 
 | 
											
												
													
														|  | -                        raise
 |  | 
 | 
											
												
													
														|  | -                    self.note("Could not stop pid %s: No such process." % pid)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                nodes.append((nodename, tuple(argv), pid))
 | 
											
												
													
														|  |              else:
 |  |              else:
 | 
											
												
													
														|  | -                self.note("> Skipping node %s: not alive." % (nodename, ))
 |  | 
 | 
											
												
													
														|  | 
 |  | +                self.note("> %s: %s" % (nodename, self.DOWN))
 | 
											
												
													
														|  | 
 |  | +                if callback:
 | 
											
												
													
														|  | 
 |  | +                    callback(nodename, argv, pid)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return nodes
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def kill(self, argv, cmd):
 | 
											
												
													
														|  | 
 |  | +        self.splash()
 | 
											
												
													
														|  | 
 |  | +        p = NamespacedOptionParser(argv)
 | 
											
												
													
														|  | 
 |  | +        for nodename, _, pid in self.getpids(p, cmd):
 | 
											
												
													
														|  | 
 |  | +            self.note("Killing node %s (%s)" % (nodename, pid))
 | 
											
												
													
														|  | 
 |  | +            self.signal_node(nodename, pid, signal.SIGKILL)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def stop(self, argv, cmd):
 | 
											
												
													
														|  | 
 |  | +        self.splash()
 | 
											
												
													
														|  | 
 |  | +        p = NamespacedOptionParser(argv)
 | 
											
												
													
														|  | 
 |  | +        return self._stop_nodes(p, cmd)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _stop_nodes(self, p, cmd, retry=None, callback=None):
 | 
											
												
													
														|  | 
 |  | +        restargs = p.args[len(p.values):]
 | 
											
												
													
														|  | 
 |  | +        self.shutdown_nodes(self.getpids(p, cmd, callback=callback),
 | 
											
												
													
														|  | 
 |  | +                            sig=findsig(restargs),
 | 
											
												
													
														|  | 
 |  | +                            retry=retry,
 | 
											
												
													
														|  | 
 |  | +                            callback=callback)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def restart(self, argv, cmd):
 | 
											
												
													
														|  | 
 |  | +        self.splash()
 | 
											
												
													
														|  | 
 |  | +        p = NamespacedOptionParser(argv)
 | 
											
												
													
														|  | 
 |  | +        self.with_detacher_default_options(p)
 | 
											
												
													
														|  | 
 |  | +        retvals = []
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        def on_node_shutdown(nodename, argv, pid):
 | 
											
												
													
														|  | 
 |  | +            self.note(self.colored.blue(
 | 
											
												
													
														|  | 
 |  | +                "> Restarting node %s: " % nodename), newline=False)
 | 
											
												
													
														|  | 
 |  | +            retval = self.waitexec(argv)
 | 
											
												
													
														|  | 
 |  | +            self.note(retval and self.FAILED or self.OK)
 | 
											
												
													
														|  | 
 |  | +            retvals.append(retval)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        self._stop_nodes(p, cmd, retry=2, callback=on_node_shutdown)
 | 
											
												
													
														|  | 
 |  | +        self.retval = int(any(retvals))
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def expand(self, argv, cmd=None):
 |  |      def expand(self, argv, cmd=None):
 | 
											
												
													
														|  |          template = argv[0]
 |  |          template = argv[0]
 | 
											
										
											
												
													
														|  | @@ -180,18 +318,24 @@ class MultiTool(object):
 | 
											
												
													
														|  |          say(__doc__)
 |  |          say(__doc__)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def usage(self):
 |  |      def usage(self):
 | 
											
												
													
														|  | -        say("Please use one of the following commands: %s" % (
 |  | 
 | 
											
												
													
														|  | -            ", ".join(self.commands.keys())))
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.splash()
 | 
											
												
													
														|  | 
 |  | +        say(USAGE % {"prog_name": self.prog_name})
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def splash(self):
 | 
											
												
													
														|  | 
 |  | +        c = self.colored
 | 
											
												
													
														|  | 
 |  | +        self.note(c.cyan("%s v%s" % (self.prog_name, __version__)))
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def waitexec(self, argv, path=sys.executable):
 |  |      def waitexec(self, argv, path=sys.executable):
 | 
											
												
													
														|  | -        pipe = Popen(shlex.split(" ".join([path] + argv)))
 |  | 
 | 
											
												
													
														|  | -        self.info("  %s" % " ".join([path] + argv))
 |  | 
 | 
											
												
													
														|  | 
 |  | +        argstr = shlex.split(" ".join([path] + list(argv)))
 | 
											
												
													
														|  | 
 |  | +        pipe = Popen(argstr)
 | 
											
												
													
														|  | 
 |  | +        self.info("  %s" % " ".join(argstr))
 | 
											
												
													
														|  |          retcode = pipe.wait()
 |  |          retcode = pipe.wait()
 | 
											
												
													
														|  |          if retcode < 0:
 |  |          if retcode < 0:
 | 
											
												
													
														|  |              self.note("* Child was terminated by signal %s" % (-retcode, ))
 |  |              self.note("* Child was terminated by signal %s" % (-retcode, ))
 | 
											
												
													
														|  | 
 |  | +            return -retcode
 | 
											
												
													
														|  |          elif retcode > 0:
 |  |          elif retcode > 0:
 | 
											
												
													
														|  |              self.note("* Child terminated with failure code %s" % (retcode, ))
 |  |              self.note("* Child terminated with failure code %s" % (retcode, ))
 | 
											
												
													
														|  | -        return retcode == 0
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return retcode
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def error(self, msg=None):
 |  |      def error(self, msg=None):
 | 
											
												
													
														|  |          if msg:
 |  |          if msg:
 | 
											
										
											
												
													
														|  | @@ -200,13 +344,13 @@ class MultiTool(object):
 | 
											
												
													
														|  |          self.retcode = 1
 |  |          self.retcode = 1
 | 
											
												
													
														|  |          return 1
 |  |          return 1
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def info(self, msg):
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def info(self, msg, newline=True):
 | 
											
												
													
														|  |          if self.verbose:
 |  |          if self.verbose:
 | 
											
												
													
														|  | -            self.note(msg)
 |  | 
 | 
											
												
													
														|  | 
 |  | +            self.note(msg, newline=newline)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def note(self, msg):
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def note(self, msg, newline=True):
 | 
											
												
													
														|  |          if not self.quiet:
 |  |          if not self.quiet:
 | 
											
												
													
														|  | -            say(msg)
 |  | 
 | 
											
												
													
														|  | 
 |  | +            say(str(msg), newline=newline)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  def multi_args(p, cmd="celeryd", append="", prefix="", suffix=""):
 |  |  def multi_args(p, cmd="celeryd", append="", prefix="", suffix=""):
 | 
											
										
											
												
													
														|  | @@ -332,8 +476,8 @@ def abbreviations(map):
 | 
											
												
													
														|  |      return expand
 |  |      return expand
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -def say(m):
 |  | 
 | 
											
												
													
														|  | -    sys.stderr.write("%s\n" % (m, ))
 |  | 
 | 
											
												
													
														|  | 
 |  | +def say(m, newline=True):
 | 
											
												
													
														|  | 
 |  | +    sys.stderr.write(newline and "%s\n" % (m, ) or m)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  def findsig(args, default=signal.SIGTERM):
 |  |  def findsig(args, default=signal.SIGTERM):
 |