Потеря данных стандартного вывода в Python - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь создать скрипт Python, который запускает скрипт bash на удаленной машине через ssh, а затем анализирует его вывод.Сценарий bash выводит большое количество данных (например, 5 мегабайт текста / 50 тыс. Строк) в стандартный вывод, и здесь возникает проблема - я получаю все данные только в ~ 10% случаев.В других 90% случаев я получаю около 97% от того, что я ожидаю, и похоже, что в конце оно всегда обрезается.Вот как выглядит мой скрипт:

import subprocess
import re
import sys
import paramiko

def run_ssh_command(ip, port, username, password, command):
    ssh = paramiko.SSHClient()    
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())                                                   
    ssh.connect(ip, port, username, password)                                                                   
    stdin, stdout, stderr = ssh.exec_command(command)                                                           
    output = ''                                                                                                 
    while not stdout.channel.exit_status_ready():                                                               
        solo_line = ''                                                                                          
        # Print stdout data when available                                                                      
        if stdout.channel.recv_ready():                                                                         
            # Retrieve the first 1024 bytes                                                                     
            solo_line = stdout.channel.recv(2048).                                                              
            output += solo_line                                                                                 
    ssh.close()                                                                                                 
    return output                                                                                  

result = run_ssh_command(server_ip, server_port, login, password, 'cat /var/log/somefile')
print "result size: ", len(result)                                                                                    

Я почти уверен, что проблема в переполнении какого-то внутреннего буфера, но какой именно и как это исправить?

Спасибо большоемного за любой совет!

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Когда stdout.channel.exit_status_ready() начинает возвращать True, на удаленной стороне все еще может быть много данных, ожидающих отправки.Но вы получаете только еще один кусок размером 2048 байт и выходите.

Вместо проверки состояния выхода вы можете продолжать вызывать recv(2048) до тех пор, пока он не возвратит пустую строку, , что означает , что нетпоступает больше данных:

output = ''
next_chunk = True
while next_chunk:
    next_chunk = stdout.channel.recv(2048)
    output += next_chunk

Но на самом деле вы, вероятно, просто хотите:

output = stdout.read()
0 голосов
/ 11 мая 2018

Могу ли я предложить менее грубый способ выполнения команды через ssh через библиотеку Fabric.Это может выглядеть следующим образом (без указания деталей аутентификации ssh):

from fabric import Connection

with Connection('user@localhost') as con:
    res = con.run('~/test.sh', hide=True)
    lines = res.stdout.split('\n')
    print('{} lines readen.'.format(len(lines)))

с учетом сценария тестирования ~/test.sh

#!/bin/sh
for i in {1..1234}
do
  echo "Line $i"
done

все выходные данные корректно потребляются

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...