How To Use Python Paramiko Module To Implements SFTP File Upload, Download And Remote Command Execution

Python Paramiko module is a Python-based SSH remote secure connection module, it is used for SSH remote command execution, file transfer, and other functions. The Paramiko module is not a python built-in module, so you need to run the command pip3 install Paramiko to install it manually.

1. Install Python Paramiko Module.

$ pip3 install Paramiko
Collecting Paramiko
  Downloading paramiko-2.7.2-py2.py3-none-any.whl (206 kB)
     |████████████████████████████████| 206 kB 215 kB/s 
Collecting cryptography>=2.5
  Downloading cryptography-3.3.1-cp36-abi3-macosx_10_10_x86_64.whl (1.8 MB)
     |████████████████████████████████| 1.8 MB 45 kB/s 
Collecting pynacl>=1.0.1
  Downloading PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl (380 kB)
     |████████████████████████████████| 380 kB 41 kB/s 
Collecting bcrypt>=3.1.3
  Downloading bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl (31 kB)
Collecting six>=1.4.1
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Collecting cffi>=1.12
  Downloading cffi-1.14.4-cp39-cp39-macosx_10_9_x86_64.whl (177 kB)
     |████████████████████████████████| 177 kB 26 kB/s 
Collecting pycparser
  Downloading pycparser-2.20-py2.py3-none-any.whl (112 kB)
     |████████████████████████████████| 112 kB 22 kB/s 
Installing collected packages: six, pycparser, cffi, cryptography, pynacl, bcrypt, Paramiko
Successfully installed Paramiko-2.7.2 bcrypt-3.2.0 cffi-1.14.4 cryptography-3.3.1 pycparser-2.20 pynacl-1.4.0 six-1.15.0

2. Use Python Paramiko To Upload File By SFTP Source Code.

import paramiko

"""
    Upload file, can not upload directory.
    :param host: sftp server host name or ip.
    :param port: sftp server listening port nubmer.
    :param user: sftp user name
    :param password: sftp account password
    :param server_path: remote server file path,for example:/root/test/test.txt
    :param local_path: local file path (c:/test.txt)
    :param timeout: upload connection timeout number ( an integer value, default is 10 )
    :return: bool
"""
def sftp_upload_file(host, port, user, password, server_path, local_path, timeout=10):
    try:
        # create transport object.
        t = paramiko.Transport((host, port))
        
        # set connection timeout number.
        t.banner_timeout = timeout
        
        # connect to remote sftp server
        t.connect(username=user, password=password)
        
        # get the SFTP client object.
        sftp = paramiko.SFTPClient.from_transport(t)
        
        # upload local file to remote server path.
        sftp.put(local_path, server_path)

        # close the connection.
        t.close()
        return True
    except Exception as e:
        print(e)
        return False

3. Use Python Paramiko To Download File By SFTP Source Code.

"""
   Download file, do not support download directory.
   :param host: SFTP server host name or ip address.
   :param port: SFTP server port number, the default port number is 22.
   :param user: SFTP server user name.
   :param password: SFTP server password.
   :param server_path: Download file path on server side.
   :param local_path: Local file path, download file saved as.
   :param timeout: Connection time out must be an integer number, defautl value is 10.
   :return: bool
"""

def sftp_down_file(host, port=22, user, password, server_path, local_path, timeout=10):

    try:
        # Create the transport object
        t = paramiko.Transport((host,port))

        # Set connection timeout value.
        t.banner_timeout = timeout

        # Connect to the SFTP server use username and password.
        t.connect(username=user,password=password)

        # Get SFTP client object.
        sftp = paramiko.SFTPClient.from_transport(t)

        # Download file from server side and save it to local path.
        sftp.get(server_path, local_path)

        # Close SFTP server connection.
        t.close()
        return True
    except Exception as e:
        print(e)
        return False

4. Use Python Paramiko To Implement Remote Command Execution.

"""
   Use SSH to connect to remote server and execute command
   :param host: server host name or ip address
   :param user: user name
   :param password: password
   :param cmd: the command to execute.
   :param seconds: execution timeout time, should be an integer number.
   :return: dict
"""

def ssh_exec_command(host,user,password, cmd,timeout=10):

    # return result is a python dictionary object. 'status' - value is 1 means success. 'data' - the command output data.
    result = {'status': 1, 'data': None}  
    try:
        # Create a new SSHClient instance.
        ssh = paramiko.SSHClient()  

        # Set connection timeout value.
        ssh.banner_timeout = timeout

        # Set host key, if no relevant information is stored in "known_hosts", the default behavior of SSHClient is to deny the connection, it will prompt yes/no.
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # Connect to a remote server with a timeout of 1 second.
        ssh.connect(host, 22, user, password, timeout=timeout)  

        # Execute the command and return a list.
        stdin, stdout, stderr = ssh.exec_command(cmd,get_pty=True,timeout=timeout)  
        
        # Get execution result, the readlines() method will return a list object.
        out = stdout.readlines()    
       
        # Command execution status, 0 means success,1 means fail.
        channel = stdout.channel
        status = channel.recv_exit_status()

        # Close ssh connection.
        ssh.close()

        # Modify the returned result object.
        result['status'] = status
        result['data'] = out

        # return result to outer invoker.
        return result
    except Exception as e:
        print(e)
        print("Error, connection to server or command execution timeout!!! ip: {} command: {}".format(ip,cmd))
        return False

5. How To Fix EllipticCurvePublicKey.public_bytes Error.

When you run the above source code, you may encounter the below error. This is because Paramiko(2.4.2) relies on cryptography module, and the latest cryptography(2.5) has some deprecated APIs.

Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding.

So uninstall cryptography(2.5) and install cryptography(2.4.2) will fix this error.

# Uninstall current cryptography 2.5 version.
pip uninstall cryptography

# Install cryptography 2.4.2 version.
pip install cryptography==2.4.2

6. How To Fix Error reading SSH protocol banner Error.

To solve this problem, we need to increase the response waiting time of python Paramiko module. Modifying the value of self.banner_timeout in the paramiko/transport.py file to 300 or some other longer value will solve this problem.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.