2011-12-07 10 views
7

WindowsサービスとしてXML-RPCサーバーを作成しようとしています。
XML-RPCサーバーはFTPなどのファイルを取得して置くことができ、
はリモートクライアント
が送信するos.system()によってコマンドを実行します。WindowsサービスとしてのPython XML-RPCサーバー

私はWindowsサービスでサーバーをカプセル化しようとしています
イベントループ。

サービスの作成時に問題はありません。

python.exe remoteServer.py --startup=auto install 
Installing service XMLRPCServerService 
Service installed 

サービス開始時に問題ありません。

python.exe remoteServer.py start 
Starting service XMLRPCServerService 

サービスを停止するときに問題はありません。

python.exe remoteServer.py stop 
Stopping service XMLRPCServerService 

サービスを再開するときに問題があります。プロセスモニタを見てみると

python.exe remoteServer.py start 
Starting service XMLRPCServerService 
Error starting service: An instance of the service is already running. 

、私は
がまだ実行されているプロセス「pythonservice.exe」を参照してください。ここで

はremoteServer.pyの内容は以下のとおりです。

#!/bin/python 

# $Revision: 1.7 $ 
# $Author: dot $ 
# $Date: 2011/12/07 01:16:13 $ 

LISTEN_HOST='0.0.0.0' 
LISTEN_PORT=8000 

import os 
import SocketServer 
import BaseHTTPServer 
import SimpleHTTPServer 
import xmlrpclib 
import SimpleXMLRPCServer 
import socket 
import httplib 
import inspect 
import win32service 
import win32serviceutil 
import win32api 
import win32con 
import win32event 
import win32evtlogutil 

class XMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher): 
    def __init__(self, server_address, HandlerClass, logRequests=True): 
     """ XML-RPC server. """ 
     self.logRequests = logRequests 

     SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,False,None) 
     SocketServer.BaseServer.__init__(self, server_address, HandlerClass) 

     self.socket = socket.socket(
       socket.AF_INET, socket.SOCK_STREAM) 

     self.server_bind() 
     self.server_activate() 

class XMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): 
    """ XML-RPC request handler class. """ 
    def setup(self): 
     self.connection = self.request 
     self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) 
     self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) 

    def do_POST(self): 
     """ Handles the HTTPS request. 
      It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. 
     """ 

     try: 
      # get arguments 
      data = self.rfile.read(int(self.headers["content-length"])) 
      # In previous versions of SimpleXMLRPCServer, _dispatch 
      # could be overridden in this class, instead of in 
      # SimpleXMLRPCDispatcher. To maintain backwards compatibility, 
      # check to see if a subclass implements _dispatch and dispatch 
      # using that method if present. 
      response = self.server._marshaled_dispatch(
        data, getattr(self, '_dispatch', None) 
       ) 
     except: 
      # This should only happen if the module is buggy 
      # internal error, report as HTTP server error 
      self.send_response(500) 
      self.end_headers() 
     else: 
      # got a valid XML RPC response 
      self.send_response(200) 
      self.send_header("Content-type", "text/xml") 
      self.send_header("Content-length", str(len(response))) 
      self.end_headers() 
      self.wfile.write(response) 

      # shut down the connection 
      self.wfile.flush() 
      self.connection.shutdown() # Modified here! 

def XMLRPCServerGet(HandlerClass = XMLRPCRequestHandler,ServerClass = XMLRPCServer): 
    """Test xml rpc over http server""" 
    class xmlrpc_registers: 
     def _listMethods(self): 
      return list_public_methods(self) 

     def _methodHelp(self, method): 
      f = getattr(self, method) 
      return inspect.getdoc(f) 

     def list(self, dir_name): 
      """list(dir_name) => [<filenames>] 

      Returns a list containing the contents of the named directory. 
      """ 
      return os.listdir(dir_name) 

     def put(self,filename,filedata): 
      try: 
       with open(filename, "wb") as handle: 
        handle.write(filedata.data) 
        handle.close() 
       return True 
      except Exception,ex: 
       return 'error' 

     def get(self,filepath): 
      try: 
       handle = open(filepath) 
       return xmlrpclib.Binary(handle.read()) 
       handle.close() 
      except: 
       return 'error' 

     def system(self, command): 
      result = os.system(command) 
      return result 

    server_address = (LISTEN_HOST, LISTEN_PORT) # (address, port) 
    server = ServerClass(server_address, HandlerClass)  
    server.register_introspection_functions() 
    server.register_instance(xmlrpc_registers())  
    #sa = server.socket.getsockname() 
    return server 
    #server.serve_forever() 
    #print "Serving HTTP on", sa[0], "port", sa[1] 
    #try: 
    # #print 'Use Control-C to exit' 
    # server.serve_forever() 
    #except KeyboardInterrupt: 
    # #print 'Exiting' 

class XMLRPCServerService(win32serviceutil.ServiceFramework): 
    _svc_name_   = "XMLRPCServerService" 
    _svc_display_name_ = "XMLRPCServerService" 
    _svc_description_ = "Tests Python service framework by receiving and echoing messages over a named pipe" 

    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) 
     win32event.SetEvent(self.hWaitStop)      

    def SvcDoRun(self): 
     import servicemanager  
     servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 
     self.timeout = 100 
     server = XMLRPCServerGet() 
     #server.serve_forever() 

     while 1: 
      # Wait for service stop signal, if I timeout, loop again 
      rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) 
      # Check to see if self.hWaitStop happened 
      if rc == win32event.WAIT_OBJECT_0: 
       # Stop signal encountered 
       server.shutdown() 
       servicemanager.LogInfoMsg("XMLRPCServerService - STOPPED") 
       break 
      else: 
       server.handle_request() 
       servicemanager.LogInfoMsg("XMLRPCServerService - is alive and well") 

def ctrlHandler(ctrlType): 
    return True 

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

これが問題の根源かどうかはわかりませんが、SvcStopメソッドの最後に 'self.ReportServiceStatus(win32service.SERVICE_STOPPED) 'の呼び出しが見つからないようです。 –

+0

@David K. Hessあなたは絶対に正しいです!それは目に見えて隠れていた! –

+1

ありがとう!私は先に進み、それを答えとして加えました。 –

答えて

5

あなたがへの呼び出しが欠落しているように見えますself.ReportServiceStatus(win32service.SERVICE_STOPPED)をSvcStopメソッドの最後に追加します。

2

デイヴィッドK.ヘスはこのための信用に値します。
彼は私がSvcStop defで、クラスXMLRPCServerServiceにライン142の後に以下を追加提案:ここ

 self.ReportServiceStatus(win32service.SERVICE_STOPPED) 

が興味を持つ人のための最終的なバージョンです:

#!/bin/python 

# $Revision: 1.7 $ 
# $Author: dot $ 
# $Date: 2011/12/07 01:16:13 $ 

LISTEN_HOST='0.0.0.0' 
LISTEN_PORT=8000 

import os 
import SocketServer 
import BaseHTTPServer 
import SimpleHTTPServer 
import xmlrpclib 
import SimpleXMLRPCServer 
import socket 
import httplib 
import inspect 
import win32service 
import win32serviceutil 
import win32api 
import win32con 
import win32event 
import win32evtlogutil 

class XMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher): 
    def __init__(self, server_address, HandlerClass, logRequests=True): 
     """ XML-RPC server. """ 
     self.logRequests = logRequests 

     SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,False,None) 
     SocketServer.BaseServer.__init__(self, server_address, HandlerClass) 

     self.socket = socket.socket(
       socket.AF_INET, socket.SOCK_STREAM) 

     self.server_bind() 
     self.server_activate() 

class XMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): 
    """ XML-RPC request handler class. """ 
    def setup(self): 
     self.connection = self.request 
     self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) 
     self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) 

    def do_POST(self): 
     """ Handles the HTTPS request. 
      It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. 
     """ 

     try: 
      # get arguments 
      data = self.rfile.read(int(self.headers["content-length"])) 
      # In previous versions of SimpleXMLRPCServer, _dispatch 
      # could be overridden in this class, instead of in 
      # SimpleXMLRPCDispatcher. To maintain backwards compatibility, 
      # check to see if a subclass implements _dispatch and dispatch 
      # using that method if present. 
      response = self.server._marshaled_dispatch(
        data, getattr(self, '_dispatch', None) 
       ) 
     except: 
      # This should only happen if the module is buggy 
      # internal error, report as HTTP server error 
      self.send_response(500) 
      self.end_headers() 
     else: 
      # got a valid XML RPC response 
      self.send_response(200) 
      self.send_header("Content-type", "text/xml") 
      self.send_header("Content-length", str(len(response))) 
      self.end_headers() 
      self.wfile.write(response) 

      # shut down the connection 
      self.wfile.flush() 
      self.connection.shutdown() # Modified here! 

def XMLRPCServerGet(HandlerClass = XMLRPCRequestHandler,ServerClass = XMLRPCServer): 
    """Test xml rpc over http server""" 
    class xmlrpc_registers: 
     def _listMethods(self): 
      return list_public_methods(self) 

     def _methodHelp(self, method): 
      f = getattr(self, method) 
      return inspect.getdoc(f) 

     def list(self, dir_name): 
      """list(dir_name) => [<filenames>] 

      Returns a list containing the contents of the named directory. 
      """ 
      return os.listdir(dir_name) 

     def put(self,filename,filedata): 
      try: 
       with open(filename, "wb") as handle: 
        handle.write(filedata.data) 
        handle.close() 
       return True 
      except Exception,ex: 
       return 'error' 

     def get(self,filepath): 
      try: 
       handle = open(filepath) 
       return xmlrpclib.Binary(handle.read()) 
       handle.close() 
      except: 
       return 'error' 

     def system(self, command): 
      result = os.system(command) 
      return result 

    server_address = (LISTEN_HOST, LISTEN_PORT) # (address, port) 
    server = ServerClass(server_address, HandlerClass)  
    server.register_introspection_functions() 
    server.register_instance(xmlrpc_registers())  
    #sa = server.socket.getsockname() 
    return server 
    #server.serve_forever() 
    #print "Serving HTTP on", sa[0], "port", sa[1] 
    #try: 
    # #print 'Use Control-C to exit' 
    # server.serve_forever() 
    #except KeyboardInterrupt: 
    # #print 'Exiting' 

class XMLRPCServerService(win32serviceutil.ServiceFramework): 
    _svc_name_   = "XMLRPCServerService" 
    _svc_display_name_ = "XMLRPCServerService" 
    _svc_description_ = "Tests Python service framework by receiving and echoing messages over a named pipe" 

    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) 
     self.ReportServiceStatus(win32service.SERVICE_STOPPED) 
     win32event.SetEvent(self.hWaitStop)      

    def SvcDoRun(self): 
     import servicemanager  
     servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 
     self.timeout = 100 
     server = XMLRPCServerGet() 
     #server.serve_forever() 

     while 1: 
      # Wait for service stop signal, if I timeout, loop again 
      rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) 
      # Check to see if self.hWaitStop happened 
      if rc == win32event.WAIT_OBJECT_0: 
       # Stop signal encountered 
       server.shutdown() 
       servicemanager.LogInfoMsg("XMLRPCServerService - STOPPED") 
       break 
      else: 
       server.handle_request() 
       servicemanager.LogInfoMsg("XMLRPCServerService - is alive and well") 

def ctrlHandler(ctrlType): 
    return True 

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

あなたは彼の答えを受け入れるべきです – GoingTharn

関連する問題