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