2016-03-05 2 views
6

Я хочу написать программу (в Python 3.x на Windows 7), которая выполняет несколько команд на удаленной оболочке через ssh. Посмотрев на функцию exec_command() paramikos, я понял, что он не подходит для моего использования (потому что канал закрывается после выполнения команды), так как команды зависят от переменных окружения (установленных предыдущими командами) и не могут быть объединены в один вызов exec_command(), поскольку они должны выполняться в разное время в программе.Внедрить интерактивную оболочку поверх ssh в Python с помощью Paramiko?

Таким образом, я хочу выполнять команды в одном канале. Следующий вариант я заглянула в осуществляет интерактивную оболочку с помощью paramikos' invoke_shell функция():

ssh = paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(host, username=user, password=psw, port=22) 

channel = ssh.invoke_shell() 

out = channel.recv(9999) 

channel.send('cd mivne_final\n') 
channel.send('ls\n') 

while not channel.recv_ready(): 
    time.sleep(3) 

out = channel.recv(9999) 
print(out.decode("ascii")) 

channel.send('cd ..\n') 
channel.send('cd or_fail\n') 
channel.send('ls\n') 

while not channel.recv_ready(): 
    time.sleep(3) 

out = channel.recv(9999) 
print(out.decode("ascii")) 

channel.send('cd ..\n') 
channel.send('cd simulator\n') 
channel.send('ls\n') 

while not channel.recv_ready(): 
    time.sleep(3) 

out = channel.recv(9999) 
print(out.decode("ascii")) 

ssh.close() 

Есть некоторые проблемы с этим кодом:

  1. первый „печать“ не всегда печати вывод «ls» (иногда он печатается только во второй «печати»).
  2. Первые команды «cd» и «ls» всегда присутствуют на выходе (я получаю их через команду «recv», как часть вывода), тогда как все следующие команды «cd» и «ls» иногда печатаются, а иногда и нет.
  3. Вторая и третья команды 'cd' и 'ls' (при печати) всегда отображаются перед первым выходом 'ls'.

Я смущен этим «недетерминированностью» и очень ценю вашу помощь.

+0

вы получите дополнительную помощь, если заменить тег на меньшее число последователей тегом python, считая, что это действительно код python. удачи. – shellter

+0

Вам нужно использовать 'paramiko'? Мне было гораздо легче работать с «тканью». Вы просто настраиваете переменные 'env', такие как' user', 'password' и' host_string', а затем можете делать различные вещи, такие как use: 'get' для загрузки файлов с удаленного хоста,' put' для отправки файлов и 'run' для выдачи команд. Вы можете цепями таких команд, например: 'run ('cd .. && cd simulator && ls')'. – kchomski

+0

@kchomski, к сожалению, ткань не совместима с python 3.x, поэтому это не вариант. Во всяком случае, из того, что я видел, Fabric - всего лишь обертка для paramiko и не позволяет запускать команды «non-chain» в том же канале. Существует много логики, которые я в конечном счете хочу выполнять между командами оболочки. – misha

ответ

8
import paramiko 
import re 


class ShellHandler: 

    def __init__(self, host, user, psw): 
     self.ssh = paramiko.SSHClient() 
     self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
     self.ssh.connect(host, username=user, password=psw, port=22) 

     channel = self.ssh.invoke_shell() 
     self.stdin = channel.makefile('wb') 
     self.stdout = channel.makefile('r') 

    def __del__(self): 
     self.ssh.close() 

    def execute(self, cmd): 
     """ 

     :param cmd: the command to be executed on the remote computer 
     :examples: execute('ls') 
        execute('finger') 
        execute('cd folder_name') 
     """ 
     cmd = cmd.strip('\n') 
     self.stdin.write(cmd + '\n') 
     finish = 'end of stdOUT buffer. finished with exit status' 
     echo_cmd = 'echo {} $?'.format(finish) 
     self.stdin.write(echo_cmd + '\n') 
     shin = self.stdin 
     self.stdin.flush() 

     shout = [] 
     sherr = [] 
     exit_status = 0 
     for line in self.stdout: 
      if str(line).startswith(cmd) or str(line).startswith(echo_cmd): 
       # up for now filled with shell junk from stdin 
       shout = [] 
      elif str(line).startswith(finish): 
       # our finish command ends with the exit status 
       exit_status = int(str(line).rsplit(maxsplit=1)[1]) 
       if exit_status: 
        # stderr is combined with stdout. 
        # thus, swap sherr with shout in a case of failure. 
        sherr = shout 
        shout = [] 
       break 
      else: 
       # get rid of 'coloring and formatting' special characters 
       shout.append(re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]').sub('', line). 
          replace('\b', '').replace('\r', '')) 

     # first and last lines of shout/sherr contain a prompt 
     if shout and echo_cmd in shout[-1]: 
      shout.pop() 
     if shout and cmd in shout[0]: 
      shout.pop(0) 
     if sherr and echo_cmd in sherr[-1]: 
      sherr.pop() 
     if sherr and cmd in sherr[0]: 
      sherr.pop(0) 

     return shin, shout, sherr 
+0

Как я могу отправить несколько команд в execute()? Я попытался сделать цикл for: для команды в командах: object.execute (команда) для списка команд, но он выполняет только две команды, тогда мне нужно перезапустить оболочку. – magicsword

+0

Можете ли вы показать мне код? – misha

+0

Что делать, если моя команда создает как stdout, так и stderr, и я хочу, чтобы они были отдельными файлами? –

0

Я в основном используя весь код и просто добавив цикл:

commands = ["ls","command2","command3"] 
conn_one = ShellHandler(host,name,pwd) 
for command in commands: 
     conn_one.execute(command) 

Он выполняет две из команд с правильным выходом, но затем он просто сидит там. Мне интересно, нужно ли мне позвонить del где-нибудь в коде.

+0

Может быть, ваша третья команда требует интерактивного ввода от пользователя? Какие команды вы пытаетесь выполнить? – misha

+0

Похоже, он не возвращается. Если у меня есть, out, err = conn_one.execute (command) print (in, out, err), я ничего не получаю. Должен ли я называть ssh.close() в коде, чтобы вернуться в цикл? – magicsword

+0

Нет, вы не должны называть close(). Не могли бы вы сказать, какие именно команды вы пытаетесь выполнить? – misha

 Смежные вопросы

  • Нет связанных вопросов^_^