# vim: et sw=4 ts=8 sts from wxPython.wx import * import sys, os, time import pywintypes import win32serviceutil import win32service import win32event import win32process
ID_ABOUT = 101 ID_EXIT = 102 # the max seconds we're allowed to spend backing off BACKOFF_MAX = 300 # if the process runs successfully for more than BACKOFF_CLEAR_TIME # seconds, we reset the backoff stats to their initial values BACKOFF_CLEAR_TIME = 30 # the initial backoff interval (the amount of time we wait to restart # a dead process) BACKOFF_INITIAL_INTERVAL = 5 class Service(win32serviceutil.ServiceFramework): """ A class representing a Windows NT service that can manage an instance-home-based Zope/ZEO/ZRS processes """ # The comment below is mostly irrelevant if you're running a standalone # SchoolBell server, I think. -TEH # The PythonService model requires that an actual on-disk class declaration # represent a single service. Thus, the below definition of start_cmd, # must be overridden in a subclass in a file within the instance home for # each instance. The below-defined start_cmd (and _svc_display_name_ # and _svc_name_) are just examples. # To use this script with SchoolTool, just replace "SchoolBell" # with "SchoolTool" in the variables below. # You'll also need to change 'Python24' to 'Python23' if that's # what you've got. -TEH #cmd_str = os.environ["moin_service"] #_svc_name_ = r'moin_service' #_svc_display_name_ = r'moin_service' #start_cmd = r"c:\mmde\moin.exe" info = ['', '', ''] def __init__(self): self._svc_name = info[0] self._svc_display_name_ = info[1] self.start_cmd = info[2] win32serviceutil.ServiceFramework.__init__(self) # Create an event which we will use to wait on. # The "service stop" request will set this event. self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.redirectOutput() def __init__(self, args): self._svc_name = info[0] self._svc_display_name_ = info[1] self.start_cmd = info[2] win32serviceutil.ServiceFramework.__init__(self, args) # Create an event which we will use to wait on. # The "service stop" request will set this event. self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.redirectOutput() def redirectOutput(self): #pass sys.stdout.close() sys.stderr.close() sys.stdout = NullOutput() sys.stderr = NullOutput() def SvcStop(self): # Before we do anything, tell the SCM we are starting the stop process. self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # TODO: This TerminateProcess call doesn't make much sense: it's # doing a hard kill _first_, never giving the process a chance to # shut down cleanly. Compare to current Zope2 service code, which # uses Windows events to give the process a chance to shut down # cleanly, doing a hard kill only if that doesn't succeed. # stop the process if necessary try: win32process.TerminateProcess(self.hZope, 0) except pywintypes.error: # the process may already have been terminated pass # And set my event. win32event.SetEvent(self.hWaitStop) # SvcStop only gets triggered when the user explictly stops (or restarts) # the service. To shut the service down cleanly when Windows is shutting # down, we also need to hook SvcShutdown. SvcShutdown = SvcStop def createProcess(self, cmd): return win32process.CreateProcess( None, cmd, None, None, 0, 0, None, None, win32process.STARTUPINFO()) def SvcDoRun(self): # indicate to Zope that the process is daemon managed (restartable) # os.environ['ZMANAGED'] = '1' # daemon behavior: we want to to restart the process if it # dies, but if it dies too many times, we need to give up. # we use a simple backoff algorithm to determine whether # we should try to restart a dead process: for each # time the process dies unexpectedly, we wait some number of # seconds to restart it, as determined by the backoff interval, # which doubles each time the process dies. if we exceed # BACKOFF_MAX seconds in cumulative backoff time, we give up. # at any time if we successfully run the process for more thab # BACKOFF_CLEAR_TIME seconds, the backoff stats are reset. # the initial number of seconds between process start attempts backoff_interval = BACKOFF_INITIAL_INTERVAL # the cumulative backoff seconds counter backoff_cumulative = 0 import servicemanager # log a service started message servicemanager.LogMsg( servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, ' (%s)' % self._svc_display_name_)) while 1: start_time = time.time() info = self.createProcess(self.start_cmd) self.hZope = info[0] # the pid if backoff_interval > BACKOFF_INITIAL_INTERVAL: # if we're in a backoff state, log a message about # starting a new process servicemanager.LogInfoMsg( '%s (%s): recovering from died process, new process ' 'started' % (self._svc_name_, self._svc_display_name_) ) rc = win32event.WaitForMultipleObjects( (self.hWaitStop, self.hZope), 0, win32event.INFINITE) if rc == win32event.WAIT_OBJECT_0: # user sent a stop service request self.SvcStop() break else: # user did not send a service stop request, but # the process died; this may be an error condition status = win32process.GetExitCodeProcess(self.hZope) if status == 0: # the user shut the process down from the web # interface (or it otherwise exited cleanly) break else: # this was an abormal shutdown. if we can, we want to # restart the process but if it seems hopeless, # don't restart an infinite number of times. if backoff_cumulative > BACKOFF_MAX: # it's hopeless servicemanager.LogErrorMsg( '%s (%s): process could not be restarted due to max ' 'restart attempts exceeded' % ( self._svc_display_name_, self._svc_name_ )) self.SvcStop() break servicemanager.LogWarningMsg( '%s (%s): process died unexpectedly. Will attempt ' 'restart after %s seconds.' % ( self._svc_name_, self._svc_display_name_, backoff_interval ) ) # if BACKOFF_CLEAR_TIME seconds have elapsed since we last # started the process, reset the backoff interval # and the cumulative backoff time to their original # states if time.time() - start_time > BACKOFF_CLEAR_TIME: backoff_interval = BACKOFF_INITIAL_INTERVAL backoff_cumulative = 0 # we sleep for the backoff interval. since this is async # code, it would be better done by sending and # catching a timed event (a service # stop request will need to wait for us to stop sleeping), # but this works well enough for me. time.sleep(backoff_interval) # update backoff_cumulative with the time we spent # backing off. backoff_cumulative = backoff_cumulative + backoff_interval # bump the backoff interval up by 2* the last interval backoff_interval = backoff_interval * 2 # loop and try to restart the process # log a service stopped message servicemanager.LogMsg( servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED, (self._svc_name_, ' (%s) ' % self._svc_display_name_)) class NullOutput: """A stdout / stderr replacement that discards everything.""" def noop(self, *args, **kw): pass write = writelines = close = seek = flush = truncate = noop def __iter__(self): return self def next(self): raise StopIteration def isatty(self): return False def tell(self): return 0 def read(self, *args, **kw): return '' readline = read def readlines(self, *args, **kw): return [] class MyFrame(wxFrame): def __init__(self, parent, ID, title): wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(200, 150)) self.CreateStatusBar() self.SetStatusText("This is the statusbar") menu = wxMenu() menu.Append(ID_ABOUT, "&About", "More information about this program") menu.AppendSeparator() menu.Append(ID_EXIT, "E&xit", "Terminate the program") menuBar = wxMenuBar() menuBar.Append(menu, "&File"); self.SetMenuBar(menuBar) # 서비스명 servicenameText = wxStaticText(self, -1, "Service Name") self.servicenameCtrl = wxTextCtrl(self, -1, size=(200, -1)) # 서비스로 실행할 명령 cmdText = wxStaticText(self, -1, "Service command") self.cmdCtrl = wxTextCtrl(self, -1, size=(200, -1)) # 실행 버튼 installButton = wxButton(self, -1, label="Install", size=(80, -1)) removeButton = wxButton(self, -1, label="Remove", size=(80, -1)) startButton = wxButton(self, -1, label="Start", size=(80, -1)) stopButton = wxButton(self, -1, label="Stop", size=(80, -1)) installButton.Bind(EVT_BUTTON, self.onInstallButtonClick) removeButton.Bind(EVT_BUTTON, self.onRemoveButtonClick) startButton.Bind(EVT_BUTTON, self.onStartButtonClick) stopButton.Bind(EVT_BUTTON, self.onStopButtonClick) # Sizer 구성 sizer = wxFlexGridSizer(rows=2, cols=2, hgap=10, vgap=5) sizer.Add(servicenameText) # (0, 0) sizer.Add(self.servicenameCtrl) # (0, 1) sizer.Add(cmdText) # (1, 0) sizer.Add(self.cmdCtrl) # (1, 1) sizer.Add(installButton) # (2, 0) sizer.Add(removeButton) # (2, 1) sizer.Add(startButton) # (3, 0) sizer.Add(stopButton) # (3, 1) border = wxBoxSizer() border.Add(sizer, 0, wxALL, 10) self.SetSizerAndFit(border) self.Fit() def onInstallButtonClick(self, event): Service.info[0] = self.servicenameCtrl.GetValue() Service.info[1] = self.servicenameCtrl.GetValue() Service.info[2] = self.cmdCtrl.GetValue() #Service._svc_name_ = self.servicenameCtrl.GetValue() #Service._svc_display_name_ = self.servicenameCtrl.GetValue() #Service.start_cmd = self.cmdCtrl.GetValue() #win32serviceutil.HandleCommandLine(Service) win32serviceutil.InstallService( win32serviceutil.GetServiceClassString(Service), self.servicenameCtrl.GetValue(), self.servicenameCtrl.GetValue() ) def onRemoveButtonClick(self, event): win32serviceutil.RemoveService(self.servicenameCtrl.GetValue()) def onStartButtonClick(self, event): win32serviceutil.StartService(self.servicenameCtrl.GetValue()) def onStopButtonClick(self, event): win32serviceutil.StopService(self.servicenameCtrl.GetValue()) #def onOkButtonClick(self, event): # Service._svc_name_ = self.servicenameCtrl.GetValue() # Service._svc_display_name_ = self.servicenameCtrl.GetValue() # Service.start_cmd = (self.cmdCtrl.GetValue()) # sys.argv.append(self.argsCtrl.GetValue()) # win32serviceutil.HandleCommandLine(Service) class MyApp(wxApp): def OnInit(self): frame = MyFrame(NULL, -1, "Hello from wxPython") frame.servicenameCtrl.SetValue(r"moin_service") frame.cmdCtrl.SetValue(r"c:\mmde\moin.exe") #frame.argsCtrl.SetValue("stop") Service.info[0] = frame.servicenameCtrl.SetValue(r"moin_service") Service.info[1] = frame.servicenameCtrl.SetValue(r"moin_service") Service.info[2] = frame.cmdCtrl.SetValue(r"c:\mmde\moin.exe") frame.Show(true) self.SetTopWindow(frame) return true if __name__ == '__main__': app = MyApp(0) app.MainLoop() ---------------------------- start stop remove ==> ok I cann't install service help!!! -- http://mail.python.org/mailman/listinfo/python-list