Paramiko ssh die/hang с голям изход

Опитвам се да архивирам сървър с помощта на Paramiko и ssh, за да извикам команда tar. Когато има ограничен брой файлове, всичко работи добре, но когато папката е голяма, скриптът чака безкрайно. Следният тест ми показва, че проблемът идва от размера на stdout.

Има ли начин да се коригира това и да се изпълни този вид команда?

Случай голям изход:

query = 'cd /;ls -lshAR -h'
chan.exec_command(query)
while not chan.recv_exit_status():
    if chan.recv_ready():
        data = chan.recv(1024)
        while data:
            print data
            data = chan.recv(1024)

    if chan.recv_stderr_ready():
        error_buff = chan.recv_stderr(1024)
        while error_buff:
            print error_buff
            error_buff = chan.recv_stderr(1024)
    exist_status = chan.recv_exit_status()
    if 0 == exist_status:
        break

Резултатът е (не е добре - блокирай - умри??)

2015-07-25 12:57:07,402 --> Query sent

Случай малък изход:

query = 'cd /;ls -lshA -h'
chan.exec_command(query)
while not chan.recv_exit_status():
    if chan.recv_ready():
        data = chan.recv(1024)
        while data:
            print data
            data = chan.recv(1024)

    if chan.recv_stderr_ready():
        error_buff = chan.recv_stderr(1024)
        while error_buff:
            print error_buff
            error_buff = chan.recv_stderr(1024)
    exist_status = chan.recv_exit_status()
    if 0 == exist_status:
        break

Резултатът е (всичко е наред)

2015-07-25 12:55:08,205 --> Query sent
total 172K
4.0K drwxr-x---   2 root psaadm 4.0K Dec 27  2013 archives
   0 -rw-r--r--   1 root root      0 Jul  9 23:49 .autofsck
   0 -rw-r--r--   1 root root      0 Dec 27  2013 .autorelabel
4.0K dr-xr-xr-x   2 root root   4.0K Dec 23  2014 bin
2015-07-25 12:55:08,307 --> Query executed (0.10) 

person Alexis G    schedule 25.07.2015    source източник
comment
Поставете GitHub =› github.com/paramiko/paramiko/issues/563   -  person Alexis G    schedule 26.07.2015


Отговори (2)


Ако ls -R отпечата много грешки (което е вероятно, ако текущият потребител не е root =› няма достъп до всички папки), вашият код в крайна сметка блокира.

Това е така, защото изходният буфер на потока от грешки в крайна сметка се запълва, така че ls спира да работи, чакайки да прочетете потока (изпразнете буфера).

Докато чакате редовният изходен поток да приключи, това, което той никога не прави, тъй като ls ви чака да прочетете потока за грешки, което никога не правите.

Трябва да четете двата потока паралелно (вижте Изпълнете паралелно множество команди в различни SSH сървъри с помощта на Python Paramiko).

Или още по-лесно, използвайте Channel.set_combine_stderr за обединяване на двата потока в един.

person Martin Prikryl    schedule 27.07.2015

прочетете данните, преди да проверите състоянието на изход

channel.recv_exit_status() виси

person hustljian    schedule 23.07.2016