diff options
Diffstat (limited to 'src/mailman/commands/cli_control.py')
| -rw-r--r-- | src/mailman/commands/cli_control.py | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/mailman/commands/cli_control.py b/src/mailman/commands/cli_control.py new file mode 100644 index 000000000..919ebc0be --- /dev/null +++ b/src/mailman/commands/cli_control.py @@ -0,0 +1,169 @@ +# Copyright (C) 2009 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Module stuff.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + 'Start', + 'Stop', + ] + + +import os +import sys +import signal +import logging + +from zope.interface import implements + +from mailman.config import config +from mailman.i18n import _ +from mailman.interfaces.command import ICLISubCommand + + +qlog = logging.getLogger('mailman.qrunner') + + + +class Start: + """Start the Mailman daemons.""" + + implements(ICLISubCommand) + + name = 'start' + + def add(self, parser, command_parser): + """See `ICLISubCommand`.""" + command_parser.add_argument( + '-f', '--force', + default=False, action='store_true', + help=_("""\ + If the master watcher finds an existing master lock, it will + normally exit with an error message. With this option,the master + will perform an extra level of checking. If a process matching + the host/pid described in the lock file is running, the master + will still exit, requiring you to manually clean up the lock. But + if no matching process is found, the master will remove the + apparently stale lock and make another attempt to claim the master + lock.""")) + command_parser.add_argument( + '-u', '--run-as-user', + default=True, action='store_false', + help=_("""\ + Normally, this script will refuse to run if the user id and group + id are not set to the 'mailman' user and group (as defined when + you configured Mailman). If run as root, this script will change + to this user and group before the check is made. + + This can be inconvenient for testing and debugging purposes, so + the -u flag means that the step that sets and checks the uid/gid + is skipped, and the program is run as the current user and group. + This flag is not recommended for normal production environments. + + Note though, that if you run with -u and are not in the mailman + group, you may have permission problems, such as begin unable to + delete a list's archives through the web. Tough luck!""")) + command_parser.add_argument( + '-q', '--quiet', + default=False, action='store_true', + help=_("""\ + Don't print status messages. Error messages are still printed to + standard error.""")) + + def process(self, args): + """See `ICLISubCommand`.""" + def log(message): + if not args.quiet: + print message + # Daemon process startup according to Stevens, Advanced Programming in + # the UNIX Environment, Chapter 13. + pid = os.fork() + if pid: + # parent + log(_("Starting Mailman's master qrunner")) + return + # child: Create a new session and become the session leader, but since + # we won't be opening any terminal devices, don't do the + # ultra-paranoid suggestion of doing a second fork after the setsid() + # call. + os.setsid() + # Instead of cd'ing to root, cd to the Mailman runtime directory. + os.chdir(config.VAR_DIR) + # Exec the master watcher. + execl_args = [ + sys.executable, sys.executable, + os.path.join(config.BIN_DIR, 'master'), + ] + if args.force: + execl_args.append('--force') + if args.config: + execl_args.extend(['-C', args.config]) + qlog.debug('starting: %s', execl_args) + os.execl(*execl_args) + # We should never get here. + raise RuntimeError('os.execl() failed') + + + +def kill_watcher(sig): + try: + with open(config.PIDFILE) as fp: + pid = int(fp.read().strip()) + except (IOError, ValueError) as error: + # For i18n convenience + print >> sys.stderr, _('PID unreadable in: $config.PIDFILE') + print >> sys.stderr, error + print >> sys.stderr, _('Is qrunner even running?') + return + try: + os.kill(pid, sig) + except OSError as error: + if e.errno != errno.ESRCH: + raise + print >> sys.stderr, _('No child with pid: $pid') + print >> sys.stderr, e + print >> sys.stderr, _('Stale pid file removed.') + os.unlink(config.PIDFILE) + + + +class Stop: + """Stop the Mailman daemons.""" + + implements(ICLISubCommand) + + name = 'stop' + + def add(self, parser, command_parser): + """See `ICLISubCommand`.""" + command_parser.add_argument( + '-q', '--quiet', + default=False, action='store_true', + help=_("""\ + Don't print status messages. Error messages are still printed to + standard error.""")) + + def process(self, args): + """See `ICLISubCommand`.""" + def log(message): + if not args.quiet: + print message + log(_("Shutting down Mailman's master qrunner")) + kill_watcher(signal.SIGTERM) |
