如何实现Twisted SSH服务器execCommand方法以兼容Fabric
问题根因
Fabric基于Paramiko实现SSH客户端,执行远程命令时会严格遵循SSH会话协议流程,除了等待服务端返回输出内容、EOF信号外,还必须收到服务端发送的命令退出状态码,同时收到通道关闭的确认才会结束等待。你当前的实现仅发送了EOF,缺失了退出状态码上报和通道关闭的完整逻辑,因此客户端会一直挂起。
修复步骤
- 新增
struct模块导入,用于打包SSH协议要求的整数类型退出状态码 - 补全
execCommand方法的完整结束流程:写完输出后先标记输出流结束,上报退出状态码,再发送EOF并关闭连接。
修改后核心代码
首先补全导入项:
import struct from pathlib import Path # 其余原有导入保持不变
然后修改SSHDemoAvatar类的execCommand方法:
def execCommand(self, protocol: session.SSHSessionProcessProtocol, cmd: bytes): # 写入命令返回内容,必须传bytes类型 protocol.write(b"Some text to return\n") # 标记标准输出、标准错误流已结束 protocol.outConnectionLost() protocol.errConnectionLost() # 按SSH协议规范上报命令退出状态,0表示执行成功,非0表示执行异常 protocol.session.conn.sendRequest( protocol.session, b"exit-status", struct.pack(">I", 0), True ) # 发送EOF并关闭会话通道 protocol.session.conn.sendEOF(protocol.session) protocol.loseConnection()
额外说明
- 如果命令执行逻辑有异常,可以把exit-status对应的值改成非0整数,Fabric会自动识别为命令执行失败,抛出对应异常
- 写入
protocol的所有内容必须是bytes类型,传入字符串会触发类型错误 - 不需要主动关闭整个SSH连接,只需要关闭当前执行命令的session通道即可,同一个连接可以复用执行多个命令
- 如果你需要在Fabric端开启PTY执行命令,保持现有
getPty方法返回None即可正常兼容,不需要额外修改
内容的提问来源于stack exchange,提问作者Mr-Pepe
相关产品推荐
相关产品推荐

