Paramiko - Python SSH - 单通道下多个命令

0 投票
4 回答
5079 浏览
提问于 2025-04-17 20:35

我看过其他关于这个问题的StackOverflow帖子,那些都是比较旧的内容,我想了解最新的情况。

在Paramiko中,是否可以通过一个通道发送多个命令?还是说现在仍然不行?

如果可以的话,有没有其他的库可以做到这一点。

举个例子,自动化配置Cisco路由器:用户需要先输入“Config t”,才能输入其他命令。目前在Paramiko中是做不到的。

谢谢。

4 个回答

0

你可以查看我的回答,链接在这里,或者看看这个页面

import threading, paramiko

strdata=''
fulldata=''

class ssh:
    shell = None
    client = None
    transport = None

    def __init__(self, address, username, password):
        print("Connecting to server on ip", str(address) + ".")
        self.client = paramiko.client.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
        self.client.connect(address, username=username, password=password, look_for_keys=False)
        self.transport = paramiko.Transport((address, 22))
        self.transport.connect(username=username, password=password)

        thread = threading.Thread(target=self.process)
        thread.daemon = True
        thread.start()

    def closeConnection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

    def openShell(self):
        self.shell = self.client.invoke_shell()

    def sendShell(self, command):
        if(self.shell):
            self.shell.send(command + "\n")
        else:
            print("Shell not opened.")

    def process(self):
        global strdata, fulldata
        while True:
            # Print data when available
            if self.shell is not None and self.shell.recv_ready():
                alldata = self.shell.recv(1024)
                while self.shell.recv_ready():
                    alldata += self.shell.recv(1024)
                strdata = strdata + str(alldata)
                fulldata = fulldata + str(alldata)
                strdata = self.print_lines(strdata) # print all received data except last line

    def print_lines(self, data):
        last_line = data
        if '\n' in data:
            lines = data.splitlines()
            for i in range(0, len(lines)-1):
                print(lines[i])
            last_line = lines[len(lines) - 1]
            if data.endswith('\n'):
                print(last_line)
                last_line = ''
        return last_line


sshUsername = "SSH USERNAME"
sshPassword = "SSH PASSWORD"
sshServer = "SSH SERVER ADDRESS"


connection = ssh(sshServer, sshUsername, sshPassword)
connection.openShell()
connection.send_shell('cmd1')
connection.send_shell('cmd2')
connection.send_shell('cmd3')
time.sleep(10)
print(strdata)    # print the last line of received data
print('==========================')
print(fulldata)   # This contains the complete data received.
print('==========================')
connection.close_connection()
0

看看这个parallel-ssh吧:

from pssh.pssh2_client import ParallelSSHClient

cmds = ['my cmd1', 'my cmd2']
hosts = ['myhost']
client = ParallelSSHClient(hosts)

for cmd in cmds:
    output = client.run_command(cmd)
    # Wait for completion
    client.join(output)

它可以让你用一个客户端,在同一个SSH连接上同时发送多个命令,还可以选择在多个主机上并行执行,而且不会让你等着。

0

如果你打算使用paramiko API里的exec_command()方法,你会发现每次只能发送一个命令。命令执行完后,连接就会关闭。

下面是Paramiko API文档中的一段摘录:

exec_command(self, command) 源代码 在服务器上执行一个命令。如果服务器允许,连接将直接连接到正在执行的命令的标准输入、标准输出和标准错误。

当命令执行完毕后,连接会关闭,不能再使用。如果你想执行另一个命令,就必须重新打开一个连接。

不过,由于传输也是一种套接字,你可以不使用exec_command()方法,而是通过基本的套接字编程来发送命令。

如果你有一组固定的命令,可以使用pexpect和exscript,这样你就可以从文件中读取一组命令并通过连接发送它们。

撰写回答