Jenkins中通过Fabric SSH执行sudo snap revert报错求助
问题
尝试使用Fabric通过SSH在远程Ubuntu 18.04机器上执行snap revert命令,手动执行该命令可正常运行,但通过Jenkins执行时失败。
使用的Python代码如下:
from fabric import Config, Connection connection = Connection( node_ip, config=Config(overrides={"sudo": {"password": sudo_pass}}), user=user, connect_kwargs={"password": sudo_pass}, ) connection.sudo("snap revert mysnap-app")
出现的错误信息:
... raise ThreadException(thread_exceptions) invoke.exceptions.ThreadException: Saw 1 exceptions within threads (OSError): Thread args: {'kwargs': {'buffer_': ['[sudo] password: \n'], 'hide': False, 'output': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>}, 'target': <bound method Runner.handle_stderr of <fabric.runners.Remote object at 0x10fb06a00>>} Traceback (most recent call last): ... File "/.../site-packages/paramiko/channel.py", line 1198, in _send raise socket.error("Socket is closed") OSError: Socket is closed
已尝试设置pty=False,结果相同。问题具有一致性:在Jenkins代理所在机器手动运行正常,但通过Jenkins代理执行时必然失败。
解决思路
- 对比环境变量差异:手动运行时和Jenkins代理的环境变量可能存在区别,比如
HOME、PATH或snap相关变量。可在代码中先执行connection.run("env"),将输出与手动执行的结果对比,排查差异点。 - 优化sudo权限配置:修改远程机器的
sudoers文件,允许执行命令的用户免密运行snap revert mysnap-app,避免密码交互过程中出现Socket断开问题。示例规则:user ALL=(ALL) NOPASSWD: /usr/bin/snap revert mysnap-app。 - 增加调试日志:在执行
snap revert前后添加调试命令,比如connection.run("whoami")、connection.run("snap list mysnap-app"),确认执行上下文是否正常;也可使用connection.sudo("snap revert mysnap-app", warn=True)捕获详细错误信息,而非直接抛出异常。 - 增强SSH连接稳定性:在
connect_kwargs中添加keepalive_interval参数维持连接,示例:connect_kwargs={"password": sudo_pass, "keepalive_interval": 30},避免因连接超时导致Socket关闭。 - 指定命令完整路径:Jenkins环境的
PATH可能与手动环境不同,先用connection.run("which snap")获取snap的绝对路径,然后用完整路径执行命令,比如/usr/bin/snap revert mysnap-app。 - 排查Fabric版本兼容性:部分Fabric 2.x版本可能存在与Paramiko的兼容性问题,尝试切换到稳定版本(比如2.7.0)测试是否解决问题。
内容的提问来源于stack exchange,提问作者chaos.ct
相关产品推荐
相关产品推荐

