Re: SVN: Zope/trunk/ Support for using zopectl on Windows has been added.
Hi. I have just recently been given zope.org SVN write access and made my first bigger change - making zopectl work on Windows. Please review and test my changes. The change I made is based on code that I had in the plone.recipe.zope2instance buildout recipe and has seen quite some use by various developers, so should be reasonable stable. Hanno Hanno Schlichting wrote:
Log message for revision 75066: Support for using zopectl on Windows has been added. All commands are supported and there are two Windows specific ones: install and remove, which install or remove the Windows service. The start, stop and restart commands handle the Windows service.
Changed: U Zope/trunk/doc/CHANGES.txt U Zope/trunk/lib/python/Zope2/Startup/zopectl.py A Zope/trunk/skel/bin/zopectl.bat.in
-=- Modified: Zope/trunk/doc/CHANGES.txt =================================================================== --- Zope/trunk/doc/CHANGES.txt 2007-05-03 18:27:55 UTC (rev 75065) +++ Zope/trunk/doc/CHANGES.txt 2007-05-03 18:35:20 UTC (rev 75066) @@ -51,6 +51,12 @@
Features added
+ - Support for using zopectl on Windows has been added. All commands are + supported and there are two Windows specific ones: install and remove, + which install or remove the Windows service. The start, stop and + restart commands handle the Windows service. In order to use them, you + need to call 'bin\zopectl install' once. + - ZCatalog result objects (catalog brains) now have an interface, ZCatalog.interfaces.ICatalogBrain.
Modified: Zope/trunk/lib/python/Zope2/Startup/zopectl.py =================================================================== --- Zope/trunk/lib/python/Zope2/Startup/zopectl.py 2007-05-03 18:27:55 UTC (rev 75065) +++ Zope/trunk/lib/python/Zope2/Startup/zopectl.py 2007-05-03 18:35:20 UTC (rev 75066) @@ -48,6 +48,9 @@ from ZConfig.components.logger.handlers import FileHandlerFactory from ZConfig.datatypes import existing_dirpath
+WIN = False +if sys.platform[:3].lower() == "win": + WIN = True
def string_list(arg): return arg.split() @@ -127,6 +130,12 @@ self.python = sys.executable self.zdrun = os.path.join(os.path.dirname(zdaemon.__file__), "zdrun.py") + if WIN: + # Add the path to the zopeservice.py script, which is needed for + # some of the Windows specific commands + servicescript = os.path.join(self.directory, 'bin', 'zopeservice.py') + self.servicescript = '"%s" %s' % (self.python, servicescript) + self.exitcodes = [0, 2] if self.logfile is None and config.eventlog is not None: for handler in config.eventlog.handler_factories: @@ -158,11 +167,59 @@ args = [opt, svalue] return args
+ if WIN: + def get_status(self): + # get_status from zdaemon relies on *nix specific socket handling. + # We just don't support getting the status and sending actions to + # the control server on Windows. This could be extended to ask for + # the status of the Windows service though + self.zd_up = 0 + self.zd_pid = 0 + self.zd_status = None + return + + def do_stop(self, arg): + # Stop the Windows service + program = "%s stop" % self.options.servicescript + print program + os.system(program) + + def do_restart(self, arg): + # Restart the Windows service + program = "%s restart" % self.options.servicescript + print program + os.system(program) + + # Add extra commands to install and remove the Windows service + + def do_install(self, arg): + program = "%s install" % self.options.servicescript + print program + os.system(program) + + def help_install(self): + print "install -- Installs Zope as a Windows service." + + def do_remove(self, arg): + program = "%s remove" % self.options.servicescript + print program + os.system(program) + + def help_remove(self): + print "remove -- Removes the Zope Windows service." + def do_start(self, arg): # signal to Zope that it is being managed - #(to indicate it's web-restartable) + # (to indicate it's web-restartable) os.putenv('ZMANAGED', '1') - ZDCmd.do_start(self, arg) + if WIN: + # On Windows start the service, this fails with a reasonable + # error message as long as the service is not installed + program = "%s start" % self.options.servicescript + print program + os.system(program) + else: + ZDCmd.do_start(self, arg)
def get_startup_cmd(self, python, more): cmdline = ( '%s -c "from Zope2 import configure;' @@ -179,12 +236,17 @@ os.system(cmdline)
def do_foreground(self, arg): - self.options.program[1:1] = ["-X", "debug-mode=on"] - try: + if WIN: + # Adding arguments to the program is not supported on Windows + # and the runzope script doesn't put you in debug-mode either ZDCmd.do_foreground(self, arg) - finally: - self.options.program.remove("-X") - self.options.program.remove("debug-mode=on") + else: + 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" @@ -262,19 +324,23 @@ args.insert(0, self.options.python)
print 'Running tests via: %s' % ' '.join(args) - pid = os.fork() - if pid == 0: # child - os.execv(self.options.python, args) - - # Parent process running (execv replaces process in child - while True: - try: - os.waitpid(pid, 0) - except (OSError, KeyboardInterrupt): - continue - else: - break + if WIN: + # Windows process handling is quite different + os.system(' '.join(args)) + else: + pid = os.fork() + if pid == 0: # child + os.execv(self.options.python, args)
+ # Parent process running (execv replaces process in child + while True: + try: + os.waitpid(pid, 0) + except (OSError, KeyboardInterrupt): + continue + else: + break + def help_test(self): print "test [args]+ -- run unit / functional tests." print " See $ZOPE_HOME/bin/test.py --help for syntax." @@ -317,7 +383,8 @@ # If it is not reset, 'os.wait[pid]' can non-deterministically fail. # Thus, use a way such that "SIGCHLD" is definitely reset in children. #signal.signal(signal.SIGCHLD, signal.SIG_IGN) - if os.uname()[0] != 'Darwin': + if not WIN and os.uname()[0] != 'Darwin': + # On Windows the os.uname method does not exist. # On Mac OS X, setting up a signal handler causes waitpid to # raise EINTR, which is not preventable via the Python signal # handler API and can't be dealt with properly as we can't pass
Copied: Zope/trunk/skel/bin/zopectl.bat.in (from rev 75039, Zope/trunk/skel/bin/runzope.bat.in) =================================================================== --- Zope/trunk/skel/bin/runzope.bat.in 2007-05-03 07:18:30 UTC (rev 75039) +++ Zope/trunk/skel/bin/zopectl.bat.in 2007-05-03 18:35:20 UTC (rev 75066) @@ -0,0 +1,8 @@ +@set ZOPE_HOME=<<ZOPE_HOME>> +@set INSTANCE_HOME=<<INSTANCE_HOME>> +@set PYTHON=%ZOPE_HOME%\bin\python.exe +@set SOFTWARE_HOME=%ZOPE_HOME%\lib\python +@set CONFIG_FILE=%INSTANCE_HOME%\etc\zope.conf +@set PYTHONPATH=%SOFTWARE_HOME% +@set ZDCTL=%SOFTWARE_HOME%\Zope2\Startup\zopectl.py +"%PYTHON%" "%ZDCTL%" -C "%CONFIG_FILE%" %1 %2 %3 %4 %5 %6 %7
--On 3. Mai 2007 20:43:40 +0200 Hanno Schlichting <plone@hannosch.info> wrote:
Hi.
I have just recently been given zope.org SVN write access and made my first bigger change - making zopectl work on Windows.
Although I don't care much about Windows, great job! Thanks! Andreas
Hanno Schlichting wrote:
Hi.
I have just recently been given zope.org SVN write access and made my first bigger change - making zopectl work on Windows. Please review and test my changes. The change I made is based on code that I had in the plone.recipe.zope2instance buildout recipe and has seen quite some use by various developers, so should be reasonable stable.
Cool, I've been waiting for this for about 5 years ;-) Shame start and stop require Zope to be a service, does each Zope instance become a seperate service? Are there any problems with having lots of zope instances running as services on the same box? Do zopectl debug and zopectl test work? Which version of Zope will this land in? Or, and where are the tests? <0.8 wink>) cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Hi. Chris Withers wrote:
Hanno Schlichting wrote:
I have just recently been given zope.org SVN write access and made my first bigger change - making zopectl work on Windows. Please review and test my changes. The change I made is based on code that I had in the plone.recipe.zope2instance buildout recipe and has seen quite some use by various developers, so should be reasonable stable.
Cool, I've been waiting for this for about 5 years ;-)
I needed it three years ago and have finally found the time to write this, though I'm not developing on Windows anymore ;)
Shame start and stop require Zope to be a service, does each Zope instance become a seperate service? Are there any problems with having lots of zope instances running as services on the same box?
I think start/stop requiring a service is the only sane thing you can do on Windows, without rewriting the whole service concept - automatic starts at boot time, easy restarting, running as a separate user... Running multiple Zope instances on the same box has no problems I heard of so far or have been witnessing. Obviously they need to listen on their own distinct ports.
Do zopectl debug and zopectl test work?
Yes, as far as my testing suggests.
Which version of Zope will this land in?
I consider this a non-trivial change that changes a crucial part (a broken zopectl in a minor release would heart us) so I only committed it to the current trunk which will become Zope 2.11 one day I suppose.
Or, and where are the tests? <0.8 wink>)
There aren't any for zopectl at all, so I haven't tried to come up with a way to write them specifically for Windows. My main problem here is, that I cannot think of any sane way to test starting a real Zope instance in a test environment. If somebody has ideas how to approach this, feel free to tell me ;) Hanno
participants (3)
-
Andreas Jung -
Chris Withers -
Hanno Schlichting