【问题标题】:How to run commands inside the root session in python如何在 python 的根会话中运行命令
【发布时间】:2022-01-04 13:35:31
【问题描述】:

我必须实现一个场景,我需要以 root 身份登录,然后通过 python 执行一些 ssh 和 scp 命令来自动化某些工作流。

示例:假设MACHINE12是我的主机,当前用户是test,即test@MACHINE12 我希望以这样的方式编写交互式代码,如果我输入以下命令,它应该以 root 用户身份登录,并且应该维护会话以在 python 中执行其他操作。

{test@MACHINE12} su

password:

输入密码后,以root身份登录。

{test@MACHINE12 test}

在此处执行其他命令

{test@MACHINE12 test} ssh user1@abc

我在 python 中使用pexpect 命令尝试了此操作,但未维护根会话或保留执行其他操作。 这些命令只有在登录会话是 root 时才能执行,因为abc 主机需要root 权限。

在这里找到我尝试过的 sn-p:

def loginAsroot():
    childTab = pexpect.spawn("su") //command su to enter to root
    childTab.expect(":")
    childTab.sendline("asdgfgh")  // entering password
    childTab.expect("#")

def runCommands():
    command = "ssh user1@abc 'cat /dfg/hello.txt'>> /doc/g/auth.txt"
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    output, error = process.communicate(timeout=10000)
    return output

//function call
loginAsroot()
runCommands()

我正在尝试执行 linux 命令,它给出了权限被拒绝错误,因为 root 会话没有保留,它被注销了。因此Permission denied

我怎样才能实现这种执行?

【问题讨论】:

    标签: python-3.x linux automation root pexpect


    【解决方案1】:

    您正在尝试同时使用 pexpect 和 subprocess。这些可能会产生不同的会话。以下是否有效?

    import pexpect
    child = pexpect.spawn('su')
    child.expect(':')
    child.sendline('asdgfgh')
    child.expect('#')
    command = "ssh user1@abc 'cat /dfg/hello.txt'>> /doc/g/auth.txt"
    child.sendline(command)
    child.expect('#')
    

    我认为使用其中任何一个模块都可以解决您的问题。

    【讨论】:

    • 我试过了,但没用。
    • 错误是什么?
    【解决方案2】:

    对于 SSH,我喜欢 Paramiko,因为它可以处理开销。为了演示,我编写了两个版本的代码:一个一直使用 Pexpect,另一个使用 Paramiko。请记住:

    1. 确保远程机器的IP地址不在/root/.ssh/known_hosts中;否则会出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 错误。
    2. 我更喜欢expect_exact,因为expect 使用正则表达式模式。使用expect,如果您查找使用正则表达式字符的提示(例如$),您可能会收到错误消息。
    3. 如果我必须使用root,我也更喜欢使用su - 而不是su,因为它会清除环境变量。

    顺便说一句,谢谢你的问题。有时我会忘记我刚刚告诉您要记住的内容:facepalm:!

    注意 - 使用两个 Debian VM 和 Python 3.9 进行测试。我更改了提示并隐藏了密码和 IP 地址。

    使用 Pexpect(所有内容都回显到 STDOUT):

    import sys
    
    import pexpect
    
    child = pexpect.spawn("su -", logfile=sys.stdout.buffer)
    child.expect_exact("Password:")
    child.sendline("**********")
    child.expect_exact("#")
    child.sendline("ssh user@192.168.X.X")
    while True:
        # Must use expect_exact to avoid expect regex conflict with prompt ($)!
        index = child.expect_exact(
            ["Are you sure you want to continue connecting", "password:", "$", ])
        if index == 0:
            child.sendline("yes")
        elif index == 1:
            child.sendline("**********")
        else:
            break
    child.sendline("cat hello.txt >> auth.txt")
    child.expect_exact("$")
    child.sendline("cat auth.txt")
    child.expect_exact("$")
    # If you do not use the logfile, you can make sure the file got copied using:
    # print(child.before)
    child.sendline("exit")
    child.expect_exact("#")
    child.sendline("exit")
    # The child closes after the exit command (EOF); this is just to make sure
    child.expect_exact(["$", pexpect.EOF, ])
    child.close()
    print("Script complete. Have a nice day.")
    

    输出:

    Password: **********
    
    test@MACHINE12:~# ssh user1@192.168.X.X
    ssh user1@192.168.X.X
    The authenticity of host '192.168.X.X (192.168.X.X)' can't be established.
    RSA key fingerprint is SHA256:********************************************
    This key is not known by any other names
    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
    yes
    Warning: Permanently added '192.168.X.X' (RSA) to the list of known hosts.
    **********@192.168.X.X's password: **********
    
    Last login: Sat Dec  4 20:40:12 2021 from 192.168.X.X
    user1@192.168.X.X:~$ cat hello.txt >> auth.txt
    cat hello.txt >> auth.txt
    user1@192.168.X.X:~$ cat auth.txt
    cat auth.txt
    Hello, world!
    user1@192.168.X.X:~$ b' cat auth.txt\r\nHello, world!\r\nuser1@192.168.X.X:~'
    exit
    exit
    logout
    Connection to 192.168.X.X closed.
    
    test@MACHINE12:~# exit
    exit
    Script complete. Have a nice day.
    
    Process finished with exit code 0
    

    使用 Paramiko(无回显):

    import paramiko
    import pexpect
    
    child = pexpect.spawn("su -")
    child.expect_exact("Password:")
    child.sendline("**********")
    child.expect_exact("#")
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("192.168.X.X", username="user1", password="**********")
    ssh.exec_command("cat hello.txt >> auth.txt")
    _, chan_out, _ = ssh.exec_command("cat auth.txt")
    print("\nauth contents:", chan_out.read().decode())
    ssh.close()
    child.sendline("exit")
    child.expect_exact(["$", pexpect.EOF, ])
    child.close()
    print("Script complete. Have a nice day.")
    

    输出:

    auth contents: Hello, world!

    祝你的代码好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-24
      • 2010-09-30
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      相关资源
      最近更新 更多