Python Windows Service日志功能失效问题排查求助
问题分析与解决
首先得给你点明一个核心关键点:你在命令行执行install/start/restart/remove这些命令时,运行的Python进程和Windows实际启动的服务进程是完全独立的两个进程!
你现在看到的日志(Class opened和Calling Handle Command Line),全都是来自你手动在命令行执行脚本的那个进程;而服务真正运行时的进程,是由Windows服务控制管理器(SCM)启动的——它的默认工作目录是C:\Windows\System32,运行账户通常是Local System,这就是你的内部函数日志没出现在预期文件里的根本原因:
- 你在代码里重复调用
logging.basicConfig,但这个函数只有第一次调用会生效,后续调用都会被忽略。更关键的是,服务进程启动时的工作目录不是你的脚本目录,所以search_server.log会被创建在C:\Windows\System32里,而非你脚本所在的C:\PythonScripts\SearchServer,你自然看不到这些日志。 - Local System账户可能没有你脚本目录的写入权限,就算服务进程想往那里写日志也会静默失败。
修复步骤
1. 统一配置日志,使用绝对路径
把日志配置移到脚本最开头,只配置一次,并且指定绝对路径,确保服务进程能精准找到并写入目标文件:
import win32serviceutil import win32service import win32event import servicemanager import socket import logging import os # 获取脚本所在的绝对路径,彻底规避服务进程工作目录问题 script_dir = os.path.dirname(os.path.abspath(__file__)) log_path = os.path.join(script_dir, 'search_server.log') # 仅配置一次日志,添加时间戳更便于排查问题 logging.basicConfig( filename=log_path, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) class AppServerSvc(win32serviceutil.ServiceFramework): _svc_name_ = "TestService" _svc_display_name_ = "Test Service" _svc_description_ = "New Test Service" def __init__(self, args): logging.info('Init function called') win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(60) def SvcStop(self): logging.info('Stop function called') self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) def SvcDoRun(self): logging.info('Run function called') servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '')) self.main() def main(self): logging.info('Main function called') # 替换print,服务没有控制台输出,print内容会丢失 if __name__ == '__main__': logging.info('Calling Handle Command Line') win32serviceutil.HandleCommandLine(AppServerSvc)
2. 确保服务有日志目录的写入权限
如果修改后还是看不到日志,大概率是权限问题,你可以任选一种方式解决:
- 手动给
C:\PythonScripts\SearchServer目录添加Local System账户的写入权限; - 把日志路径改到系统默认有写入权限的位置,比如
C:\Temp\search_server.log; - 安装服务时指定有权限的运行账户:
python servicetest.py install --username "你的Windows用户名" --password "你的账户密码"。
3. 验证之前的问题残留
你可以去C:\Windows\System32目录下找找有没有search_server.log文件,里面应该有服务进程之前生成的Init、Run、Main这些日志——这就能实锤之前的问题确实是工作目录导致的。
额外提示
- 服务进程没有控制台窗口,所以
print语句的输出你完全看不到,全部换成logging才是正确的调试方式; - 不要在类定义里直接写
logging.info('Class opened'),因为每次加载类的时候都会执行(包括命令行进程加载类的场景),这就是你看到多次Class opened的原因,建议把这行删掉,只保留业务相关的日志。
内容的提问来源于stack exchange,提问作者Matthew Baker




