问题
Below is the framework for the windows service that I am running. In the event of an error, the error is logged and can be viewed in the event viewer. The problem is that the script just quits and does not restart again even though I have the recovery set to restart the service on the first, second and subsequent failures. Currently I have little error handling because I want to see what errors that may arise in the event viewer so that I can write code to handle these errors accordingly.
from win32api import CloseHandle, GetLastError, SetConsoleCtrlHandler
import os
import sys
import time
import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
class AppServerSvc (win32serviceutil.ServiceFramework):
_svc_name_ = "my_service_name"
_svc_display_name_ = "my service"
def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
SetConsoleCtrlHandler(lambda x: True, True)
self.hWaitStop = win32event.CreateEvent(None,0,0,None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.run = False
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.run = True
self.main()
def main(self):
while self.run == True
pass
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
Edit:
I tried to try: except around self.main but the outcome was still the same. The service did not restart when it crashed... Please anyone out there with any ideas? A service is not all that useful if it cannot restart in the event of a crash... Might as well run it as a .pyc
Edit:
below is an example of an error that may arise within my script... I don't believe this error message is particularly useful because what I am try to achieve is to have the service restart but none the less here is an example of an error that has crashed my service without it restarting:
The instance's SvcRun() method failed
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\win32\lib\win32serviceutil.py", line 806, in SvcRun
self.SvcDoRun()
File "C:\Some_Service.py", line 46, in SvcDoRun
self.main()
File "Some_Service.py", line 61, in main
ser = self.open_serial_port()
File "Some_Service.py", line 70, in open_serial_port
serial_connection.open()
File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 56, in open
raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))
SerialException: could not open port COM6: [Error 1225] The remote system refused the network connection.
%2: %3
回答1:
Below is a service that just divides by zero to raise an error. If there is an error, an event is sent and the service exits using os._exit(-1)
. The value has to be anything but 0 so that the windows knows that the service didn't exit nicely.
from win32api import CloseHandle, GetLastError, SetConsoleCtrlHandler
import os
import sys
import time
import win32serviceutil
import win32service
import win32event
import servicemanager
import traceback
class AppServerSvc (win32serviceutil.ServiceFramework):
_svc_name_ = "test"
_svc_display_name_ = "test"
def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
SetConsoleCtrlHandler(lambda x: True, True)
self.hWaitStop = win32event.CreateEvent(None,0,0,None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.run = False
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.run = True
try: # try main
self.main()
except:
servicemanager.LogErrorMsg(traceback.format_exc()) # if error print it to event log
os._exit(-1)#return some value other than 0 to os so that service knows to restart
def main(self):
while self.run == True:
time.sleep(30)
t = 1/0
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
回答2:
My suspicion is that your service is not in fact crashing, but completing before it has a chance to run. Have you tried inserting a sleep statement of a few seconds in the main
function?
回答3:
Why don't you use a try-except for it ?
class AppServerSvc (win32serviceutil.ServiceFramework):
_svc_name_ = "my_service_name"
_svc_display_name_ = "my service"
def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
SetConsoleCtrlHandler(lambda x: True, True)
self.hWaitStop = win32event.CreateEvent(None,0,0,None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.run = False
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.run = True
self.main()
def main(self):
while self.run == True
try :
<your code>
except :
time.sleep(3)
<may be an error log here>
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
来源:https://stackoverflow.com/questions/5315193/how-to-keep-a-windows-service-running