Skip to content
Advertisement

SFTP using Python Paramiko directly between two remote machines

I have a code where I have to login into a Unix server. After that I have to sftp into some server and have download few files to that Unix server. I am using Pythons’ Paramiko command to login into Unix server. I know by using sftp.get(filepath, localpath), I can sftp files from SFTP server to local machine. However, my problem is I have to sftp those files into Unix server and not into local machine.

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, port, username, password)

sftp = ssh.open_sftp()

stdin,stdout,stderr = ssh.exec_command('some commands')
sftp.get(filepath, localpath)
stdin.write('Password')
stdin.flush()
outlines = stdout.readlines()
resp=''.join(outlines)
print(resp)
sftp.close()

This code is throwing error as it is trying to sftp files in my local machine rather than in unix server.

Advertisement

Answer

SFTP does not allow transfer between two remote servers. So you have to initiate the transfer on one of the servers using any SFTP client available there.


If the servers are common *nix servers, they do have OpenSSH sftp client.

So use SSHClient.exec_command to execute sftp and then use stdin.write to feed sftp commands to it.

Like:

stdin,stdout,stderr = ssh.exec_command('sftp username@hostname')
stdin.write("get filen")
stdin.write("quitn")
stdin.flush()

Though the above will work only, if you have OpenSSH public key authentication setup (or any other input-less authentication) on the server, where you run sftp. With a password authentication, it’s more complicated as OpenSSH does not allow you to provide a password automatically. You should be able to write the password to stdin, if you set get_pty=True:

stdin,stdout,stderr = ssh.exec_command('sftp username@hostname', get_pty=True)
stdin.write(password + "n")
stdin.write("get filen")
stdin.write("quitn")
stdin.flush()

get_pty can bring some undesired side effects, but I believe that in this case it should work without problems.

For alternative approaches, see How to run the sftp command with a password from Bash script?


You can also use any other SFTP client, that you may have available on the servers, like curl or lftp.

Or you can execute python on one of the servers and feed Paramiko/SFTP code to it.


All of the above is true if by “directly” you mean direct network traffic between the two remote machines.

If by “directly” you mean transfer that does not involve (temporary) local file copy of the transferred file, even if it involves network traffic via the local machine (so actual download and upload), then there are other options.

For example, you can use file-like object API of Paramiko to stream the download directly to the upload:

with source_sftp.open(source_remote_path, bufsize=32768) as f:
    dest_sftp.putfo(f, dest_remote_path)

(for the purpose of bufsize=32768, see Reading file opened with Python Paramiko SFTPClient.open method is slow)

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement