Python3.12升级后Win10服务版端口反向转发脚本崩溃求助
Python 3.12下pywin32端口转发服务启动后立即停止的排查建议
以下是针对问题的具体排查步骤:
确认pywin32兼容性:Python 3.12对第三方库兼容性要求更高,先升级pywin32到支持3.12的最新版本:
pip install --upgrade pywin32安装完成后必须以管理员权限执行注册脚本:
python "C:\Python312\Lib\site-packages\pywin32_postinstall.py" -install查看系统事件日志:打开Windows事件查看器,依次进入「Windows日志」→「应用程序」,查找来源为
Service Control Manager或服务名autossh1的错误条目,里面会包含服务启动失败的具体原因(如权限不足、依赖缺失、代码抛出未捕获异常等)。添加本地错误日志:服务环境下
print输出无法查看,修改代码中的异常捕获逻辑,将错误信息写入本地日志文件,以便定位具体报错:# 替换原有的except块 except Exception as e: with open('C:\\autossh_service_errors.log', 'a', encoding='utf-8') as f: log_time = time.strftime('%Y-%m-%d %H:%M:%S') f.write(f"[{log_time}] Execution failed: {str(e)}\n")检查subprocess执行环境:
- 服务运行在系统账户下,可能找不到
ssh命令,需指定ssh的绝对路径(比如OpenSSH默认路径C:\\Windows\\System32\\OpenSSH\\ssh.exe); - 系统账户没有普通用户的SSH密钥配置,需将密钥文件放到系统账户的
C:\Windows\System32\config\systemprofile\.ssh目录下,确保权限正确。
- 服务运行在系统账户下,可能找不到
非服务模式测试代码:先直接运行脚本(普通用户权限),验证SSH命令是否能正常执行,排除代码逻辑本身的问题,再切换到服务环境测试。
调整服务启动超时设置:在
SvcDoRun方法中,修改启动状态报告的等待超时时间,避免因初始化耗时过长被系统判定启动失败:def SvcDoRun(self): # 增加waitHint参数,设置10秒超时等待 self.ReportServiceStatus(win32service.SERVICE_START_PENDING, waitHint=10000) self.service_impl = MyService() self.ReportServiceStatus(win32service.SERVICE_RUNNING) self.service_impl.run()
修正后的原始代码(已处理HTML转义的引号)
import time import sys import subprocess as sp import win32serviceutil # ServiceFramework and commandline helper import win32service # Events import servicemanager # Simple setup and logging class MyService: def stop(self): self.running = False def run(self): rport=55009 cmd=f'ssh -fNR {rport}:127.0.0.1:3389 username@remotehost -p 22' cmd1=f'ssh -tt username@remotehost -p 22 "netstat -tpa | grep \'**:{rport} **\'"' while True: a=sp.run(cmd1,capture_output=True,shell=True).stdout.decode("utf-8") # print('one turn') if f":{rport}" not in a: try: p=sp.Popen(cmd,shell=True) p.wait(2) except sp.TimeoutExpired: p.kill() except Exception as e: with open('C:\\autossh_service_errors.log', 'a', encoding='utf-8') as f: log_time = time.strftime('%Y-%m-%d %H:%M:%S') f.write(f"[{log_time}] Execution failed (reconnect): {str(e)}\n") elif not "ESTABLISHED" in a: cmd2='"ps aux | grep \'**xiaoya**\'| awk \'{print $2}\' | xargs -r kill"' cmd2=f"ssh -tt username@remotehost -p 22 {cmd2}" try: sp.run(cmd2,shell=True) p=sp.Popen(cmd,shell=True) p.wait(2) except sp.TimeoutExpired: p.kill() except Exception as e: with open('C:\\autossh_service_errors.log', 'a', encoding='utf-8') as f: log_time = time.strftime('%Y-%m-%d %H:%M:%S') f.write(f"[{log_time}] Execution failed (restart): {str(e)}\n") time.sleep(5) servicemanager.LogInfoMsg("Service running...") class MyServiceFramework(win32serviceutil.ServiceFramework): _svc_name_ = 'autossh1' _svc_display_name_ = 'autossh1' def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) self.service_impl.stop() self.ReportServiceStatus(win32service.SERVICE_STOPPED) def SvcDoRun(self): self.ReportServiceStatus(win32service.SERVICE_START_PENDING, waitHint=10000) self.service_impl = MyService() self.ReportServiceStatus(win32service.SERVICE_RUNNING) self.service_impl.run() def init(): if len(sys.argv) == 1: servicemanager.Initialize() servicemanager.PrepareToHostSingle(MyServiceFramework) servicemanager.StartServiceCtrlDispatcher() else: win32serviceutil.HandleCommandLine(MyServiceFramework) if __name__ == '__main__': init()
内容的提问来源于stack exchange,提问作者wangwei
相关产品推荐
相关产品推荐

