2017-07-28 4 views
0

次のリンクに記載されている解決策を実行して、実行中の日数後に停止しようとするとSTOPPING状態でハングしないWindowsサービスを作成します。PythonでのWindowsサービス

Timeout and Windows Services for Long Running Processes (Python)

私が直面しています問題は、私は一度だけ実行するように思わサービスとWindowsサービスマネージャでサービスを開始した後にすべてのタスクが私はそれを停止または再起動することはできません無効にしているということです。以下は私のコードです。実行したい実際のタスクをすべて削除し、実行するたびに変数(x)に1を加えてログファイルに書き込むダミー​​サービスで置き換えます。

私は自分の間違いがどこにあるのかを見つけようとしています。

# -*- coding: utf-8 -*- 
""" 
Created on Thu Jul 27 09:07:29 2017 

@author:aaaa 
""" 

import threading 
import logging 
import logging.config 
import win32api 
import win32serviceutil 
import win32event 


class InterruptedException(Exception): 
    pass 

class WorkerThread(threading.Thread): 
    def __init__(self, controller): 
     self._controller = controller 
     self._stop = threading.Event() 
     super(WorkerThread, self).__init__() 

     self.x=0 

     #------------------------------------------------------------------------------ 
     # Creating logger 
     #------------------------------------------------------------------------------ 
     logging.config.fileConfig(r'c:\temp\teste_logging.conf') 
     # create logger 
     self.logger = logging.getLogger('teste') 
     self.logger.debug("Serviço criado") 

    def stop(self): 
     self._stop.set() 

    def stopped(self): 
     return self._stop.isSet() 

    def run(self): 
     try: 
      # Insert the code you want to run as a service here 
      # rather than do "execfile(.../.../blah)" simply do: 
      # You can have your code throw InterruptedException if your code needs to exit 
      # Also check often if self.stopped and then cleanly exit 
      self.x+=1 
      self.logger.debug('x = {}'.format(self.x)) 

     except InterruptedException as e: 
      # We are forcefully quitting 
      self.logger.debug('Interruption Exception - {}'.format(str(e))) 
      pass 
     except Exception as e: 
      self.logger.debug('Unexpected Error - {}'.format(str(e))) 
      pass 
      # Oh oh, did not anticipate this, better report to Windows or log it 
     finally: 
      # Close/release any connections, handles, files etc. 
      # OK, we can stop now 
      win32event.SetEvent(self._controller) 

class test_service(win32serviceutil.ServiceFramework): 

    _svc_name_ = "pyTEST" 
    _svc_display_name_ = "TEST Event service" 
    _svc_description_ = "Service to teste python service" 

    def __init__(self, args): 
     win32serviceutil.ServiceFramework.__init__(self, args) 
     self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)  
     self.hWaitDone = win32event.CreateEvent(None, 0, 0, None) 

     #logger 
     self.logger=logging.getLogger('teste.SERVICE') 

     #create worker 
     self.worker = WorkerThread(self.hWaitDone) 

    def SvcDoRun(self): 
     import servicemanager  
     servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, 
           servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 

     #worker = WorkerThread(self.hWaitDone,self.dCONFIG) 
     self.worker.start() 

     while True: 
      # Wait for service stop signal 
      rc = win32event.WaitForMultipleObjects([self.hWaitStop, self.hWaitDone],win32event.INFINITE,60000) 

      # Check to see if self.hWaitStop happened as part of Windows Service Management 
      if rc == 0: 
       # Stop signal encountered 
       servicemanager.LogInfoMsg(self._svc_name_ + " - STOPPED!") #For Event Log 
       break 

      if rc == 1: 
       # Wait until worker has fully finished 
       self.worker.join() 

       # Determine from worker state if we need to start again (because run finished) 
       # Or do whatever 
       if not self.worker.need_to_start_again(): 
        break 

       self.worker.start() 

def ctrlHandler(ctrlType): 
    return True 

if __name__ == '__main__': 
    win32api.SetConsoleCtrlHandler(ctrlHandler, True) 
    win32serviceutil.HandleCommandLine(test_service) 

ここでは、ロギングモジュールの構成を示します。テキストファイルに保存してteste_logging.confとして保存してください。

[loggers] 
keys=root,teste 

[handlers] 
keys=logfile,consoleHandler 

[formatters] 
keys=simpleFormatter,logfileformatter 

[logger_root] 
level=DEBUG 
handlers=consoleHandler 

[logger_teste] 
level=DEBUG 
handlers=logfile 
qualname=teste 
propagate=0 

[formatter_logfileformatter] 
format=%(asctime)s %(name)-12s: %(levelname)s %(message)s 

[formatter_simpleFormatter] 
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 
datefmt= 

[handler_consoleHandler] 
class=StreamHandler 
level=DEBUG 
formatter=simpleFormatter 
args=(sys.stdout,) 

[handler_logfile] 
class=handlers.RotatingFileHandler 
level=DEBUG 
args=(r'C:\temp\pyteste.log','a',5000000,20) 
formatter=logfileformatter 
+0

WaitForMultipleObjectsの2番目のパラメータは、すべてのオブジェクトを待機する必要があるかどうかを判断するブール値です。誤ってこの引数に 'INFINITE'(-1)を渡しています。これは真の値なので、waitは常に両方のイベントが設定されていなければ' WAIT_TIMEOUT'(258)を返します。 – eryksun

+0

しかし、これはrc = win32event.WaitForSingleObject(self.hWaitStop、10000)を使用した場合にも発生します。 – Dariva

+0

タイムアウトを提供しています。タイムアウトが必要ない場合は、 'win32event.WaitForMultipleObjects([self.hWaitStop、self.hWaitDone]、False、win32event.INFINITE)'を使用してください。 – eryksun

答えて

0

サービスタスクが無効になった理由が見つかりました。私はSvcStop機能を実装するのを忘れていました。

def SvcStop(self): 
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 
    win32event.SetEvent(self.hWaitStop)  

それでも1回だけ実行されます。

+0

私は、問題はrc(win32event.WaitForMultipleObject)が値258を戻していることに気付きました。誰もがこの意味を知っていますか? – Dariva

+0

'net helpmsg 258':待機操作がタイムアウトしました。 –

+0

...と私はエリクソンがすでにそれが起こっている理由を説明して参照してください。 –

関連する問題