【问题标题】:Python running multiple commands via ssh and paramiko, get output from one off themPython 通过 ssh 和 paramiko 运行多个命令,从其中一个获取输出
【发布时间】:2021-11-10 09:20:16
【问题描述】:

这是我想要模仿的:

打开两个 PuTTY 窗口并使用 auth 连接到同一台机器。 在窗口 1 中运行一个命令(我们称之为 CHECK),等待我在窗口 2 中运行的另一个命令(我们称之为 TEST)。 CHECK 评估 TEST 并在 TEST 完成后显示它通过了 CHECK。然后我必须 CTRL+C 退出它。

我正在尝试跳过这些登录并通过 GUI 完成,所以我只需按下一个按钮。

我尝试通过子进程调用 TEST 脚本并运行它,但 CHECK 只是坐在那里永远等待。反过来我也试过了,结果一样。

如果 stdin、stdout、stderr 在 CHECK 中没有显示任何内容?

我想我可以等待然后关闭 CHECK,因为 TEST 会运行一段时间,但我需要 CHECK 的输出来查看它是否通过。

顺便说一句,我使用 tkinter 作为 GUI 的一个按钮,当我运行 CHECK 部分时,它会冻结并变得无响应。有没有办法解决这个问题?

到目前为止我的代码:

import subprocess
import tkinter as tk
import paramiko

hostname = "xxx.xxx.xxx.xxx"
username = "xxx"
password = "xxx"

def initiate():
    subprocess.call(["python", "ljustest2.py"])

    client1 = paramiko.SSHClient()

    client1.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client1.connect(hostname=hostname, username=username, password=password)
        print('Connect 1')
    except:
        print("[!] Cannot connect to the SSH Server")
        exit()

    commands = ['mosquitto_sub -t "/test/#" -v']

    for command in commands:
        print("="*40, command, "="*40)
        stdin, stdout, stderr = client1.exec_command(command)
        print(stdout.read().decode())
        err = stderr.read().decode()
        if err:
            print(err)


window = tk.Tk()
window.title("MQTT")
window.geometry("300x300")
window.resizable(False, False)

window.rowconfigure([0], minsize=300, weight=0)
window.columnconfigure([0], minsize=300, weight=0)

btn_abl = tk.Button(window, text="Start", command = initiate)
btn_abl.grid(row=0, column=0, sticky="nsew")

window.mainloop()

ljustest2.py 的代码:

import paramiko

hostname = "xxx.xxx.xxx.xxx"
username = "xxx"
password = "xxx"

client2 = paramiko.SSHClient()

client2.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    client2.connect(hostname=hostname, username=username, password=password)
    print('Connect 2')
except:
    print("[!] Cannot connect to the SSH Server")
    exit()
    
commands = ['mosquitto_pub -t "/test/start" -m \'{"type": "phcomtest", "cycles": 3}\'']

for command in commands:
    print("="*40, command, "="*40)
    stdin, stdout, stderr = client2.exec_command(command)
    print(stdout.read().decode())
    err = stderr.read().decode()
    if err:
        print(err)

【问题讨论】:

  • 是的,我刚刚提到我之前必须这样做,我试图用 python 来模拟它。我认为这可能是相关的,以及如何通过 paramiko 获得与 PuTTY 相同的输出。但是,是的,2 个 ssh 会话 :)
  • 它询问我的密码并继续使用 CHECK 并输出通过的部分。这很好,但我希望能够跳过身份验证,这就是我使用 paramiko 的原因。如果我能得到它通过的输出。我已经搜索了 paramiko api,但找不到我要找的东西...感谢您的帮助!

标签: python subprocess paramiko


【解决方案1】:

我终于明白了。

我看到了这个帖子:Paramiko and exec_command - killing remote process?

稍微修改了一下,中提琴!奇迹般有效!感谢所有回复。

import tkinter as tk
import paramiko
import select

hostname = "xxx.xxx.xxx.xxx"
username = "xxx"
password = "xxx"

def initiate():
    client1 = paramiko.SSHClient()

    client1.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        client1.connect(hostname=hostname, username=username, password=password)
        print('Connect 1')
    except:
        print("[!] Cannot connect to the SSH Server")
        exit()
        
    command = 'mosquitto_pub -t "/test/start" -m \'{"type": "phcomtest", "cycles": 3}\''

    print("="*40, 'Mosquitto TEST ', "="*40)
    client1.exec_command(command)



    client2 = paramiko.SSHClient()

    client2.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client2.connect(hostname=hostname, username=username, password=password)
        print('Connect 2')
    except:
        print("[!] Cannot connect to the SSH Server")
        exit()
    transport = client2.get_transport()
    channel = transport.open_session()
    channel.get_pty()

    commands = ['mosquitto_sub -t "/test/#" -v']

    for command in commands:
        print("="*40,  'Mosquitto CHECK', "="*40)
        channel.exec_command(command)
        while True:
            try:
                rl, wl, xl = select.select([channel],[],[],0.0)
                if len(rl) > 0:
                    if str(channel.recv(1024))[2:-5] == '/test/complete passed':
                        client1.close()
                        client2.close()
                        channel.close()
                        exit(0)
                    print(str(channel.recv(1024))[2:-5])
            except KeyboardInterrupt:
                print("Caught control-C")
                client1.close()
                client2.close()
                channel.close()
                exit(0)


window = tk.Tk()
window.title("Mosuitto")
window.geometry("300x300")
window.resizable(False, False)


btn_abl = tk.Button(window, text="Start", command = initiate)
btn_abl.place(x=0, y=0, width=300, height=300)

window.mainloop()

【讨论】:

    最近更新 更多