Jump to content
EduGeek EdSec 2026 is Go! 27th Oct in Derby! Join us for a day of EdTech security focused talks, networking, and an evening social ×

Recommended Posts

Posted

Hello All,

 

I have a small web server application I've written in Python that goes and gets some data from a database system and returns it to the user as XML. That part works fine - I can run the Python web server application from the command line and I can have clients connect to it and get data back. At the moment, to run the web server I have to be logged in to our server as the administrator user and I have to manually start the web server. I want to have the web server automatically start on system start as a service and run in the background.

 

Using code from ActiveState's site and StackOverflow, I have a pretty good idea of how to go about creating a service, and I think I've got that bit sorted - I can install and start my web server as a Windows service. I can't, however, figure out how to stop the service again. My web server is created from a BaseHTTPServer:

 

server = BaseHTTPServer.HTTPServer(('', 8081), SIMSAPIServerHandler)
server.serve_forever()

 

The serve_forever() call, naturally enough, makes the web server sit in an infinite loop and wait for HTTP connections (or a ctrl-break keypress, not useful for a service). I get the idea from the example code above that your main() function is supposed to sit in an infinite loop and only break out of it when it comes accross a "stop" condition. My main calls serve_forever(). I have a SvcStop function:

 

def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
exit(0)

 

Which seems to get called when I do "python myservice stop" from the command line (I can put a debug line in there that produces output to a file) but doesn't actually exit the whole service - subsequent calls to "python myservice start" gives me an error:

 

Error starting service: An instance of the service is already running.

 

and subsequent calls to stop gives me:

 

Error stopping service: The service cannot accept control messages at this time. (1061)

 

I think I need either some replacement for serve_forever (serve_until_stop_received, or whatever) or I need some way of modifying SvcStop so it stops the whole service.

 

Here's a full listing (I've trimmed includes/comments to save space):

 

    class SIMSAPIServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
   	def do_GET(self):
   		try:
   			reportTuple = self.path.partition("/")
   			if len(reportTuple) < 3:
   				return
   			if reportTuple[2] == "":
   				return
   			os.system("C:\\Programs\\SIMSAPI\\runCommandReporter.bat " + reportTuple[2])
   			f = open("C:\\Programs\\SIMSAPI\\out.xml", "rb")
   			self.send_response(200)
   			self.send_header('Content-type', "application/xml")
   			self.end_headers()
   			self.wfile.write(f.read())
   			f.close()
   			# The output from CommandReporter is simply dumped to out.xml, which we read, write to the user, then remove.
   			os.unlink("C:\\Programs\\SIMSAPI\\out.xml")
   			return
   		except IOError:
   			self.send_error(404,'File Not Found: %s' % self.path)
   			
   			
   			
   class SIMSAPI(win32serviceutil.ServiceFramework):
   	_svc_name_ = "SIMSAPI"
   	_svc_display_name_ = "A simple web server"
   	_svc_description_ = "Serves XML data produced by SIMS CommandReporter"
   	
   	def __init__(self, args):
   		win32serviceutil.ServiceFramework.__init__(self, args)
   		self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)           
   		
   	def SvcStop(self):
   			self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
   			exit(0)
   			
   	def SvcDoRun(self):
   		import servicemanager
   		servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 
   		
   		self.timeout = 3000
   		
   		while 1:
   			server = BaseHTTPServer.HTTPServer(('', 8081), SIMSAPIServerHandler)
   			server.serve_forever()
   			
   def ctrlHandler(ctrlType):
   	return True
                     
   if __name__ == '__main__':
   	win32api.SetConsoleCtrlHandler(ctrlHandler, True)
   	win32serviceutil.HandleCommandLine(SIMSAPI)

 

--

David Hicks

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...