#!/usr/bin/env python """ ThreadedAppServerService For general notes, see ThreadedAppServer.py. This version of the app server is a threaded app server that runs as a Windows NT Service. This means it can be started and stopped from the Control Panel or from the command line using "net start" and "net stop", and it can be configured in the Control Panel to auto-start when the machine boots. This requires the win32all package to have been installed. To see the options for installing, removing, starting, and stopping the service, just run this program with no arguments. Typical usage is to install the service to run under a particular user account and startup automatically on reboot with python ThreadedAppServerService.py --username mydomain\myusername --password mypassword --startup auto install Then, you can start the service from the Services applet in the Control Panel, where it will be listed as "WebKit Threaded Application Server". Or, from the command line, it can be started with either of the following commands: net start WebKit python ThreadedAppServerService.py start The service can be stopped from the Control Panel or with: net stop WebKit python ThreadedAppServerService.py stop And finally, to uninstall the service, stop it and then run: python ThreadedAppServerService.py remove FUTURE * This shares a lot of code with ThreadedAppServer.py -- instead it should inherit from ThreadedAppServer and have very little code of its own. * Have an option for sys.stdout and sys.stderr to go to a logfile instead of going nowhere. * Optional NT event log messages on start, stop, and errors. * Allow the option of installing multiple copies of WebKit with different configurations and different service names. * Figure out why I need the Python service hacks marked with ### below. * Allow it to work with wkMonitor, or some other fault tolerance mechanism. """ import time startTime = time.time() import win32serviceutil import win32service import os, sys, cStringIO class ThreadedAppServerService(win32serviceutil.ServiceFramework): _svc_name_ = 'WebKit' _svc_display_name_ = 'WebKit Threaded Application Server' def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.server = None # Fix the current working directory -- this gets initialized incorrectly # for some reason when run as an NT service. try: os.chdir(os.path.abspath(os.path.dirname(__file__))) except: pass def SvcStop(self): # Before we do anything, tell the SCM we are starting the stop process self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # And set running to 0 in the server. If it hasn't started yet, we'll # have to wait until it does. while self.server is None: time.sleep(1.0) self.server.initiateShutdown() def SvcDoRun(self): try: # Temporarily suck up stdout and stderr into a cStringIO stdoutAndStderr = cStringIO.StringIO() sys.stdout = sys.stderr = stdoutAndStderr # Import the ThreadedAppServer if '' not in sys.path: sys.path = [''] + sys.path os.chdir(os.pardir) from WebKit import Profiler Profiler.startTime = startTime from WebKit.ThreadedAppServer import ThreadedAppServer self.server = ThreadedAppServer(self.workDir()) # Now switch the output to the logfile specified in the appserver's config # setting "NTServiceLogFilename" if self.server.hasSetting('NTServiceLogFilename'): sys.stdout = sys.stderr = open(self.server.setting('NTServiceLogFilename'), 'a+') sys.stdout.write('-' * 68 + '\n') sys.stdout.write(stdoutAndStderr.getvalue()) else: # Make all output go nowhere. Otherwise, print statements cause # the service to crash, believe it or not. sys.stdout = sys.stderr = open('nul', 'w') del stdoutAndStderr self.server.mainloop() self.server._closeThread.join() except Exception, e: #Need to kill the Sweeper thread somehow print e print "Exiting AppServer" if 0: #See the traceback from an exception tb = sys.exc_info() print tb[0] print tb[1] import traceback traceback.print_tb(tb[2]) if self.server: self.server.running=0 self.server.shutDown() raise def workDir(self): return None if __name__=='__main__': win32serviceutil.HandleCommandLine(ThreadedAppServerService)