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

基于Python Paramiko实现SCP服务器时exec请求失败问题求解

问题根源分析
  • SCP协议底层依赖SSH的exec请求实现,你当前编写的Server类仅实现了shell和pty请求的处理逻辑,没有重写check_channel_exec_request回调方法,Paramiko默认会拒绝所有未显式声明支持的exec请求,这是exec request failed on channel 0报错的直接原因。
  • 现有代码存在冗余逻辑错误:身份验证通过后你主动发起了到本机22端口的新Transport连接,还直接调用interactive.interactive_shell(chan)抢占了会话通道,导致后续exec请求根本无法被正常接收处理。
修复步骤

步骤1:给Server类添加exec请求处理方法

在Server类中新增如下方法,允许exec请求并存储接收的命令:

def check_channel_exec_request(self, channel, command):
    logging.info(f"Received exec request: {command.decode()}")
    # 存储命令到实例属性,方便后续业务逻辑调用
    self.command = command
    self.event.set()
    return True

步骤2:删除冗余错误逻辑

完全删除以下三行无效代码,服务器不需要主动向自身发起SSH连接,也不需要提前抢占通道启动交互shell:

transport = paramiko.Transport(sock=("192.168.34.10", 22))
transport.connect(username="root", password="password")
interactive.interactive_shell(chan)

步骤3:添加SCP协议处理逻辑

SCP的-t参数表示当前是服务器端接收文件的场景,你需要按照SCP协议规则完成交互,替换原有后续的shell处理逻辑为以下代码:

server.event.wait()
# 优先处理exec类请求(含SCP)
if hasattr(server, 'command'):
    cmd = server.command.decode()
    # 匹配SCP上传请求
    if cmd.startswith('scp -t'):
        # 解析目标存储路径
        target_path = cmd.split(' ')[-1]
        # 向客户端返回0字节表示就绪,可以开始传输
        chan.sendall(b'\x00')
        # 读取文件元信息,格式为 C<权限> <文件大小> <文件名>\n
        header = chan.recv(1024).decode()
        if not header.startswith('C'):
            chan.sendall(b'\x01')
            chan.close()
            sys.exit(1)
        # 解析元信息字段
        mode, size, filename = header[1:].strip().split(' ')
        size = int(size)
        # 确认收到元信息,通知客户端发送文件内容
        chan.sendall(b'\x00')
        # 接收文件内容
        file_content = b''
        while len(file_content) < size:
            chunk = chan.recv(min(4096, size - len(file_content)))
            if not chunk:
                break
            file_content += chunk
        # 接收传输结束标记
        chan.recv(1)
        # 返回传输成功
        chan.sendall(b'\x00')
        # 存储文件到本地,生产环境需要补充路径遍历漏洞防护
        save_path = os.path.join(dir_local, filename)
        with open(save_path, 'wb') as f:
            f.write(file_content)
        chan.close()
        sys.exit(0)

# 原有shell处理逻辑保留,用于普通SSH登录场景
chan.send("Success Connect\r\n\r\n")
f = chan.makefile("rU")
while True:
    cmd = f.readline().strip("\r\n")
    myCmd = os.popen(cmd).read()
    print(myCmd)
额外注意事项
  • 上述SCP处理为最简实现,生产环境使用需要补充路径遍历防护、大文件分片存储、异常错误码返回、权限校验等逻辑。
  • 测试前请确认代码中定义的dir_local路径存在,且运行进程对该路径有写入权限。
  • 如果需要支持SCP下载功能(客户端从服务器拉取文件),还需要额外适配scp -f开头的命令逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:45:04