子进程 Popen 无法发送多个命令,命令似乎被截断
假设有以下的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字符串格式和其他字符串选项。
1 个回答
1
与其使用 subprocess
,不如试试一个叫做 Paramiko 的模块。你可以通过 pip3 install paramiko
来安装它。这个模块专门用于在 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()