Подтвердить что ты не робот

Как выполнить несколько команд за один сеанс в Paramiko? (Python)

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" ), но мне нужно сделать это в отдельных вызовах функций.

4b9b3361

Ответ 1

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

Это неинтерактивный пример... он отправляет 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 для интерактивных сеансов.

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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