欢迎访问宙启技术站
智能推送

win32service:如何在Python中实现Windows服务的日志记录

发布时间:2023-12-24 11:01:23

在Python中,可以使用win32service和win32serviceutil模块来实现Windows服务的日志记录。下面是一个使用例子,展示了如何创建一个简单的Windows服务,并在其中记录日志。

首先,安装pywin32库来获取win32service和win32serviceutil模块。可以使用以下命令来安装:

pip install pywin32

接下来,创建一个Python脚本,并导入所需的模块:

import win32service
import win32serviceutil
import win32event
import servicemanager
import socket
import logging
import os
import inspect

# 创建日志记录器
def setup_logger(logger_name, log_file, level=logging.INFO):
    l = logging.getLogger(logger_name)
    formatter = logging.Formatter('%(asctime)s : %(message)s')
    fileHandler = logging.FileHandler(log_file, mode='w')
    fileHandler.setFormatter(formatter)
    streamHandler = logging.StreamHandler()
    streamHandler.setFormatter(formatter)

    l.setLevel(level)
    l.addHandler(fileHandler)
    l.addHandler(streamHandler)

# 编写一个简单的服务类
class MyService(win32serviceutil.ServiceFramework):
    _svc_name_ = 'MyService'
    _svc_display_name_ = 'My Service'

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

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

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

    def main(self):
        # 获取当前脚本所在路径
        script_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))

        # 设置日志文件路径
        log_file = os.path.join(script_dir, 'service.log')

        # 设置日志记录器
        setup_logger('my_service_logger', log_file)

        # 记录日志
        logging.info('Service started')

        while self.is_running:
            # 在此处执行服务的主要功能
            pass

        # 记录日志
        logging.info('Service stopped')

# 主函数
def main():
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(MyService)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(MyService)

if __name__ == '__main__':
    main()

上述代码创建了一个名为MyService的Windows服务类,其中定义了一些必要的函数用于服务的启动和停止。在SvcDoRun函数中,记录了服务的启动事件,并调用了自定义的main函数。

main函数中,根据命令行参数的数量判断是以服务方式运行还是以命令行方式运行。以命令行方式运行时,会使用win32serviceutil.HandleCommandLine函数来解析命令行参数,以执行相关操作。

在main函数的MyService类实例化之前,我们在MyService类的构造函数中设置了日志记录,指定了日志文件的路径和记录级别。在MyService类的main函数中,可以使用logging.info、logging.warning等函数来记录相应级别的日志。

启动服务时,可以通过服务控制台或使用以下命令:

python service.py install
python service.py start

这样就创建了一个可以在Windows系统中运行的服务,并且可以在日志文件中记录相应的日志。

需要注意的是,日志记录器的设置可能有所不同,可以根据实际需求进行调整,比如设置日志级别、日志格式等。

参考资料:

- [https://pypi.org/project/pywin32/](https://pypi.org/project/pywin32/)

- [https://docs.python.org/3/library/win32serviceutil.html](https://docs.python.org/3/library/win32serviceutil.html)

- [https://docs.python.org/3/library/logging.html](https://docs.python.org/3/library/logging.html)