2014-01-13 6 views
6

저는 Paramiko를 사용하여 많은 명령을 실행하고 추가 분석을 위해 결과를 수집합니다. 가끔씩 첫 번째 명령의 결과는 시간 안에 완전히 되돌아 와서 두 번째 명령의 출력으로 끝납니다.Paramiko : 명령간에 데이터가 수신되도록하는 방법

이 문제를 설명하기 위해 recv_ready를 사용하려고 시도하고 있지만 제대로 작동하지 않아 내가 잘못하고 있다고 가정합니다. 관련 코드는 다음과 같습니다.

pause = 1 

def issue_command(chan, pause, cmd): 
    # send commands and return results 
    chan.send(cmd + '\n') 
    while not chan.recv_ready(): 
     time.sleep(pause) 
    data = chan.recv(99999) 

ssh = paramiko.SSHClient() 
ssh.load_system_host_keys() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
chan = ssh.connect(host, port=22, username=username, password=password, timeout=3,) 

resp1 = issue_command(chan, pause, cmd1) 
resp2 = issue_command(chan, pause, cmd2) 

이러한 명령의 출력은 상대적으로 적습니다 (몇 문장). 일시 중지를 늘리면 문제가 해결되지만 이상적인 해결책은 아닙니다.

모든 제안이나 권장 사항에 감사드립니다.

답변

8

transport을 직접 사용하고 각 명령에 대해 새 채널을 만듭니다. 출력을 사용할 때 명령 목록을 각위한 새로운 채널을 산란 각 짱의 recv_ready를 폴링하고, 자신의 표준 출력/표준 에러를 빨아하는 것

def issue_command(transport, pause, command): 
    chan = transport.open_session() 
    chan.exec_command(command) 

    buff_size = 1024 
    stdout = "" 
    stderr = "" 

    while not chan.exit_status_ready(): 
     time.sleep(pause) 
     if chan.recv_ready(): 
      stdout += chan.recv(buff_size) 

     if chan.recv_stderr_ready(): 
      stderr += chan.recv_stderr(buff_size) 

    exit_status = chan.recv_exit_status() 
    # Need to gobble up any remaining output after program terminates... 
    while chan.recv_ready(): 
     stdout += chan.recv(buff_size) 

    while chan.recv_stderr_ready(): 
     stderr += chan.recv_stderr(buff_size) 

    return exit_status, stdout, stderr 

ssh = paramiko.SSHClient() 
ssh.load_system_host_keys() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(host, port=22, username=username, password=password, timeout=3,) 
transport = ssh.get_transport() 
pause = 1  

resp1 = issue_command(transport, pause, cmd1) 
resp2 = issue_command(transport, pause, cmd2) 

더 좋은 방법 : 그럼 당신은 같은 것을 사용할 수 있습니다 . :-)

편집 : 명령을 종료 한 후 데이터를 읽는 중 잠재적 인 문제가 있습니다. 의견을 참조하십시오!

+0

나는 이것이 옳은 길에 있다고 생각합니다. – KMS

+0

나는 이것이 옳은 길로 나를 데려 갔다고 생각한다. 고맙습니다. 발행 된 각 명령에 대해 새 연결 및 전송을 만들어서 ssh.connect 및 transport 문을 issue_command 함수로 옮길 필요가있었습니다. 결과는 지금까지 좋았습니다. – KMS

+2

이 솔루션은 작동 할 수는 있지만 총알 방지는 아닙니다. 채널 스트림이 닫히기 전에'recv_ready()'가'False '를 반환 할 수 있기 때문에 모든 데이터가 수신되기 전에 종료 될 수 있습니다. 추가 정보 : http://stackoverflow.com/a/39019370/2075565 – Ivan