How can I execute a command on a remote server in Python and pipe the stdout to a local command? To do ssh host 'echo test' | cat
in Python, I have tried
import paramiko
import subprocess
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('host', username='user')
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('echo test')
proc = subprocess.Popen(['cat'], stdin=ssh_stdout)
outs, errs = proc.communicate()
print(outs)
but I get the exception 'ChannelFile' object has no attribute 'fileno'
. It seems that Paramiko's ssh_stdout
can't be used as stdin with subprocess.Popen.
Yes,
subprocess
cannot redirect output on a "fake" file. It needsfileno
which is defined only with "real" files (io.BytesIO()
doesn't have it either).I would do it manually like the following code demonstrates:
so you're telling
Popen
that the input is a pipe, and then you write ssh output data in the pipe (and close it socat
knows when it must end)According to the docs, the
ChannelFile
object does not directly wrap an actual file descriptor (because of the decryption and demuxing and so on that occurs within SSH), so it can't directly be used as a file descriptor forPopen
.Something like
might work; i.e. you read the SSH stdout stream manually, up to 4096 bytes at a time, and write them to the subprocess's stdin pipe. I'm not sure how the code above will behave when the remote command exits, though, so YMMV.