You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:24:52