Paramiko ssh 死/挂,输出大

Ale*_*s G 5 python ssh paramiko

我尝试使用 Paramiko 和 ssh 来备份服务器以调用tar命令。当文件数量有限时,一切正常,但当文件夹很大时,脚本会无休止地等待。下面的测试告诉我问题出在标准输出的大小上。

有没有办法纠正它并执行这种命令?

案例大输出:

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
Run Code Online (Sandbox Code Playgroud)

结果是(不行 - 阻止 - 死??)

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
Run Code Online (Sandbox Code Playgroud)

案例小输出:

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
Run Code Online (Sandbox Code Playgroud)

结果是(一切正常)

2015-07-25 12:57:07,402 --> Query sent
Run Code Online (Sandbox Code Playgroud)

Mar*_*ryl 4

如果ls -R打印大量错误输出(如果当前用户不是root=>无权访问所有文件夹,则可能发生这种情况),您的代码最终会死锁

这是因为,错误流的输出缓冲区最终被填满,因此停止ls工作,等待您读取流(清空缓冲区)。

当您等待常规输出流完成时,它永远不会做的事情,当您ls等待您读取错误流时,您永远不会做的事情。

您必须并行读取两个流(请参阅使用 Python Paramiko 在不同的 SSH 服务器中并行运行多个命令)。

或者更简单的是,使用Channel.set_combine_stderr将两个流合并为一个。