7

I wrote this code in Paramiko:

ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(hostname, username=user, password=passwd, timeout=3)

session = ssh.invoke_shell()
session.send("\n")

session.send("echo step 1\n")
time.sleep(1)

session.send("sleep 30\n")
time.sleep(1)

while not session.recv_ready():
    time.wait(2)

output = session.recv(65535)

session.send("echo step 2\n")
time.sleep(1)

output += session.recv(65535)

I'm trying execute more commands on my Linux server. The problem is my Python code not wait to finish execute command, for example if I'm try to execute sleep 30, the Python not wait 30 seconds for finish execute commands. How can resolve this problem ? I tried with while recv_ready(), but it still does not wait.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
selfmarket.net
  • 139
  • 1
  • 2
  • 7

2 Answers2

11

Use exec_command: http://docs.paramiko.org/en/1.16/api/channel.html

stdin, stdout, stderr = ssh.exec_command("my_long_command --arg 1 --arg 2")

The following code works for me:

from paramiko import SSHClient, AutoAddPolicy
import time
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect('111.111.111.111', username='myname', key_filename='/path/to/my/id_rsa.pub', port=1123)
sleeptime = 0.001
outdata, errdata = '', ''
ssh_transp = ssh.get_transport()
chan = ssh_transp.open_session()
# chan.settimeout(3 * 60 * 60)
chan.setblocking(0)
chan.exec_command('ls -la')
while True:  # monitoring process
    # Reading from output streams
    while chan.recv_ready():
        outdata += chan.recv(1000)
    while chan.recv_stderr_ready():
        errdata += chan.recv_stderr(1000)
    if chan.exit_status_ready():  # If completed
        break
    time.sleep(sleeptime)
retcode = chan.recv_exit_status()
ssh_transp.close()

print(outdata)
print(errdata)

Please note that command history cannot be executed with ssh as is. See example here: https://superuser.com/questions/962001/incorrect-output-of-history-command-of-ssh-how-to-read-the-timestamp-info-corre

Community
  • 1
  • 1
baldr
  • 2,891
  • 11
  • 43
  • 61
  • 1
    i need use invoke_shell because whit exec_command not return output complete – selfmarket.net Dec 09 '15 at 14:49
  • This code can indeed lose some output. You need to test the `exit_status_ready` before reading (but exit only after reading). See for example https://stackoverflow.com/q/66191219/850848. Though see my answer for a simpler solution. – Martin Prikryl Mar 28 '21 at 06:52
3

In case you do not need to read the stdout and stderr separately, you can use way more straightforward code:

stdin, stdout, stderr = ssh_client.exec_command(command)
stdout.channel.set_combine_stderr(True)
output = stdout.readlines()

The readlines reads until the command finishes and returns a complete output.


In case you need the output separately, do not be tempted to remove the set_combine_stderr and call readlines on stdout and stderr separately. That might deadlock. See Paramiko ssh die/hang with big output

For a correct code that reads the outputs separately, see Run multiple commands in different SSH servers in parallel using Python Paramiko.


Obligatory warning: Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992