【问题标题】:Do not wait for commands to finish when executing them with Python Paramiko [duplicate]使用 Python Paramiko 执行命令时不要等待命令完成 [重复]
【发布时间】:2021-05-07 22:49:11
【问题描述】:

我正在利用 Paramiko 库运行一系列远程 shell 命令。

最终的命令需要用户在终端设备上输入,我不需要等待执行完成;但是,在最后一个命令完成之前,我无法继续。

代码:

k = paramiko.RSAKey.from_private_key_file("....", password="....")
conn = paramiko.SSHClient()
conn.connect(hostname=ip_addr, username="root", pkey=k, password="....")

commands = ["chmod 755 /tmp/evtool", "nohup /tmp/test.sh >/dev/null 2>&1"]

for command in commands:
    stdin, stdout, stderr = conn.exec_command(command)
conn.close()

有问题的命令是:

nohup /tmp/test.sh >/dev/null 2>&1

无论我如何尝试运行它:

/tmp/test.sh
/tmp/test.sh&

应用程序等待进程完成;但是完成可能需要几个小时,并且通过/失败会显示在远程单元上,我不需要等待结果。

我有几十个远程单元,上面的函数是从一个循环中调用的,该循环遍历单元 ip 地址并建立连接/运行测试。

任何想法如何不等待最后一个过程完成?

谢谢,丹。

【问题讨论】:

    标签: python linux shell ssh paramiko


    【解决方案1】:

    这不是真正的 Python 或 Paramiko 问题。这是一个 Linux shell 问题。

    根据Getting ssh to execute a command in the background on target machine,看来你需要nohup&


    尽管从您的 cmets 看来,您似乎确实想等待命令完成。您可能只是想并行运行多个命令。

    实际上SSHClient.exec_command 不会等待。所以我不确定你的问题到底是什么。

    但实际上,在收集它们的输出时并行等待多个命令(如果这是您想要的)并不是那么简单。这样的工作:

    commands = [
        "for i in {1..10}; do echo \"0 o:$i\"; sleep 1; echo \"0 e:$i\" >&2; sleep 1; done",
        "for i in {1..10}; do echo \"1 o:$i\"; sleep 1; echo \"1 e:$i\" >&2; sleep 1; done",
        "for i in {1..10}; do echo \"2 o:$i\"; sleep 1; echo \"2 e:$i\" >&2; sleep 1; done",
    ]
    
    channels = []
    for command in commands:
        print(f"starting {len(channels)}")
        stdin, stdout, stderr = ssh.exec_command(command)
        channels.append(stdout.channel)
    
    while any(x is not None for x in channels):
        for i in range(len(channels)):
            channel = channels[i]
            if channel is not None:
                # To prevent losing output at the end, first test for exit, then for output
                exited = channel.exit_status_ready()
                while channel.recv_ready():
                    s = channel.recv(1024).decode('utf8')
                    print(f"#{i} stdout: {s}")
                while channel.recv_stderr_ready():
                    s = channel.recv_stderr(1024).decode('utf8')
                    print(f"#{i} stderr: {s}")
                if exited:
                    print(f"#{i} done")
                    channels[i] = None
        time.sleep(0.1)
    

    【讨论】:

      最近更新 更多