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

如何在Python中保持root会话存续并执行后续ssh、scp等命令

问题根因

你之前的实现逻辑存在本质错误:loginAsroot函数中用pexpect创建的su子进程是独立的临时会话,函数执行完成后该会话就会被销毁。后续通过subprocess启动的所有进程仍然运行在当前普通用户test的权限下,和之前的root会话完全无关,自然会触发Permission denied权限错误。

解决方案:复用同一个pexpect root会话执行所有命令

所有需要root权限的操作都必须在同一个pexpect启动的su子进程中执行,不要单独调用subprocess。你可以将root会话对象保存下来,后续所有命令都通过该对象发送执行即可。

完整可运行示例代码

import pexpect

# 全局保存root会话对象,也可以封装到类中使用
root_session = None

def login_as_root(root_password: str) -> bool:
    """登录root账号,返回登录结果"""
    global root_session
    try:
        # 启动su进程
        root_session = pexpect.spawn("su", timeout=30)
        # 匹配密码输入提示
        root_session.expect(r"Password:\s*$")
        # 发送root密码
        root_session.sendline(root_password)
        # 匹配root用户的命令提示符#(匹配行尾避免命令输出中的#干扰)
        root_session.expect(r"#\s*$")
        return True
    except Exception as e:
        print(f"root登录失败:{str(e)}")
        if root_session:
            root_session.close()
            root_session = None
        return False

def run_command_in_root(cmd: str) -> tuple[str, str]:
    """在已有的root会话中执行命令,返回(标准输出, 错误输出)"""
    if not root_session:
        return "", "未登录root,请先调用login_as_root"
    try:
        # 发送要执行的命令
        root_session.sendline(cmd)
        # 等待命令执行完成,匹配提示符
        root_session.expect(r"#\s*$")
        # 提取输出内容:去掉输入的命令本身和最后的提示符
        output = root_session.before.decode("utf-8").splitlines()[1:]
        return "\n".join(output), ""
    except Exception as e:
        return "", str(e)

def close_root_session():
    """退出root会话,释放资源"""
    global root_session
    if root_session:
        root_session.sendline("exit")
        root_session.close()
        root_session = None

# 调用示例
if __name__ == "__main__":
    # 替换为你的root密码
    login_success = login_as_root("asdgfgh")
    if not login_success:
        exit(1)
    
    # 执行你的ssh命令
    cmd = "ssh user1@abc 'cat /dfg/hello.txt' >> /doc/g/auth.txt"
    output, err = run_command_in_root(cmd)
    if err:
        print(f"命令执行出错:{err}")
    else:
        print(f"命令执行完成,输出:{output}")
    
    # 执行其他需要root的命令,比如scp
    # scp_cmd = "scp /local/file root@remote:/path/"
    # run_command_in_root(scp_cmd)

    # 用完退出会话
    close_root_session()

注意事项

  • 提示符匹配正则可以根据你的实际root提示符调整,避免匹配错误导致命令执行超时
  • 如果ssh需要输入密码,可以在run_command_in_root逻辑中增加密码匹配逻辑,和su登录的处理逻辑一致
  • 所有需要root权限的ssh、scp、文件操作等命令,都必须通过run_command_in_root执行,不要单独调用subprocess

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:15:04