[Zope-Checkins] SVN: zdaemon/trunk/ Bugs Fixed
Jim Fulton
jim at zope.com
Thu Dec 21 18:46:15 EST 2006
Log message for revision 71643:
Bugs Fixed
----------
- In non-daemon mode, start hung, producing annoying dots
when the program exited.
- The start command hung producing annoying dots if the deamon failed
to start.
- foreground and start had different semantics because one used
os.system and another used os.spawn
New Features
------------
- Documentation
- Command-line arguments can now be supplied to the start and
foreground (fg) commands
- zdctl now invokes itself to run zdrun. This means that it's
no-longer necessary to generate a separate zdrun script. This
especially when the magic techniques to find and run zdrun using
directory sniffing fail to set the path corrrectly.
- The daemon mode is now enabled by default. To get non-deamon mode,
you have to use a configuration file and set deamon to off
there. The old -d option is kept for backward compatibility, but is
a no-op.
Changed:
U zdaemon/trunk/CHANGES.txt
A zdaemon/trunk/src/zdaemon/README.txt
U zdaemon/trunk/src/zdaemon/component.xml
A zdaemon/trunk/src/zdaemon/tests/tests.py
U zdaemon/trunk/src/zdaemon/zdctl.py
U zdaemon/trunk/src/zdaemon/zdoptions.py
-=-
Modified: zdaemon/trunk/CHANGES.txt
===================================================================
--- zdaemon/trunk/CHANGES.txt 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/CHANGES.txt 2006-12-21 23:46:14 UTC (rev 71643)
@@ -1,19 +1,88 @@
zdaemon Changelog
-=================
+*****************
+To-Dos
+======
+
+Tests:
+
+- non-daemon mode
+
+- no infinite loop when program fails on start
+
+More docs:
+
+- Document/demonstrate some important features, such as:
+
+ - transcript log
+
+ - working directory
+
+- Reference docs
+
+
+Features
+
+- environment variables
+
+- transcript log rotation
+
+Bugs
+
+- help command
+
+
+zdaemon 2.0a1 (2006/12/21)
+==========================
+
+Bugs Fixed
+----------
+
+- In non-daemon mode, start hung, producing annoying dots
+ when the program exited.
+
+- The start command hung producing annoying dots if the deamon failed
+ to start.
+
+- foreground and start had different semantics because one used
+ os.system and another used os.spawn
+
+New Features
+------------
+
+- Documentation
+
+- Command-line arguments can now be supplied to the start and
+ foreground (fg) commands
+
+- zdctl now invokes itself to run zdrun. This means that it's
+ no-longer necessary to generate a separate zdrun script. This
+ especially when the magic techniques to find and run zdrun using
+ directory sniffing fail to set the path corrrectly.
+
+- The daemon mode is now enabled by default. To get non-deamon mode,
+ you have to use a configuration file and set deamon to off
+ there. The old -d option is kept for backward compatibility, but is
+ a no-op.
+
+zdaemon 1.4a1 (2005/11/21)
+==========================
+
+Fixed a bug in the distribution setup file.
+
zdaemon 1.4a1 (2005/11/05)
---------------------------
+==========================
First semi-formal release.
After some unknown release(???)
--------------------------------
+===============================
- Made 'zdaemon.zdoptions' not fail for --help when __main__.__doc__
is None.
After zdaemon 1.1
------------------
+=================
- Updated test 'testRunIgnoresParentSignals':
@@ -40,7 +109,7 @@
forceful warning.
zdaemon 1.1 (2005/06/09)
-------------------------
+========================
- SVN tag: svn://svn.zope.org/repos/main/zdaemon/tags/zdaemon-1.1
Added: zdaemon/trunk/src/zdaemon/README.txt
===================================================================
--- zdaemon/trunk/src/zdaemon/README.txt 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/src/zdaemon/README.txt 2006-12-21 23:46:14 UTC (rev 71643)
@@ -0,0 +1,139 @@
+Using zdaemon
+=============
+
+zdaemon provides a script, zdaemon, that can be used to running other
+programs as POSIX (Unix) daemons. (Of course, it is only usable on
+POSIX-complient systems.
+
+Using zdaemon requires specifying a number of options, which can be
+given in a configuration file, or as command-line options. It also
+accepts commands teling it what do do. The commants are:
+
+start
+ Start a process as a daemon
+
+stop
+ Stop a running daemon process
+
+restart
+ Stop and then restart a program
+
+status
+ Find out if the program is running
+
+foreground or fg
+ Run a program
+
+kill signal
+ Send a signal to the daemon process
+
+help command
+ Get help on a command
+
+
+Commands can be given on a command line, or can be given using an
+interactive interpreter.
+
+Let's start with a simple example. We'll use command-line options to
+run the echo command:
+
+ >>> system("./zdaemon -p 'echo hello world' fg")
+ echo hello world
+ hello world
+
+Here we used the -p option to specify a program to run. We can
+specify a program name and command-line options in the program
+command. Note, however, that the command-line parsing is pretty
+primitive. Quotes and spaces aren't handled correctly. Let's look at
+a slightly more complex example. We'll run the sleep command as a
+daemon :)
+
+ >>> system("./zdaemon -p 'sleep 100' start")
+ . daemon process started, pid=819
+
+This ran the sleep deamon. We can check whether it ran with the
+status command:
+
+ >>> system("./zdaemon -p 'sleep 100' status")
+ program running; pid=819
+
+We can stop it with the stop command:
+
+ >>> system("./zdaemon -p 'sleep 100' stop")
+ daemon process stopped
+
+ >>> system("./zdaemon -p 'sleep 100' status")
+ daemon manager not running
+
+Normally, we control zdaemon using a configuration file. Let's create
+a typical configuration file:
+
+ >>> open('conf', 'w').write(
+ ... '''
+ ... <runner>
+ ... program sleep 100
+ ... </runner>
+ ... ''')
+
+Now, we can run with the -C option to read the configuration file:
+
+ >>> system("./zdaemon -Cconf start")
+ . daemon process started, pid=1136
+
+If we list the directory:
+
+ >>> system("ls")
+ conf
+ zdaemon
+ zdsock
+
+We'll see that a file, zdsock, was created. This is a unix-domain
+socket used internally by ZDaemon. We'll normally want to control
+where this goes.
+
+ >>> system("./zdaemon -Cconf stop")
+ daemon process stopped
+
+ >>> open('conf', 'w').write(
+ ... '''
+ ... <runner>
+ ... program sleep 100
+ ... socket-name /tmp/demo.zdsock
+ ... </runner>
+ ... ''')
+
+
+ >>> system("./zdaemon -Cconf start")
+ . daemon process started, pid=1139
+
+ >>> system("ls")
+ conf
+ zdaemon
+
+ >>> import os
+ >>> os.path.exists("/tmp/demo.zdsock")
+ True
+
+ >>> system("./zdaemon -Cconf stop")
+ daemon process stopped
+
+In the example, we included a command-line argument in the program
+option. We can also provide options on the command line:
+
+ >>> open('conf', 'w').write(
+ ... '''
+ ... <runner>
+ ... program sleep
+ ... socket-name /tmp/demo.zdsock
+ ... </runner>
+ ... ''')
+
+ >>> system("./zdaemon -Cconf start 100")
+ . daemon process started, pid=1149
+
+ >>> system("./zdaemon -Cconf status")
+ program running; pid=1149
+
+ >>> system("./zdaemon -Cconf stop")
+ daemon process stopped
+
Property changes on: zdaemon/trunk/src/zdaemon/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zdaemon/trunk/src/zdaemon/component.xml
===================================================================
--- zdaemon/trunk/src/zdaemon/component.xml 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/src/zdaemon/component.xml 2006-12-21 23:46:14 UTC (rev 71643)
@@ -93,7 +93,7 @@
<key name="daemon" datatype="boolean"
required="no"
- default="false">
+ default="on">
<description>
Command-line option: -d or --daemon.
Added: zdaemon/trunk/src/zdaemon/tests/tests.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/tests.py 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/src/zdaemon/tests/tests.py 2006-12-21 23:46:14 UTC (rev 71643)
@@ -0,0 +1,87 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""XXX short summary goes here.
+
+$Id$
+"""
+
+import os, re, shutil, sys, tempfile, unittest
+import ZConfig, zdaemon
+from zope.testing import doctest, renormalizing
+
+try:
+ import pkg_resources
+except ImportError:
+ zdaemon_loc = os.path.dirname(os.path.dirname(zdaemon.__file__))
+ zconfig_loc = os.path.dirname(os.path.dirname(ZConfig.__file__))
+else:
+ zdaemon_loc = pkg_resources.working_set.find(
+ pkg_resources.Requirement.parse('zdaemon')).location
+ zconfig_loc = pkg_resources.working_set.find(
+ pkg_resources.Requirement.parse('ZConfig')).location
+
+def setUp(test):
+ test.globs['_td'] = td = []
+ here = os.getcwd()
+ td.append(lambda : os.chdir(here))
+ workspace = tempfile.mkdtemp()
+ td.append(lambda : shutil.rmtree(workspace))
+ os.chdir(workspace)
+ open('zdaemon', 'w').write(zdaemon_template % dict(
+ python = sys.executable,
+ zdaemon = zdaemon_loc,
+ ZConfig = zconfig_loc,
+ ))
+ os.chmod('zdaemon', 0755)
+ test.globs.update(dict(
+ system = system
+ ))
+
+def tearDown(test):
+ for f in test.globs['_td']:
+ f()
+
+def system(command, input=''):
+ i, o = os.popen4(command)
+ if input:
+ i.write(input)
+ i.close()
+ print o.read(),
+
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocFileSuite(
+ '../README.txt',
+ setUp=setUp, tearDown=tearDown,
+ checker=renormalizing.RENormalizing([
+ (re.compile('pid=\d+'), 'pid=NNN'),
+ ])
+ ),
+ ))
+
+
+zdaemon_template = """#!%(python)s
+
+import sys
+sys.path[0:0] = [
+ %(zdaemon)r,
+ %(ZConfig)r,
+ ]
+
+import zdaemon.zdctl
+
+if __name__ == '__main__':
+ zdaemon.zdctl.main()
+"""
Property changes on: zdaemon/trunk/src/zdaemon/tests/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: zdaemon/trunk/src/zdaemon/zdctl.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdctl.py 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/src/zdaemon/zdctl.py 2006-12-21 23:46:14 UTC (rev 71643)
@@ -76,7 +76,7 @@
class ZDCtlOptions(RunnerOptions):
- positional_args_allowed = 1
+ positional_args_allowed = True
def __init__(self):
RunnerOptions.__init__(self)
@@ -111,16 +111,6 @@
if not self.python:
self.python = sys.executable
- # Where's zdrun?
- if not self.zdrun:
- if __name__ == "__main__":
- file = sys.argv[0]
- else:
- file = __file__
- file = os.path.normpath(os.path.abspath(file))
- dir = os.path.dirname(file)
- self.zdrun = os.path.join(dir, "zdrun.py")
-
def set_schemafile(self, file):
self.schemafile = file
@@ -138,9 +128,10 @@
if m:
s = m.group(1)
args = eval(s, {"__builtins__": {}})
- if args != self.options.program:
+ program = self.options.program
+ if args[:len(program)] != program:
print "WARNING! zdrun is managing a different program!"
- print "our program =", self.options.program
+ print "our program =", program
print "daemon's args =", args
def emptyline(self):
@@ -175,22 +166,27 @@
self.zd_status = None
resp = self.send_action("status")
if not resp:
- return
+ return resp
m = re.search("(?m)^application=(\d+)$", resp)
if not m:
- return
+ return resp
self.zd_up = 1
self.zd_pid = int(m.group(1))
self.zd_status = resp
+ return resp
def awhile(self, cond, msg):
+ n = 0
try:
self.get_status()
while not cond():
sys.stdout.write(". ")
sys.stdout.flush()
time.sleep(1)
- self.get_status()
+ n += 1
+ if not self.get_status() and n > 10:
+ print "\nDaemon manager not running."
+ return
except KeyboardInterrupt:
print "^C"
else:
@@ -210,14 +206,14 @@
def do_start(self, arg):
self.get_status()
if not self.zd_up:
- args = [
- self.options.python,
- self.options.zdrun,
- ]
+ if self.options.zdrun:
+ args = [self.options.python, self.options.zdrun]
+ else:
+ args = [self.options.python, sys.argv[0], '--zdrun']
+
args += self._get_override("-S", "schemafile")
args += self._get_override("-C", "configfile")
args += self._get_override("-b", "backofflimit")
- args += self._get_override("-d", "daemon", flag=1)
args += self._get_override("-f", "forever", flag=1)
args += self._get_override("-s", "sockname")
args += self._get_override("-u", "user")
@@ -228,6 +224,7 @@
"-x", "exitcodes", ",".join(map(str, self.options.exitcodes)))
args += self._get_override("-z", "directory")
args.extend(self.options.program)
+ args.extend(self.options.args[1:])
if self.options.daemon:
flag = os.P_NOWAIT
else:
@@ -238,8 +235,9 @@
else:
print "daemon process already running; pid=%d" % self.zd_pid
return
- self.awhile(lambda: self.zd_pid,
- "daemon process started, pid=%(zd_pid)d")
+ if self.options.daemon:
+ self.awhile(lambda: self.zd_pid,
+ "daemon process started, pid=%(zd_pid)d")
def _get_override(self, opt, name, svalue=None, flag=0):
value = getattr(self.options, name)
@@ -486,10 +484,12 @@
if pid:
print "To run the program in the foreground, please stop it first."
return
- program = " ".join(self.options.program)
- print program
+
+ program = self.options.program + self.options.args[1:]
+ print " ".join(program)
+ sys.stdout.flush()
try:
- os.system(program)
+ os.spawnlp(os.P_WAIT, program[0], *program)
except KeyboardInterrupt:
print
@@ -580,6 +580,12 @@
return os.fstat(self.f.fileno())[stat.ST_SIZE]
def main(args=None, options=None, cmdclass=ZDCmd):
+ if args is None:
+ args = sys.argv[1:]
+ if args[0] == '--zdrun':
+ import zdaemon.zdrun
+ return zdaemon.zdrun.main(args[1:])
+
if options is None:
options = ZDCtlOptions()
options.realize(args)
Modified: zdaemon/trunk/src/zdaemon/zdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdoptions.py 2006-12-21 17:27:38 UTC (rev 71642)
+++ zdaemon/trunk/src/zdaemon/zdoptions.py 2006-12-21 23:46:14 UTC (rev 71643)
@@ -347,7 +347,7 @@
ZDOptions.__init__(self)
self.add("backofflimit", "runner.backoff_limit",
"b:", "backoff-limit=", int, default=10)
- self.add("daemon", "runner.daemon", "d", "daemon", flag=1, default=0)
+ self.add("daemon", "runner.daemon", "d", "daemon", flag=1, default=1)
self.add("forever", "runner.forever", "f", "forever",
flag=1, default=0)
self.add("sockname", "runner.socket_name", "s:", "socket-name=",
More information about the Zope-Checkins
mailing list