子进程Popen无法发送多个命令,命令好像被砍了

问题描述 投票:0回答:1

假设以下 Python 代码,我尝试打开 SSH 连接并保持打开状态并发送多个命令。我知道

communicate
不起作用,因为它会关闭连接,所以我使用
write
,但是
write
似乎会剪切命令之间的空格。

class ReadOutputThread(threading.Thread):
    def __init__(self, file_obj, output_queue):
        super().__init__()
        self.file_obj = file_obj
        self.output_queue = output_queue
        self.daemon = True

    def run(self):
        for line in iter(self.file_obj.readline, ''):
            self.output_queue.put(line.strip())
        self.file_obj.close()

class YourClass:
    def __init__(self, username: str, ssh_key: str, hostname: str="1.1.1.1"):
        self.ssh_session = subprocess.Popen(['ssh', '-T', '-i', ssh_key, '-Y', f'{username}@{hostname}'],
                                            stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                            universal_newlines=True, shell=False)
        self.output_queue = queue.Queue()
        self.stdout_thread = ReadOutputThread(self.ssh_session.stdout, self.output_queue)
        self.stderr_thread = ReadOutputThread(self.ssh_session.stderr, self.output_queue)
        self.stdout_thread.start()
        self.stderr_thread.start()
        self.execute_ssh_cmd(" ") # clean 
        self.ssh_session.stdin.flush()

    def execute_ssh_cmd(self, command):
        try:
            # Debug: Print the command before sending
            print(f"Executing command: {command}")

            # Send the command to the SSH session
            self.ssh_session.stdin.write(command)
            self.ssh_session.stdin.write(" \n")
            self.ssh_session.stdin.flush()  # Ensure data is sent immediately

            # Read the output from the queue
            output_lines = []
            while True:
                try:
                    line = self.output_queue.get(timeout=1)
                    if command.strip() in line.strip():  # Check if the command is part of the line
                        continue
                    output_lines.append(line)
                except queue.Empty:
                    break

            return output_lines
        except Exception as e:
            print("Error writing to SSH session:", e)
            return None

主要区块:

ssh_key_path = ""
hostname = "1.1.1.1"
username = 'user'

your_instance = YourClass(username, ssh_key_path, hostname)
output1 = your_instance.execute_ssh_cmd('ls -l')
print("Final output 1:", output1)

output2 = your_instance.execute_ssh_cmd("pwd")
print("Final output 2:", output2)

输出:

Executing command: ls
Final output 1: [': No such file or directory']
Executing command: pwd
Final output 2: ['/root']

如您所见,

ls -l
命令被删除了。

我尝试使用空格、“”、'' f 字符串格式和其他字符串选项重新输入命令。

python python-3.x multithreading ssh subprocess
1个回答
0
投票

有一个名为 paramiko 的模块,而不是使用子进程。它在 python 标准库本身中可用,不需要单独安装。该模块专门用于处理 python 中的 ssh 连接。并且使用这个模块非常简单。您的多个命令需要创建为一个列表,并迭代该列表以逐个执行。

import paramiko as pm

# Create SSH instance
ssh = pm.SSHClient()

# Automatically add host keys without prompting
ssh.set_missing_host_key_policy(pm.AutoAddPolicy())

# Connect to the SSH server
ssh.connect(hostname='<hostname>', username='<username>', password='<password>')

# keep the connection ON and run multiple commands
try:
    # Open a channel
    ch = ssh.invoke_shell()

    # create a list containg your commands
    cmds = ['cmd1', 'cmd2', 'cmd3']
    for x in cmds:
        # Send the command
        ch.send(x + '\n')

        # Wait for the command to finish 
        while not ch.recv_ready(): pass
            

        # Read and print the command output
        output = ch.recv(1024).decode()
        print(output)

    # Close the channel
    ch.close()
    
except: print("Error writing to SSH session:")

# Close the SSH connection
finally: ssh.close()
    
    
© www.soinside.com 2019 - 2024. All rights reserved.