【问题标题】:Wait until paramiko exec_command is finished等到 paramiko exec_command 完成
【发布时间】:2023-09-18 14:40:01
【问题描述】:

我有一个 python 脚本,我正在尝试在其上安装一个 rpm 包,但是当我发送安装命令时,它不会在重新启动服务之前等待命令完成。我已经阅读了很多关于使用 recv_exit_status() 的论坛,但我认为我没有正确使用它。

这就是我所拥有的:

#!/usr/bin/python

import paramiko, os
from getpass import getpass

# Setting Variables 
Hosts = [ '192.168.1.1', '192.168.1.2'] #IPs changed for posting
username = 'root'
print 'Enter root password on remote computer:'
password = getpass()
port = 22
File = 'Nessus-6.11.2-es7.x86_64.rpm'

for host in Hosts:
    print 'Finished copying files. Now executing on remote computer'

    #Setting up SSH session to run commands
    remote_client = paramiko.SSHClient()
    remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    remote_client.connect(host, username=username, password=password)

    InstallNessus = 'rpm -U --percent %s'%File
    stdin, stdout, stderr = remote_client.exec_command(InstallNessus)
    stdout.channel.recv_exit_status()
    lines = stdout.readlines()
    for line in lines:
        print line
    stdin, stdout, stderr = remote_client.exec_command('systemctl restart nessusd.service')

    remote_client.close()

我尝试过使用 Fabric,但我似乎在某处弄乱了我的语法。

【问题讨论】:

标签: python ssh paramiko


【解决方案1】:

add get_pty=True 这将等到命令执行完成。 stdin,stdout,stderr = self.ssh.exec_command(command,get_pty=True)

【讨论】:

    【解决方案2】:

    这是channel.recv_exit_status(),而不是stdout.channel.recv_exit_status()

    但是,由于您尝试在多个服务器上运行相同的命令,因此像 parallel-ssh 这样的命令更适合并且比 paramiko 更快,无论是顺序还是并行。

    实现它的代码也简单得多,只是:

    from pssh.pssh2_client import ParallelSSHClient
    
    hosts = ['192.168.1.1', '192.168.1.2']
    _file = 'Nessus-6.11.2-es7.x86_64.rpm'
    cmd = 'rpm -U --percent %s' % _file
    
    client = ParallelSSHClient(hosts, user='<user>', password='<password>')
    
    output = client.run_command(cmd)
    for host, host_output in output.items():
        for line in host_output.stdout:
            print "Host %s: %s" % (host, line)
        print "Host %s exit code %s" % (host, host_output.exit_code)
    
    restart_out = client.run_command('systemctl restart nessusd.service')
    # Just wait for completion
    client.join(restart_out)
    

    更多信息请参见documentation

    【讨论】:

    • 使用您发布的内容,但它似乎在做同样的事情。该脚本似乎没有等待 rpm 安装完成。我只得到“主机 192.168.1.1 退出代码 0”的输出。不过,我会继续查看文档。
    • 先测试你的命令。如果没有输出,则该命令可能没有执行或退出而无事可做,例如,如果 RPM 已安装。
    • 我是个菜鸟。我刚刚意识到我没有将完整路径放在我的文件变量中。我认为这是我所有脚本的问题。