杰瑞科技汇

Python paramiko如何实现SCP文件传输?

Of course! Using Python to handle file transfers via SCP (Secure Copy Protocol) is a common task, especially for automating server administration. The paramiko library is the standard go-to for this in Python.

Here's a comprehensive guide covering everything from the basics to more advanced use cases.

What is Paramiko?

Paramiko is a pure Python (3.6+ and 2.7) implementation of the SSHv2 protocol. It provides both a client and a server-side library, allowing you to create SSH clients that can execute commands and transfer files (using SFTP or SCP) on remote servers.


The Modern Way: Using paramiko.SCPClient

The easiest and most direct way to perform an SCP transfer with Paramiko is by using its built-in SCPClient. It's a high-level wrapper that handles the SCP protocol details for you.

Step 1: Install Paramiko

If you don't have it installed, open your terminal or command prompt and run:

pip install paramiko

Step 2: Basic SCP Upload (Local to Remote)

This is the most common use case: copying a file from your local machine to a remote server.

import paramiko
import os
# --- Configuration ---
HOSTNAME = 'your_server_ip'
USERNAME = 'your_username'
PASSWORD = 'your_password' # Or use a key
LOCAL_PATH = '/path/to/your/local_file.txt'
REMOTE_PATH = '/path/to/your/remote_file.txt' # Can be a filename or a path
# --- Setup SSH Client ---
try:
    # Create an SSH client
    ssh = paramiko.SSHClient()
    # Automatically add the server's host key (this is insecure, see security note below)
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # Connect to the server
    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
    # --- SCP Upload ---
    print(f"Uploading {LOCAL_PATH} to {REMOTE_PATH}...")
    # Create an SCP client
    with paramiko.SCPClient(ssh.get_transport()) as scp:
        # Put the local file to the remote path
        scp.put(LOCAL_PATH, REMOTE_PATH)
    print("Upload complete!")
except paramiko.AuthenticationException:
    print("Authentication failed, please verify your credentials.")
except paramiko.SSHException as e:
    print(f"Unable to establish SSH connection: {e}")
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    # Close the SSH connection
    if 'ssh' in locals() and ssh:
        ssh.close()

Step 3: Basic SCP Download (Remote to Local)

Downloading a file from the remote server to your local machine is just as easy. You use the get() method instead of put().

import paramiko
# --- Configuration ---
HOSTNAME = 'your_server_ip'
USERNAME = 'your_username'
PASSWORD = 'your_password' # Or use a key
REMOTE_PATH = '/path/to/your/remote_file.txt'
LOCAL_PATH = '/path/to/your/local_file.txt' # Can be a filename or a path
# --- Setup SSH Client ---
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
    # --- SCP Download ---
    print(f"Downloading {REMOTE_PATH} to {LOCAL_PATH}...")
    with paramiko.SCPClient(ssh.get_transport()) as scp:
        # Get the remote file to the local path
        scp.get(REMOTE_PATH, LOCAL_PATH)
    print("Download complete!")
except paramiko.AuthenticationException:
    print("Authentication failed, please verify your credentials.")
except paramiko.SSHException as e:
    print(f"Unable to establish SSH connection: {e}")
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    if 'ssh' in locals() and ssh:
        ssh.close()

Important Security Note: AutoAddPolicy

Using ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) is convenient but insecure. It tells Paramiko to automatically accept any host key from a server for the first time, which makes you vulnerable to Man-in-the-Middle (MitM) attacks.

The secure way is to manually add the host key the first time you connect and then check for it on subsequent connections.

# A more secure way to handle host keys
import paramiko
import os
# Path to store the known hosts file
KNOWN_HOSTS_FILE = os.path.expanduser('~/.ssh/known_hosts')
# Load known hosts
known_hosts = paramiko.HostKeys(filename=KNOWN_HOSTS_FILE)
# Get the host key from the server (this happens during the first connection)
# You can get this by running `ssh-keyscan your_server_ip >> ~/.ssh/known_hosts` on your command line
# or by connecting once with a standard SSH client.
HOST_KEY = paramiko.RSAKey(data=b'...') # Paste the actual host key here
# Add the host key to your known hosts
known_hosts.add(HOSTNAME, ssh-rsa, HOST_KEY)
known_hosts.save(KNOWN_HOSTS_FILE)
# Now, create the SSH client with a strict policy
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.RejectPolicy()) # Reject unknown hosts
ssh.load_host_keys(KNOWN_HOSTS_FILE) # Load your known hosts
# Connect
ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
# ... rest of your code

For most automation scripts, AutoAddPolicy is often used for simplicity, but be aware of the security trade-off.


Advanced: Using SSH Keys for Authentication

Using SSH keys is more secure and convenient than passwords. You can pass the key's path directly to the connect method.

import paramiko
# --- Configuration ---
HOSTNAME = 'your_server_ip'
USERNAME = 'your_username'
KEY_PATH = '/path/to/your/private_key' # e.g., ~/.ssh/id_rsa
REMOTE_PATH = '/path/to/your/remote_file.txt'
LOCAL_PATH = '/path/to/your/local_file.txt'
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # Connect using the private key
    # You can also specify a passphrase if your key is encrypted
    ssh.connect(hostname=HOSTNAME, username=USERNAME, key_filename=KEY_PATH)
    with paramiko.SCPClient(ssh.get_transport()) as scp:
        # Example: Upload
        scp.put(LOCAL_PATH, REMOTE_PATH)
        print("Upload complete!")
        # Example: Download
        # scp.get(REMOTE_PATH, LOCAL_PATH)
        # print("Download complete!")
except paramiko.AuthenticationException:
    print("Authentication failed. Is the key authorized on the server?")
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    if 'ssh' in locals() and ssh:
        ssh.close()

Alternative: The Lower-Level SFTP Method

SCP is great for single files, but if you need to work with directories, recursive uploads/downloads, or get more fine-grained control, SFTP (SSH File Transfer Protocol) is a better choice. Paramiko's SFTPClient is more powerful.

Here's how you would do the same upload using SFTP:

import paramiko
import os
# --- Configuration ---
HOSTNAME = 'your_server_ip'
USERNAME = 'your_username'
PASSWORD = 'your_password'
LOCAL_PATH = '/path/to/your/local_file.txt'
REMOTE_PATH = '/path/to/your/remote_file.txt'
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
    # Get an SFTP client from the active SSH transport
    sftp = ssh.open_sftp()
    print(f"Uploading {LOCAL_PATH} to {REMOTE_PATH} using SFTP...")
    # Use sftp.put() to upload a file
    sftp.put(LOCAL_PATH, REMOTE_PATH)
    print("Upload complete!")
    # Don't forget to close the SFTP session
    sftp.close()
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    if 'ssh' in locals() and ssh:
        ssh.close()

SFTP vs. SCP: Quick Guide

Feature paramiko.SCPClient paramiko.SFTPClient
Use Case Simple, fast file transfers. Complex file operations (directories, permissions, listing).
Operations put(), get() put(), get(), mkdir(), remove(), listdir(), stat(), etc.
Recursive No, requires manual handling. Yes, easily with sftp.put_r() and sftp.get_r().
Performance Generally faster for single files. Slightly more overhead, but more versatile.
Permissions Not preserved by default. Preserves file permissions and attributes.

Summary

  • For quick and simple file copies, use paramiko.SCPClient. It's straightforward and does exactly what you expect.
  • For managing files and directories, preserving permissions, or performing complex file operations, use paramiko.SFTPClient. It's more powerful and flexible.
  • Always prefer SSH key authentication over passwords for security and convenience.
  • Be mindful of the security implications of AutoAddPolicy and use RejectPolicy with known hosts for production-level security.
分享:
扫描分享到社交APP
上一篇
下一篇