#!python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """zopectl -- control Zope using zdaemon. Usage: zopectl [options] [action [arguments]] Options: -h/--help -- print usage message and exit -b/--backoff-limit SECONDS -- set backoff limit to SECONDS (default 10) -d/--daemon -- run as a proper daemon; fork a subprocess, close files etc. -f/--forever -- run forever (by default, exit when backoff limit is exceeded) -h/--help -- print this usage message and exit -i/--interactive -- start an interactive shell after executing commands -l/--logfile -- log file to be read by logtail command -u/--user -- run the daemon manager program as this user (or numeric id) -m/--umask -- provide octal umask for files created by the managed process action [arguments] -- see below Actions are commands like "start", "stop" and "status". If -i is specified or no action is specified on the command line, a "shell" interpreting actions typed interactively is started (unless the configuration option default_to_interactive is set to false). Use the action "help" to find out about available actions. """ import os import sys import signal import zdaemon import Zope2.Startup from zdaemon.zdctl import ZDCmd from zdaemon.zdoptions import ZDOptions from ZConfig.components.logger.handlers import FileHandlerFactory def string_list(arg): return arg.split() class ZopeCtlOptions(ZDOptions): """Zope controller options. After initialization, this should look very much like a zdaemon.zdctl.ZDCtlOptions instance. Many of the attributes are initialized from different sources, however. """ positional_args_allowed = 1 program = "zopectl" schemadir = os.path.dirname(Zope2.Startup.__file__) schemafile = "zopeschema.xml" uid = gid = None # XXX Suppress using Zope's section to avoid using the # same logging for zdctl as for the Zope appserver. There still # needs to be a way to set a logfile for zdctl. logsectionname = None def __init__(self): ZDOptions.__init__(self) self.add("program", "runner.program", "p:", "program=", handler=string_list) self.add("backofflimit", "runner.backoff_limit", "b:", "backoff-limit=", int, default=10) self.add("daemon", "runner.daemon", "d", "daemon", flag=1, default=1) self.add("forever", "runner.forever", "f", "forever", flag=1, default=0) self.add("hang_around", "runner.hang_around", default=0) self.add("interactive", None, "i", "interactive", flag=1) self.add("default_to_interactive", "runner.default_to_interactive", default=1) self.add("logfile", None, "l:", "logfile=") self.add("user", "runner.user", "u:", "user=") self.add("prompt", "runner.prompt", default="zopectl>") self.add("umask", "runner.umask", "m:", "umask=") def realize(self, *args, **kw): ZDOptions.realize(self, *args, **kw) # Additional checking of user option; set uid and gid if self.user is not None: import pwd try: uid = int(self.user) except ValueError: try: pwrec = pwd.getpwnam(self.user) except KeyError: self.usage("username %r not found" % self.user) uid = pwrec[2] else: try: pwrec = pwd.getpwuid(uid) except KeyError: self.usage("uid %r not found" % self.user) gid = pwrec[3] self.uid = uid self.gid = gid config = self.configroot self.directory = config.instancehome self.clienthome = config.clienthome if config.runner and config.runner.program: self.program = config.runner.program else: self.program = [os.path.join(self.directory, "bin", "runzope")] self.sockname = os.path.join(self.clienthome, "zopectlsock") self.python = sys.executable self.zdrun = os.path.join(os.path.dirname(zdaemon.__file__), "zdrun.py") self.exitcodes = [0, 2] if self.logfile is None and config.eventlog is not None: for handler in config.eventlog.handler_factories: if isinstance(handler, FileHandlerFactory): self.logfile = handler.section.path if self.logfile not in ("STDERR", "STDOUT"): break class ZopeCmd(ZDCmd): def _get_override(self, opt, name, svalue=None, flag=0): # Suppress the config file, and pass all configuration via the # command line. This avoids needing to specialize the zdrun # script. if name == "configfile": return [] value = getattr(self.options, name) if value is None: return [] if flag: if value: args = [opt] else: args = [] else: if svalue is None: svalue = str(value) args = [opt, svalue] return args def do_start(self, arg): # signal to Zope that it is being managed #(to indicate it's web-restartable) os.putenv('ZMANAGED', '1') ZDCmd.do_start(self, arg) def get_startup_cmd(self, python, more): cmdline = ( '%s -c "from Zope2 import configure;' 'configure(\'%s\');' % (python, self.options.configfile) ) return cmdline + more + '\"' def do_debug(self, arg): cmdline = self.get_startup_cmd(self.options.python + ' -i', 'import Zope2; app=Zope2.app()') print ('Starting debugger (the name "app" is bound to the top-level ' 'Zope object)') os.system(cmdline) def do_foreground(self, arg): self.options.program[1:1] = ["-X", "debug-mode=on"] try: ZDCmd.do_foreground(self, arg) finally: self.options.program.remove("-X") self.options.program.remove("debug-mode=on") def help_debug(self): print "debug -- run the Zope debugger to inspect your database" print " manually using a Python interactive shell" def do_run(self, arg): tup = arg.split(' ') if not arg: print "usage: run