【问题标题】:Wait to finish command executed with Python Paramiko等待完成使用 Python Paramiko 执行的命令
【发布时间】:2015-12-09 14:19:17
【问题描述】:

我在 Paramiko 中编写了这段代码:

ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(hostname, username=user, password=passwd, timeout=3)

session = ssh.invoke_shell()
session.send("\n")

session.send("echo step 1\n")
time.sleep(1)

session.send("sleep 30\n")
time.sleep(1)

while not session.recv_ready():
    time.wait(2)

output = session.recv(65535)

session.send("echo step 2\n")
time.sleep(1)

output += session.recv(65535)

我正在尝试在我的 Linux 服务器上执行更多命令。问题是我的 Python 代码没有等待完成执行命令,例如,如果我尝试执行 sleep 30,Python 不会等待 30 秒来完成执行命令。怎样才能解决这个问题?我尝试了while recv_ready(),但它仍然没有等待。

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    使用exec_commandhttp://docs.paramiko.org/en/1.16/api/channel.html

    stdin, stdout, stderr = ssh.exec_command("my_long_command --arg 1 --arg 2")
    

    以下代码适用于我:

    from paramiko import SSHClient, AutoAddPolicy
    import time
    ssh = SSHClient()
    ssh.set_missing_host_key_policy(AutoAddPolicy())
    ssh.connect('111.111.111.111', username='myname', key_filename='/path/to/my/id_rsa.pub', port=1123)
    sleeptime = 0.001
    outdata, errdata = '', ''
    ssh_transp = ssh.get_transport()
    chan = ssh_transp.open_session()
    # chan.settimeout(3 * 60 * 60)
    chan.setblocking(0)
    chan.exec_command('ls -la')
    while True:  # monitoring process
        # Reading from output streams
        while chan.recv_ready():
            outdata += chan.recv(1000)
        while chan.recv_stderr_ready():
            errdata += chan.recv_stderr(1000)
        if chan.exit_status_ready():  # If completed
            break
        time.sleep(sleeptime)
    retcode = chan.recv_exit_status()
    ssh_transp.close()
    
    print(outdata)
    print(errdata)
    

    请注意,命令history 不能按原样使用 ssh 执行。 请参阅此处的示例:https://superuser.com/questions/962001/incorrect-output-of-history-command-of-ssh-how-to-read-the-timestamp-info-corre

    【讨论】:

    • 我需要使用 invoke_shell 因为 exec_command 没有返回完整的输出
    • 这段代码确实会丢失一些输出。您需要在阅读前测试exit_status_ready(但仅在阅读后退出)。参见例如*.com/q/66191219/850848。虽然请参阅我的答案以获得更简单的解决方案。
    【解决方案2】:

    如果您不需要单独阅读标准输出和标准错误,您可以使用更直接的代码:

    stdin, stdout, stderr = ssh_client.exec_command(command)
    stdout.channel.set_combine_stderr(True)
    output = stdout.readlines()
    

    readlines 一直读取直到命令完成并返回完整的输出。


    如果您需要单独输出,不要试图删除set_combine_stderr 并分别在stdoutstderr 上调用readlines。那可能会陷入僵局。见Paramiko ssh die/hang with big output

    有关单独读取输出的正确代码,请参阅Run multiple commands in different SSH servers in parallel using Python Paramiko


    强制性警告:不要使用AutoAddPolicy - 这样做会失去对MITM attacks 的保护。如需正确解决方案,请参阅Paramiko "Unknown Server"

    【讨论】:

      最近更新 更多