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

通过SSH读取远程服务器日志时Python subprocess连接异常断开

问题描述

我尝试通过SSH连接服务器的特定端口并读取日志,但用Python subprocess执行相关命令时,SSH连接在认证完成后立即关闭。我使用的命令为:sshpass -p xxxx ssh -tt -v root@xxx.xxx.xxx.xx -p 2200 | tee -i -a remoteserver.log。调试日志如下:

debug1: Authentication succeeded (password).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: network
debug1: tty_make_modes: no fd or tio
debug1: Sending environment.
debug1: Sending env LANG = en_US
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
debug1: fd 2 clearing O_NONBLOCK
Connection to xxx.xxx.xxx.x closed.
Transferred: sent 1808, received 1440 bytes, in 0.0 seconds
Bytes per second: sent 36560.7, received 29119.1
debug1: Exit status 0

注:该命令在终端直接执行时运行正常。有人遇到过类似问题吗?


解决办法

这种情况核心是Python subprocess默认的环境和终端交互环境不匹配——终端里有完整的tty支持,能维持SSH的交互式会话,但subprocess默认的流处理会导致SSH在认证后没有输入源,直接退出。试试以下几种方案:

  1. 给subprocess模拟终端环境
    用Popen时显式指定流参数,同时开启终端模拟:

    import subprocess
    
    cmd = "sshpass -p xxxx ssh -tt -v root@xxx.xxx.xxx.xx -p 2200 | tee -i -a remoteserver.log"
    # 开启shell支持管道,绑定标准流并模拟新会话
    proc = subprocess.Popen(
        cmd,
        shell=True,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        start_new_session=True
    )
    # 保持进程运行,读取输出
    output, _ = proc.communicate()
    print(output.decode())
    
  2. 把tee逻辑移到Python里,去掉管道依赖
    直接捕获SSH输出并写入日志文件,避免管道带来的流同步问题:

    import subprocess
    
    ssh_cmd = "sshpass -p xxxx ssh -tt -v root@xxx.xxx.xxx.xx -p 2200"
    proc = subprocess.Popen(
        ssh_cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        universal_newlines=True
    )
    
    # 实时写入日志并打印
    with open("remoteserver.log", "a") as log_file:
        for line in proc.stdout:
            print(line.strip())
            log_file.write(line)
    
  3. 用pexpect处理交互式会话
    如果上述方法还是不行,试试专门处理终端交互的pexpect库,它能更好地模拟终端环境:

    import pexpect
    
    ssh_cmd = "sshpass -p xxxx ssh -tt -v root@xxx.xxx.xxx.xx -p 2200"
    child = pexpect.spawn(ssh_cmd)
    
    with open("remoteserver.log", "a") as log_file:
        while True:
            try:
                line = child.readline()
                if not line:
                    break
                content = line.decode()
                print(content.strip())
                log_file.write(content)
            except pexpect.EOF:
                break
    

内容的提问来源于stack exchange,提问作者mrutyunjay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:35:14