what socket node libreria descargar python windows windows-services flask gevent-socketio

python - libreria - sockets node



¿Cómo hacer un servicio de Windows python de un servidor matraz/gevent.socketio? (3)

Tengo un macket / gevent SocketIOServer y necesito que funcione como un servicio:

class TeleportService(win32serviceutil.ServiceFramework): _svc_name_ = "TeleportServer" _svc_display_name_ = "Teleport Database Backup Service" _svc_description_ = "More info at www.elmalabarista.com/teleport" 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): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '''')) self.ReportServiceStatus(win32service.SERVICE_RUNNING) runServer() @werkzeug.serving.run_with_reloader def runServer(): print ''Listening on %s...'' % WEB_PORT ws = SocketIOServer((''0.0.0.0'', WEB_PORT), SharedDataMiddleware(app, {}), resource="socket.io", policy_server=False) gevent.spawn(runTaskManager).link_exception(lambda *args: sys.exit("important_greenlet died")) ws.serve_forever()

Sin embargo, no puedo entender cómo detenerlo desde SvcStop, y ejecutarlo tiene el extraño comportamiento que el análisis del servicio de los parámetros de la línea de comando ocurre DESPUÉS de que se mata el servidor de ejecución. Esto significa que el servidor del matraz se ejecuta, puedo acceder desde el navegador web, pero el administrador del servicio lo listó como "No iniciado". Por ejemplo, ejecutando en la línea de comando:

C:/Proyectos/TeleportServer>python service.py uninstall <--BAD PARAM, TO MAKE IT OBVIOUS 2013-02-13 16:19:30,786 - DEBUG: Connecting to localhost:9097 * Restarting with reloader 2013-02-13 16:19:32,650 - DEBUG: Connecting to localhost:9097 Listening on 5000... Growl not available: Teleport Backup Server is started KeyboardInterrupt <--- HERE I INTERRUPT WITH CTRL-C Unknown command - ''uninstall'' Usage: ''service.py [options] install|update|remove|start [...]|stop|restart [... ]|debug [...]'' Options for ''install'' and ''update'' commands only: --username domain/username : The Username the service is to run under --password password : The password for the username --startup [manual|auto|disabled] : How the service starts, default = manual --interactive : Allow the service to interact with the desktop. --perfmonini file: .ini file to use for registering performance monitor data

Con la sugerencia de eliminar el recargador en vivo, este es el código que queda. Aún así, el mismo problema

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

#self.timeout = 640000 #640 seconds / 10 minutes (value is in milliseconds) self.timeout = 6000 #120 seconds / 2 minutes # This is how long the service will wait to run / refresh itself (see script below) notify.debug("Starting service") ws = getServer() while 1: # Wait for service stop signal, if I timeout, loop again gevent.sleep(0) rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) # Check to see if self.hWaitStop happened if rc == win32event.WAIT_OBJECT_0: # Stop signal encountered notify.debug("Stopping service") ws.kill() servicemanager.LogInfoMsg("TeleportService - STOPPED!") #For Event Log break else: notify.debug("Starting web server") ws.serve_forever()


El método serve_forever proviene de BaseServer.serve_forever . Para detenerlo, debe llamar a BaseServer.shutdown() o una derivada de este.

En resumen, debe declarar ws en el ámbito global. Poner este código antes de la definición de clase de Service es una forma de hacerlo.

ws = None

A continuación, cambie su implementación de Service.SvcStop a esto:

def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) #Tell the serve_forever() loop to stop and wait until it does. ws.shutdown()

Como ws.shutdown() ya espera a que el oyente se detenga, puede deshacerse de self.hWaitStop , a menos que lo use en otro lugar de su código.

Requiere Python 2.6+


No puedo acceder a WSGIRequestHandler en Flask fuera de la request , entonces uso Process .

import win32serviceutil import win32service import win32event import servicemanager from multiprocessing import Process from app import app class Service(win32serviceutil.ServiceFramework): _svc_name_ = "TestService" _svc_display_name_ = "Test Service" _svc_description_ = "Tests Python service framework by receiving and echoing messages over a named pipe" def __init__(self, *args): super().__init__(*args) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) self.process.terminate() self.ReportServiceStatus(win32service.SERVICE_STOPPED) def SvcDoRun(self): self.process = Process(target=self.main) self.process.start() self.process.run() def main(self): app.run() if __name__ == ''__main__'': win32serviceutil.HandleCommandLine(Service)


Para detenerlo desde SvcStop, debe almacenar una referencia a "ws" en una variable global (es decir, en algún lugar donde pueda recuperarse más adelante). AFAIK "ws.kill ()" debería finalizar el ciclo.

El decorador run_with_reloader parece ejecutar la función decorada inmediatamente, lo que explicaría por qué se procesa la línea de comandos después de ejecutar el servidor web. ¿Necesita recargar automáticamente, al parecer el decorador solo es necesario cuando necesita recargarse?

ACTUALIZACIÓN: código de servicio de ejemplo agregado

En un proyecto que no usa matraz o gevent utilizo algo como esto (con muchos detalles eliminados):

class Service (win32serviceutil.ServiceFramework): def __init__(self, *args, **kwds): self._mainloop = None win32serviceutil.ServiceFramework.__init__(self, *args, **kwds) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) if self._mainloop is not None: self._mainloop.shutdown() def SvcStart(self): self.ReportServiceStatus(win32service.SERVICE_START_PENDING) self._mainloop = ... .MainLoop() self.ReportServiceStatus(win32service.SERVICE_RUNNING) try: self._mainloop.run_forever() finally: self.ReportServiceStatus(win32service.SERVICE_STOPPED) win32serviceutil.HandleCommandLine(Service)