|
|
a3d59b |
diff --git a/bin/mailmanctl b/bin/mailmanctl
|
|
|
a3d59b |
index fa14a2c..e291df1 100644
|
|
|
a3d59b |
--- a/bin/mailmanctl
|
|
|
a3d59b |
+++ b/bin/mailmanctl
|
|
|
a3d59b |
@@ -36,7 +36,7 @@ in the file data/master-qrunner.pid but you normally don't need to use this
|
|
|
a3d59b |
pid directly. The `start', `stop', `restart', and `reopen' commands handle
|
|
|
a3d59b |
everything for you.
|
|
|
a3d59b |
|
|
|
a3d59b |
-Usage: %(PROGRAM)s [options] [ start | stop | restart | reopen ]
|
|
|
a3d59b |
+Usage: %(PROGRAM)s [options] [ start | stop | restart | reopen | status ]
|
|
|
a3d59b |
|
|
|
a3d59b |
Options:
|
|
|
a3d59b |
|
|
|
a3d59b |
@@ -90,6 +90,9 @@ Commands:
|
|
|
a3d59b |
|
|
|
a3d59b |
reopen - This will close all log files, causing them to be re-opened the
|
|
|
a3d59b |
next time a message is written to them
|
|
|
a3d59b |
+
|
|
|
a3d59b |
+ status - This returns a string indicating the status of the master
|
|
|
a3d59b |
+ qrunner
|
|
|
a3d59b |
"""
|
|
|
a3d59b |
|
|
|
a3d59b |
import sys
|
|
|
a3d59b |
@@ -190,6 +193,52 @@ def qrunner_state():
|
|
|
a3d59b |
return 0
|
|
|
a3d59b |
return 1
|
|
|
a3d59b |
|
|
|
a3d59b |
+def mailman_status():
|
|
|
a3d59b |
+ # return status, pid
|
|
|
a3d59b |
+ #
|
|
|
a3d59b |
+ # These status values match the /etc/init.d status values
|
|
|
a3d59b |
+ # (at least on Red Hat), try to return equivalent status if possible
|
|
|
a3d59b |
+ # status is 0 if running,
|
|
|
a3d59b |
+ # status is 1 if dead but pid file exists
|
|
|
a3d59b |
+ # status is 2 if dead but subsys locked
|
|
|
a3d59b |
+ # status is 3 if stopped (pid returned will be 0)
|
|
|
a3d59b |
+ #
|
|
|
a3d59b |
+ #
|
|
|
a3d59b |
+ # We want any user to be able to query the status and this presents
|
|
|
a3d59b |
+ # few interesting permission problems and is why we don't use
|
|
|
a3d59b |
+ # qrunner_state(). The pidfile is only readable by the mailman owner
|
|
|
a3d59b |
+ # and group, however the lockfile is world readable. So we will
|
|
|
a3d59b |
+ # get the master pid from the lockfile. We try to determine if the
|
|
|
a3d59b |
+ # master process exists by sending it a signal. If we don't have
|
|
|
a3d59b |
+ # permission to signal the process, but the process exists we'll
|
|
|
a3d59b |
+ # get a EPERM error, if the process does not exist then we'll get
|
|
|
a3d59b |
+ # a ESRCH error.
|
|
|
a3d59b |
+
|
|
|
a3d59b |
+ try:
|
|
|
a3d59b |
+ hostname, pid, tempfile = get_lock_data()
|
|
|
a3d59b |
+ except IOError, e:
|
|
|
a3d59b |
+ if e.errno == errno.ENOENT:
|
|
|
a3d59b |
+ # Lock file didn't exist, can't be running
|
|
|
a3d59b |
+ return 3, 0
|
|
|
a3d59b |
+ else:
|
|
|
a3d59b |
+ raise
|
|
|
a3d59b |
+ if hostname <> socket.gethostname():
|
|
|
a3d59b |
+ # not running on this host
|
|
|
a3d59b |
+ return 3, 0
|
|
|
a3d59b |
+ # Find out if the process exists by calling kill with a signal 0.
|
|
|
a3d59b |
+ try:
|
|
|
a3d59b |
+ os.kill(pid, 0)
|
|
|
a3d59b |
+ except OSError, e:
|
|
|
a3d59b |
+ if e.errno == errno.ESRCH:
|
|
|
a3d59b |
+ # process does not exist
|
|
|
a3d59b |
+ return 1, pid
|
|
|
a3d59b |
+ elif e.errno == errno.EPERM:
|
|
|
a3d59b |
+ # we don't have permission signal the process but it exists
|
|
|
a3d59b |
+ return 0, pid
|
|
|
a3d59b |
+ else:
|
|
|
a3d59b |
+ raise
|
|
|
a3d59b |
+ return 0, pid
|
|
|
a3d59b |
+
|
|
|
a3d59b |
|
|
|
a3d59b |
def acquire_lock_1(force):
|
|
|
a3d59b |
# Be sure we can acquire the master qrunner lock. If not, it means some
|
|
|
a3d59b |
@@ -338,13 +387,15 @@ def main():
|
|
|
a3d59b |
command = COMMASPACE.join(args)
|
|
|
a3d59b |
usage(1, C_('Bad command: %(command)s'))
|
|
|
a3d59b |
|
|
|
a3d59b |
+ command = args[0].lower()
|
|
|
a3d59b |
+
|
|
|
a3d59b |
if checkprivs:
|
|
|
a3d59b |
check_privs()
|
|
|
a3d59b |
else:
|
|
|
a3d59b |
- print C_('Warning! You may encounter permission problems.')
|
|
|
a3d59b |
+ if command != 'status':
|
|
|
a3d59b |
+ print C_('Warning! You may encounter permission problems.')
|
|
|
a3d59b |
|
|
|
a3d59b |
# Handle the commands
|
|
|
a3d59b |
- command = args[0].lower()
|
|
|
a3d59b |
if command == 'stop':
|
|
|
a3d59b |
# Sent the master qrunner process a SIGINT, which is equivalent to
|
|
|
a3d59b |
# giving cron/qrunner a ctrl-c or KeyboardInterrupt. This will
|
|
|
a3d59b |
@@ -363,6 +414,14 @@ def main():
|
|
|
a3d59b |
if not quiet:
|
|
|
a3d59b |
print C_('Re-opening all log files')
|
|
|
a3d59b |
kill_watcher(signal.SIGHUP)
|
|
|
a3d59b |
+ elif command == 'status':
|
|
|
a3d59b |
+ status, pid = mailman_status()
|
|
|
a3d59b |
+ if not quiet:
|
|
|
a3d59b |
+ if status == 0:
|
|
|
a3d59b |
+ print C_("mailman (pid %(pid)d) is running...")
|
|
|
a3d59b |
+ else:
|
|
|
a3d59b |
+ print C_("mailman is stopped")
|
|
|
a3d59b |
+ sys.exit(status)
|
|
|
a3d59b |
elif command == 'start':
|
|
|
a3d59b |
# First, complain loudly if there's no site list.
|
|
|
a3d59b |
check_for_site_list()
|