How do you execute multiple commands in a single session in Paramiko? (Python)

前端 未结 6 1183
礼貌的吻别
礼貌的吻别 2020-11-27 13:50
def exec_command(self, command, bufsize=-1):
    #print \"Executing Command: \"+command
    chan = self._transport.open_session()
    chan.exec_command(command)
             


        
相关标签:
6条回答
  • 2020-11-27 14:02

    You can do that by invoking shell on the client and sending commands. Please refer here
    The page has code for python 3.5. I have modified the code a bit to work for pythin 2.7. Adding code here for reference

    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()
    
    0 讨论(0)
  • 2020-11-27 14:06

    Non-Interactive use cases

    This is a non-interactive example... it sends cd tmp, ls and then 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()
    

    Interactive use cases
    If you have an interactive use case , this answer won't help... I personally would use pexpect or exscript for interactive sessions.

    0 讨论(0)
  • 2020-11-27 14:06

    Try creating a command string separated by \n character. It worked for me. For. e.g. ssh.exec_command("command_1 \n command_2 \n command_3")

    0 讨论(0)
  • 2020-11-27 14:08
    cmd = 'ls /home/dir'
    self.ssh_stdin, self.ssh_stdout, self.ssh_stderr = self.ssh.exec_command(cmd)
    print self.ssh_stdout.read()
    cmd2 = 'cat /home/dir/test.log'
    self.ssh_stdin2, self.ssh_stdout2, self.ssh_stderr2 = self.ssh.exec_command(cmd2)
    print self.ssh_stdout2.read()
    
    0 讨论(0)
  • 2020-11-27 14:23

    Strictly speaking, you can't. According to the ssh spec:

    A session is a remote execution of a program. The program may be a shell, an application, a system command, or some built-in subsystem.

    This means that, once the command has executed, the session is finished. You cannot execute multiple commands in one session. What you CAN do, however, is starting a remote shell (== one command), and interact with that shell through stdin etc... (think of executing a python script vs. running the interactive interpreter)

    0 讨论(0)
  • 2020-11-27 14:23

    You can execute an entire BASH script file for better use, here is the code for that:

    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()
    

    This will execute the local script.sh file on the remote 192.168.1.101 Linux machine.

    script.sh (just an example):

    cd Desktop
    mkdir test_folder
    cd test_folder
    echo "$PATH" > path.txt
    

    This tutorial explains this in detail: How to Execute BASH Commands in a Remote Machine in Python.

    0 讨论(0)
提交回复
热议问题