如何使用Paramiko获取SSH返回码?


97
client = paramiko.SSHClient()
stdin, stdout, stderr = client.exec_command(command)

有什么方法可以获取命令返回码?

很难解析所有stdout / stderr并知道命令是否成功完成。

Answers:


51

SSHClient是一个简单的包装类,围绕着Paramiko中的更底层功能。该API文档列出recv_exit_status()的方法Channel类。

一个非常简单的演示脚本:

import paramiko
import getpass

pw = getpass.getpass()

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
client.connect('127.0.0.1', password=pw)

while True:
    cmd = raw_input("Command to run: ")
    if cmd == "":
        break
    chan = client.get_transport().open_session()
    print "running '%s'" % cmd
    chan.exec_command(cmd)
    print "exit status: %s" % chan.recv_exit_status()

client.close()

执行示例:

$ python sshtest.py
Password: 
Command to run: true
running 'true'
exit status: 0
Command to run: false
running 'false'
exit status: 1
Command to run: 
$

9
这是一个不好的解决方案。参见下面的@apdastous'答案,它要好得多。
Patrick

虽然您对正确recv_exit_status,但是您不能以这种方式使用它,因为代码可能会死锁。您必须在等待命令完成的同时使用命令输出。参见Paramiko ssh die / hang,输出大
马丁·普里克里

282

一个更简单的示例,该示例不涉及直接调用“较低级别”的通道类(即- 使用client.get_transport().open_session()命令):

import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('blahblah.com')

stdin, stdout, stderr = client.exec_command("uptime")
print stdout.channel.recv_exit_status()    # status is 0

stdin, stdout, stderr = client.exec_command("oauwhduawhd")
print stdout.channel.recv_exit_status()    # status is 127

5
什么是好的关于这个例子是捕获不仅仅是EXIT(如问题问),但证明你仍然可以得到STDOUT和STDERR。几年前,我被Paramiko贫乏的示例代码库(不要轻视)误导了,为了退出,我诉诸了低级的transport()调用。transport()似乎迫使您“选择一个”(虽然可能不正确,但是缺乏示例和教程文档使我相信)……
Scott Prive

虽然您对正确recv_exit_status,但是您不能以这种方式使用它,因为代码可能会死锁。您必须在等待命令完成的同时使用命令输出。参见Paramiko ssh die / hang,输出大
马丁·普里克里

5

感谢JanC,我为示例添加了一些修改并在Python3中进行了测试,这对我来说真的很有用。

import paramiko
import getpass

pw = getpass.getpass()

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
#client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def start():
    try :
        client.connect('127.0.0.1', port=22, username='ubuntu', password=pw)
        return True
    except Exception as e:
        #client.close()
        print(e)
        return False

while start():
    key = True
    cmd = input("Command to run: ")
    if cmd == "":
        break
    chan = client.get_transport().open_session()
    print("running '%s'" % cmd)
    chan.exec_command(cmd)
    while key:
        if chan.recv_ready():
            print("recv:\n%s" % chan.recv(4096).decode('ascii'))
        if chan.recv_stderr_ready():
            print("error:\n%s" % chan.recv_stderr(4096).decode('ascii'))
        if chan.exit_status_ready():
            print("exit status: %s" % chan.recv_exit_status())
            key = False
            client.close()
client.close()

我们是否在chan.recv_stderr_ready()中得到任何错误消息-如果有的话?chan.recv_stderr(4096).decode('ascii')是否返回消息文本?
kten

0

就我而言,输出缓冲是问题所在。由于存在缓冲,因此应用程序的输出不会以非阻塞方式输出。您可以在此处找到有关如何在不进行缓冲的情况下打印输出的答案:禁用输出缓冲。简而言之,只需使用-u选项运行python,如下所示:

> python -u script.py

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.