如何在Paramiko的单个会话中执行多个命令? (蟒蛇)

时间:2011-06-01 15:25:03

标签: python paramiko

def exec_command(self, command, bufsize=-1):
    #print "Executing Command: "+command
    chan = self._transport.open_session()
    chan.exec_command(command)
    stdin = chan.makefile('wb', bufsize)
    stdout = chan.makefile('rb', bufsize)
    stderr = chan.makefile_stderr('rb', bufsize)
    return stdin, stdout, stderr

在paramiko中执行命令时,它总是在运行exec_command时重置会话。 我希望能够执行sudo或su,并且当我运行另一个exec_command时仍然具有这些权限。 另一个例子是尝试exec_command(“cd /”)然后再次运行exec_command并让它在根目录中。我知道你可以做像exec_command(“cd /; ls -l”)之类的东西,但我需要在单独的函数调用中完成。

8 个答案:

答案 0 :(得分:36)

非互动用例

这是非交互式示例...它会发送cd tmpls,然后exit

import sys
sys.stderr = open('/dev/null')       # Silence silly warnings from paramiko
import paramiko as pm
sys.stderr = sys.__stderr__
import os

class AllowAllKeys(pm.MissingHostKeyPolicy):
    def missing_host_key(self, client, hostname, key):
        return

HOST = '127.0.0.1'
USER = ''
PASSWORD = ''

client = pm.SSHClient()
client.load_system_host_keys()
client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
client.set_missing_host_key_policy(AllowAllKeys())
client.connect(HOST, username=USER, password=PASSWORD)

channel = client.invoke_shell()
stdin = channel.makefile('wb')
stdout = channel.makefile('rb')

stdin.write('''
cd tmp
ls
exit
''')
print stdout.read()

stdout.close()
stdin.close()
client.close()

互动用例
如果您有一个交互式用例,这个答案将无济于事......我个人会使用pexpectexscript进行交互式会话。

答案 1 :(得分:18)

严格来说,你不能。根据ssh规范:

  

会话是程序的远程执行。该计划可能是一个      shell,应用程序,系统命令或某些内置子系统。

这意味着,一旦命令执行,会话就完成了。您无法在一个会话中执行多个命令。但是,您可以做的是启动远程shell(==一个命令),并通过stdin等与该shell进行交互...(想想执行python脚本与运行交互式解释器)

答案 2 :(得分:12)

尝试创建以\n字符分隔的命令字符串。它对我有用。 对于。例如ssh.exec_command("command_1 \n command_2 \n command_3")

答案 3 :(得分:2)

stat_bin

答案 4 :(得分:2)

您可以使用以下技术运行多个命令。使用分号分隔 Linux 命令 例如:

chan.exec_command("date;ls;free -m")

答案 5 :(得分:1)

您可以通过在客户端上调用shell并发送命令来实现。请参考here
该页面包含python 3.5的代码。我已经修改了一些代码以适用于pythin 2.7。在此处添加代码以供参考

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 close_connection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

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

    def send_shell(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.open_shell()
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()

答案 6 :(得分:0)

您可以执行整个BASH脚本文件以更好地使用,这是该代码:

NULL

这将在远程import paramiko hostname = "192.168.1.101" username = "test" password = "abc123" # initialize the SSH client client = paramiko.SSHClient() # add to known hosts client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(hostname=hostname, username=username, password=password) except: print("[!] Cannot connect to the SSH Server") exit() # read the BASH script content from the file bash_script = open("script.sh").read() # execute the BASH script stdin, stdout, stderr = client.exec_command(bash_script) # read the standard output and print it print(stdout.read().decode()) # print errors if there are any err = stderr.read().decode() if err: print(err) # close the connection client.close() Linux计算机上执行本地script.sh文件。

192.168.1.101(仅作为示例):

script.sh

本教程对此进行了详细说明:How to Execute BASH Commands in a Remote Machine in Python

答案 7 :(得分:0)

如果您希望每个命令对下一个命令产生影响,您应该使用:

stdin, stdout, stderr = client.exec_command("command1;command2;command3")

但在某些情况下,我发现当“;”不起作用,使用“&&”确实起作用。

stdin, stdout, stderr = client.exec_command("command1 && command2 && command3")