[Zope-dev] Re: SVN: Zope/trunk/ Support for using zopectl on
Windows has been added.
Hanno Schlichting
plone at hannosch.info
Thu May 3 14:43:40 EDT 2007
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 @@
> + at set ZOPE_HOME=<<ZOPE_HOME>>
> + at set INSTANCE_HOME=<<INSTANCE_HOME>>
> + at set PYTHON=%ZOPE_HOME%\bin\python.exe
> + at set SOFTWARE_HOME=%ZOPE_HOME%\lib\python
> + at set CONFIG_FILE=%INSTANCE_HOME%\etc\zope.conf
> + at set PYTHONPATH=%SOFTWARE_HOME%
> + at set ZDCTL=%SOFTWARE_HOME%\Zope2\Startup\zopectl.py
> +"%PYTHON%" "%ZDCTL%" -C "%CONFIG_FILE%" %1 %2 %3 %4 %5 %6 %7
More information about the Zope-Dev
mailing list