I am testing this code to read the output of watch
command. I suspect it has to do with how watch
works, but I can't figure out what's wrong or how to work around it:
import paramiko
host = "micro"
# timeout = 2 # Succeeds
timeout = 3 # Hangs!
command = 'ls / && watch -n2 \'touch "f$(date).txt"\''
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(host, password='', look_for_keys=False)
transport = ssh_client.get_transport()
channel = transport.open_session()
channel.get_pty()
channel.settimeout(timeout)
channel.set_combine_stderr(True)
stdout = channel.makefile()
channel.exec_command(command)
for line in stdout: # Hangs here
print(line.strip())
There are several similar issues, some of them quite old (1, 2, and probably others)
This does not happen with other commands that don't use watch
either.
Does someone know what's special about this particular command and / or how to reliably set a timeout for the read operation?
(Tested on Python 3.4.2 and paramiko 1.15.1)
Edit 1: I incorporated channel.set_combine_stderr(True)
as suggested in this answer to a related question, but still didn't do the trick. However, watch
does produce a lot of output, so perhaps the problem is exactly that. In fact, using this command removed the hanging:
command = 'ls / && watch -n2 \'touch "f$(date).txt"\' > /dev/null'
So, probably this question is almost a duplicate of Paramiko ssh die/hang with big output, but makes me wonder if there's really no way to use .readline()
(called through __next__
in this case) and one has to resort to read with a fixed buffer size and assemble the lines manually.