Paramiko: how to ensure the receipt of data between teams

I use Paramiko to issue several commands and collect results for further analysis. From time to time, the results of the first team are marked as fully returned in time and end on the output for the second team.

I am trying to use recv_ready to account for this, but it does not work, so I assume that I am doing something wrong. Here is the relevant code:

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) 

The output for these teams is relatively small (a few suggestions). Increasing the pause is likely to solve the problem, but is not an ideal solution.

Any suggestions or recommendations would be appreciated.

+6
source share
1 answer

I would use transport directly and create a new channel for each command. Then you can use something like:

 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) 

An even better way is to take a list of commands and create a new channel for each, poll each chan recv_ready and throw them stdout / stderr when the output is available. :-)

Edit: There are potential problems reading the data after the command exits. Please check out the comments!

+8
source

All Articles