[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