杰瑞科技汇

python远程连接linux服务器

SSH

SSH 是一种加密的网络协议,用于在不安全的网络中为网络服务提供安全的远程登录和其他安全网络服务,当你的 Python 脚本需要连接到 Linux 服务器时,本质上就是通过 SSH 协议发送命令。


使用 paramiko 库(纯 Python 实现,最常用)

paramiko 是一个 Python 实现的 SSHv2 协议库,它不依赖任何外部库,非常适合在 Python 脚本中进行 SSH 操作,这是学习和开发 SSH 应用的首选。

安装 paramiko

pip install paramiko

基本用法:执行单条命令

这是最核心的功能,在远程服务器上执行一个命令并获取其输出。

import paramiko
# --- 1. 创建 SSHClient 对象 ---
ssh = paramiko.SSHClient()
# --- 2. 自动添加主机密钥 (不推荐用于生产环境) ---
# 第一次连接时,服务器的 SSH 密钥是未知的,这会引发一个未知主机异常。
# set_missing_host_key_policy 会自动接受并保存密钥,方便但存在安全风险。
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# --- 3. 连接服务器 ---
# 请替换为你的服务器 IP、用户名和密码
hostname = "your_server_ip"
port = 22
username = "your_username"
password = "your_password"
try:
    ssh.connect(hostname, port=port, username=username, password=password)
    print("SSH 连接成功!")
    # --- 4. 执行命令 ---
    # 'ls -l' 是一个示例命令
    command = "ls -l /home"
    stdin, stdout, stderr = ssh.exec_command(command)
    # --- 5. 获取命令输出 ---
    # stdout 是标准输出
    output = stdout.read().decode('utf-8')
    # stderr 是标准错误
    error = stderr.read().decode('utf-8')
    if error:
        print(f"命令执行出错: {error}")
    else:
        print(f"命令 '{command}' 的输出:\n{output}")
except paramiko.AuthenticationException:
    print("认证失败,请检查用户名和密码。")
except paramiko.SSHException as e:
    print(f"SSH 连接或命令执行出错: {e}")
except Exception as e:
    print(f"发生未知错误: {e}")
finally:
    # --- 6. 关闭连接 ---
    ssh.close()
    print("SSH 连接已关闭。")

高级用法:上传/下载文件

paramiko 也可以像使用 scp 命令一样传输文件。

import paramiko
# ... (连接部分的代码与上面相同) ...
# ssh.connect(...)
try:
    # --- 上传文件 ---
    local_path = 'local_file.txt'
    remote_path = '/home/your_username/remote_file.txt'
    sftp = ssh.open_sftp() # 打开 SFTP 客户端
    print(f"正在上传 {local_path} 到 {remote_path}...")
    sftp.put(local_path, remote_path)
    print("文件上传成功!")
    # --- 下载文件 ---
    download_remote_path = '/home/your_username/remote_file.txt'
    download_local_path = 'downloaded_file.txt'
    print(f"正在从 {download_remote_path} 下载到 {download_local_path}...")
    sftp.get(download_remote_path, download_local_path)
    print("文件下载成功!")
    sftp.close()
except Exception as e:
    print(f"文件传输出错: {e}")
finally:
    ssh.close()

使用 fabric 库(高级封装,更便捷)

fabric 是在 paramiko 基础上构建的一个高级库,旨在简化常见的 SSH 操作,如执行命令、上传下载文件等,它的 API 更简洁,特别适合编写部署和自动化脚本。

安装 fabric

pip install fabric

基本用法

fabric 通常通过一个 fabfile.py 文件来定义任务。

# fabfile.py
from fabric import Connection, Config
# 定义一个服务器配置
# 可以将密码或密钥路径放在配置文件中,而不是硬编码
config = Config(overrides={'sudo': {'password': 'your_sudo_password'}})
# 使用上下文管理器,连接会自动关闭
def list_home_directory(c):
    """列出服务器上 /home 目录的内容"""
    print(f"正在连接到 {c.host}...")
    # c.run() 会执行命令并打印输出
    c.run("ls -l /home", hide='out') # hide='out' 可以捕获输出而不打印
    # 也可以获取输出结果
    result = c.run("whoami", hide=True)
    print(f"当前用户是: {result.stdout.strip()}")
def upload_file(c):
    """上传一个文件到服务器"""
    local_file = 'local_file.txt'
    remote_file = '/tmp/fabric_uploaded.txt'
    print(f"正在上传 {local_file} 到 {c.host}:{remote_file}")
    # c.put() 用于上传
    c.put(local_file, remote_file)
    print("上传完成!")
# --- 如何运行这些任务 ---
# 在终端中执行:
# fab -H your_server_ip list_home_directory
# fab -H your_server_ip upload_file
# 或者使用用户名: fab -H user@your_server_ip list_home_directory

优点:

  • 代码更简洁,c.run()ssh.exec_command() 更直观。
  • 内置了对“上下文管理器”的支持,连接管理更自动化。
  • invoke 库无缝集成,任务管理更强大。

使用 subprocess 模块(调用系统命令)

如果你的脚本运行在 Linux 或 macOS 上,最简单粗暴的方法是直接调用系统的 ssh 命令。

基本用法

import subprocess
# 构建命令
# 注意:密码直接写在命令中是不安全的,通常建议使用 SSH 密钥对
command = f"ssh your_username@your_server_ip 'ls -l /home'"
try:
    # 执行命令
    # shell=True 允许命令通过系统 shell 执行
    result = subprocess.run(command, shell=True, check=True, 
                            capture_output=True, text=True)
    # 获取输出
    print("命令执行成功!")
    print("标准输出:")
    print(result.stdout)
except subprocess.CalledProcessError as e:
    print(f"命令执行失败,返回码: {e.returncode}")
    print("标准错误:")
    print(e.stderr)

缺点:

  • 安全性差:如果需要密码,会以明文形式暴露在命令行或脚本中,非常危险。强烈推荐使用 SSH 密钥对进行无密码登录
  • 平台依赖:此方法依赖于系统是否安装了 ssh 客户端。
  • 功能有限:难以处理复杂的交互(如 sudo 输入密码),错误处理和输出解析不如 paramiko 灵活。

安全最佳实践:使用 SSH 密钥对

无论使用哪种方法,都强烈建议使用 SSH 密钥对进行认证,而不是密码,这更安全、更方便。

在本地机器生成密钥对(如果没有)

# 一路回车即可,通常会在 ~/.ssh/ 目录下生成 id_rsa (私钥) 和 id_rsa.pub (公钥)
ssh-keygen -t rsa -b 4096

将公钥复制到远程服务器

# 将本地的 id_rsa.pub 公钥内容追加到远程服务器的 ~/.ssh/authorized_keys 文件中
ssh-copy-id your_username@your_server_ip
# 系统会提示你输入一次密码,之后就可以无密码登录了

在 Python 中使用密钥对连接

paramikofabric 都可以轻松地使用私钥文件进行连接。

paramiko 示例:

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 使用私钥文件连接
private_key_path = os.path.expanduser('~/.ssh/id_rsa') # 私钥路径
try:
    # 注意:如果私钥有密码,需要提供 passphrase
    ssh.connect(hostname="your_server_ip", 
                username="your_username", 
                key_filename=private_key_path,
                # passphrase='your_private_key_password' # 如果私钥有密码
               )
    print("使用密钥对连接成功!")
    # ... 执行命令 ...
    stdin, stdout, stderr = ssh.exec_command("hostname")
    print(f"远程主机名: {stdout.read().decode().strip()}")
except Exception as e:
    print(f"连接失败: {e}")
finally:
    ssh.close()

总结与选择

方法 优点 缺点 适用场景
paramiko 纯 Python 实现,功能强大灵活,是 SSH 应用的基石。 API 相对底层,需要处理更多细节。 首选推荐,需要精细控制 SSH 连接、文件传输、或开发复杂自动化工具。
fabric 高级封装,API 简洁优雅,任务管理清晰,连接管理自动化。 依赖 paramiko,学习曲线稍高。 编写部署、运维、自动化脚本,适合需要执行一系列连贯操作的场景。
subprocess 简单直接,无需额外安装库(在 Linux/macOS 上)。 安全性差(密码明文),平台依赖,功能有限,难以处理复杂交互。 快速的、一次性的、简单的远程命令执行,且环境可控,不推荐用于生产。

给你的建议:

  • 如果你是初学者或需要最大的灵活性,从 paramiko 开始学习,它能让你深刻理解 SSH 工作的原理。
  • 如果你主要目标是编写自动化部署或运维脚本,直接使用 fabric,它能让你事半功倍。
  • 尽量避免在生产环境中使用 subprocess + 密码的方式,如果必须使用,请务必配置好 SSH 密钥对。
分享:
扫描分享到社交APP
上一篇
下一篇