Как вы выполняете несколько команд за один сеанс в Paramiko?(Python) - PullRequest
36 голосов
/ 01 июня 2011
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"), но мне нужно сделать это в отдельных вызовах функций.

Ответы [ 5 ]

36 голосов
/ 01 июня 2011

Неинтерактивные варианты использования

Это неинтерактивный пример ... он отправляет cd tmp, ls, а затем 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()

Интерактивные варианты использования
Если у вас есть интерактивный вариант использования, этот ответ не поможет ... Я лично использовал бы pexpect или exscriptдля интерактивных сессий.

18 голосов
/ 01 июня 2011

Строго говоря, вы не можете.Согласно спецификации ssh:

Сеанс - это удаленное выполнение программы.Программа может быть оболочкой, приложением, системной командой или некоторой встроенной подсистемой.

Это означает, что после выполнения команды сеанс завершается.Вы не можете выполнить несколько команд за один сеанс.Однако то, что вы МОЖЕТЕ сделать, - это запустить удаленную оболочку (== одну команду) и взаимодействовать с этой оболочкой через stdin и т. Д. (Подумайте о выполнении сценария на языке python вместо запуска интерактивного интерпретатора)

12 голосов
/ 22 июля 2015

Попробуйте создать командную строку, разделенную \n символом.Это сработало для меня.За.например, ssh.exec_command("command_1 \n command_2 \n command_3")

2 голосов
/ 09 октября 2015
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()
1 голос
/ 22 января 2018

Вы можете сделать это, вызвав shell на клиенте и отправив команды.Пожалуйста, обратитесь здесь
На странице есть код для 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()
...