Bạn có thể lấy mã trả lại SSH bằng cách sử dụng Paramiko như thế nào?


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

Có cách nào để lấy mã trả về lệnh không?

Thật khó để phân tích cú pháp tất cả stdout / stderr và biết liệu lệnh đã kết thúc thành công hay chưa.

Câu trả lời:


51

SSHClient là một lớp trình bao bọc đơn giản xung quanh chức năng cấp thấp hơn trong Paramiko. Các tài liệu API liệt kê một recv_exit_status () phương pháp trên lớp Channel.

Một kịch bản trình diễn rất đơn giản:

$ cat sshtest.py
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: 
$

Thực sự đánh giá cao cho câu trả lời của bạn !! Tôi đã sử dụng nó trong dự án của mình. Cảm ơn rât nhiều. Cho đến nay, tôi có thể sử dụng paramiko thay vì gói lệnh ssh hệ thống trong lập trình với python.
Beyonder

Đó chỉ là thứ tôi tổng hợp lại bằng cách xem xét nguồn SSHClient, vì vậy nó có thể không tối ưu . BTW: nếu điều này làm những gì bạn muốn, bạn có thể muốn "chấp nhận" câu trả lời của tôi.
JanC

Liên kết đã chết Vui lòng cập nhật
bhathiya-perera

3
chan.recv_exit_status () - thật đáng yêu khi điều này chỉ bị treo và không bao giờ quay trở lại. Lời khuyên tuyệt vời.
aaa90210

9
Đây là một giải pháp tồi. Xem câu trả lời của @apdastous 'bên dưới, nó tốt hơn nhiều.
Patrick

282

Một ví dụ dễ dàng hơn nhiều không liên quan đến việc gọi trực tiếp lớp kênh "cấp thấp hơn" (tức là - KHÔNG sử dụng client.get_transport().open_session()lệnh):

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
Điều thú vị về ví dụ này là không chỉ chụp được EXIT (như câu hỏi đặt ra), mà còn chứng minh rằng bạn vẫn có thể nhận được STDOUT và STDERR. Nhiều năm trước, tôi đã bị đánh lừa bởi cơ sở mã ví dụ thiếu máu của Paramiko (không thiếu tôn trọng), và để có được EXIT, tôi đã sử dụng các lệnh gọi vận tải cấp thấp (). vận tải () dường như buộc bạn phải "chọn một" (trong đó có thể không đúng, nhưng thiếu các ví dụ và tài liệu hướng dẫn khiến tôi tin rằng) ...
Scott Prive

5

Cảm ơn JanC, tôi đã thêm một số sửa đổi cho ví dụ và thử nghiệm bằng Python3, nó thực sự hữu ích cho tôi.

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()

chúng tôi có nhận được bất kỳ thông báo lỗi nào không - nếu có - trong chan.recv_stderr_ready () ?. Chan.recv_stderr (4096) .decode ('ascii') này có trả về một tin nhắn văn bản không?
kten

0

Trong trường hợp của tôi, bộ đệm đầu ra là vấn đề. Do bộ đệm, các kết quả đầu ra từ ứng dụng không xuất hiện theo cách không bị chặn. Bạn có thể tìm thấy câu trả lời về cách in đầu ra mà không có bộ đệm tại đây: Tắt bộ đệm đầu ra . Tóm lại, chỉ cần chạy python với tùy chọn -u như sau:

> python -u script.py

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.