Tôi đang cố tạo một máy chủ XML-RPC làm dịch vụ cửa sổ.
Máy chủ XML-RPC có thể nhận và đặt các tệp (như FTP) và
cũng thực hiện lệnh thông qua os.system() mà ứng dụng khách từ xa
gửi đến nó.Máy chủ XML-RPC Python dưới dạng dịch vụ Windows
Tôi đang cố đóng gói máy chủ trong dịch vụ cửa sổ
vòng lặp sự kiện.
Khi tạo dịch vụ không có vấn đề gì.
python.exe remoteServer.py --startup=auto install
Installing service XMLRPCServerService
Service installed
Khi bắt đầu dịch vụ không có vấn đề gì.
python.exe remoteServer.py start
Starting service XMLRPCServerService
Khi dừng dịch vụ không có vấn đề gì.
python.exe remoteServer.py stop
Stopping service XMLRPCServerService
Khi khởi động lại dịch vụ, có sự cố.
python.exe remoteServer.py start
Starting service XMLRPCServerService
Error starting service: An instance of the service is already running.
Nhìn vào màn hình quá trình, tôi thấy một quá trình "pythonservice.exe" đó là
vẫn chạy.
Dưới đây là nội dung của 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)
Tôi không chắc đây có phải là gốc của sự cố không, nhưng có vẻ như bạn đang thiếu một cuộc gọi đến 'self.ReportServiceStatus (win32service.SERVICE_STOPPED) ' ở cuối phương thức SvcStop của bạn. –
@David K. Hess Bạn hoàn toàn đúng! Nó đang lẩn trốn trong tầm nhìn đơn giản! –
Cảm ơn! Tôi đã đi trước và thêm nó như là một câu trả lời. –