`paramiko` 模块:SSH 协议自动化与文件传输

好的,各位观众老爷,欢迎来到今天的“摸鱼也能搞定SSH”讲座!今天咱们的主题是 paramiko 模块,这玩意儿能让你的Python代码像个身怀绝技的特工,帮你自动化SSH连接、执行命令、传输文件,从此告别手动复制粘贴的苦逼生活。

一、 啥是 Paramiko?为啥要用它?

简单来说,paramiko 是一个用 Python 实现的 SSHv2 协议库。这意味着你可以在 Python 脚本里直接建立 SSH 连接,而不用依赖系统自带的 SSH 客户端。

为啥要用它呢?

  • 自动化运维: 想象一下,你要批量管理几百台服务器,每天都要登录上去执行同样的命令,改同样的配置文件,复制同样的文件。手动操作?加班到天荒地老吧!paramiko 可以帮你把这些操作自动化,一键搞定。
  • 远程监控: 你可以编写脚本,定期通过 SSH 连接到服务器,获取 CPU 使用率、内存占用、磁盘空间等信息,然后把这些数据存储起来,用于监控服务器的运行状态。
  • 文件传输: 需要把文件从一台服务器传输到另一台?paramiko 提供了 SFTPClient,让你像操作本地文件一样,轻松实现远程文件传输。
  • 安全可靠: paramiko 实现了 SSHv2 协议,提供了加密和认证机制,保证了连接的安全性。

二、 安装 Paramiko

这步很简单,打开你的命令行窗口,输入:

pip install paramiko

如果提示权限问题,可以尝试加上 --user 参数:

pip install --user paramiko

三、 Paramiko 的核心组件

paramiko 模块主要有几个核心组件,咱们一个一个来认识一下:

  • SSHClient 这是核心,负责建立 SSH 连接,验证身份,执行命令。
  • SFTPClient 用于文件传输,提供了上传、下载、删除、重命名等操作。
  • Transport 管理底层的 SSH 连接,处理密钥交换、加密等细节。一般不需要直接操作它。
  • Channel 代表一个 SSH 通道,用于发送和接收数据。一般也不需要直接操作它。

四、 建立 SSH 连接

首先,咱们来建立一个简单的 SSH 连接。

import paramiko

# 创建 SSHClient 对象
ssh = paramiko.SSHClient()

# 允许连接不在 known_hosts 文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 连接服务器
try:
    ssh.connect(hostname='your_server_ip',
                port=22,
                username='your_username',
                password='your_password')

    print("SSH connection established successfully!")

except Exception as e:
    print(f"SSH connection failed: {e}")

finally:
    ssh.close()

代码解释:

  1. import paramiko 导入 paramiko 模块。
  2. ssh = paramiko.SSHClient() 创建一个 SSHClient 对象。
  3. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 这行代码非常重要!当你第一次连接到一台服务器时,SSH 客户端会提示你是否信任该服务器的公钥。如果你选择信任,服务器的公钥会被添加到 known_hosts 文件中。以后再次连接时,SSH 客户端会验证服务器的公钥是否与 known_hosts 文件中的记录匹配。如果匹配,就认为连接是安全的。如果不匹配,就认为连接可能受到了中间人攻击。paramiko.AutoAddPolicy() 的作用是自动添加新的主机密钥到 known_hosts 文件中,这样你就不用手动确认了。注意: 在生产环境中,不建议使用 AutoAddPolicy(),因为它可能会导致安全问题。更安全的做法是手动添加主机密钥,或者使用 paramiko.RejectPolicy() 拒绝连接未知的服务器。
  4. ssh.connect(...) 连接服务器。你需要提供服务器的 IP 地址、端口号、用户名和密码。
  5. try...except...finally 使用 try...except 块来捕获连接过程中可能出现的异常。finally 块中的代码会在连接成功或失败后都会执行,用于关闭 SSH 连接。
  6. ssh.close() 关闭 SSH 连接,释放资源。

五、 执行命令

连接成功后,就可以执行命令了。

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    ssh.connect(hostname='your_server_ip',
                port=22,
                username='your_username',
                password='your_password')

    # 执行命令
    stdin, stdout, stderr = ssh.exec_command('ls -l')

    # 获取命令输出
    output = stdout.read().decode('utf-8')
    error = stderr.read().decode('utf-8')

    print("Command output:")
    print(output)

    if error:
        print("Command error:")
        print(error)

except Exception as e:
    print(f"SSH connection failed: {e}")

finally:
    ssh.close()

代码解释:

  1. stdin, stdout, stderr = ssh.exec_command('ls -l') 执行命令。ssh.exec_command() 方法返回三个对象:stdinstdoutstderrstdin 用于向命令发送输入,stdout 用于接收命令的输出,stderr 用于接收命令的错误信息。
  2. output = stdout.read().decode('utf-8')stdout 对象中读取命令的输出,并将其解码为 UTF-8 字符串。
  3. error = stderr.read().decode('utf-8')stderr 对象中读取命令的错误信息,并将其解码为 UTF-8 字符串。
  4. if error: 判断是否有错误信息。如果有,就打印出来。

六、 使用密钥认证

使用密码认证虽然简单,但是不够安全。更安全的方式是使用密钥认证。

1. 生成密钥对:

首先,需要在你的本地机器上生成一个密钥对。可以使用 ssh-keygen 命令:

ssh-keygen -t rsa -b 4096 -f ~/.ssh/my_private_key

这会生成两个文件:~/.ssh/my_private_key (私钥) 和 ~/.ssh/my_private_key.pub (公钥)。

2. 将公钥上传到服务器:

将公钥的内容复制到服务器的 ~/.ssh/authorized_keys 文件中。如果没有这个文件,就创建一个。

mkdir -p ~/.ssh
echo "你的公钥内容" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

3. 使用私钥连接服务器:

import paramiko

# 创建 SSHClient 对象
ssh = paramiko.SSHClient()

# 允许连接不在 known_hosts 文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 使用私钥连接服务器
try:
    private_key_path = '/path/to/your/private_key'  # 替换成你的私钥路径
    key = paramiko.RSAKey.from_private_key_file(private_key_path)

    ssh.connect(hostname='your_server_ip',
                port=22,
                username='your_username',
                pkey=key)

    print("SSH connection established successfully using private key!")

    # 执行命令 (可选)
    stdin, stdout, stderr = ssh.exec_command('ls -l')
    output = stdout.read().decode('utf-8')
    print(output)

except Exception as e:
    print(f"SSH connection failed: {e}")

finally:
    ssh.close()

代码解释:

  1. private_key_path = '/path/to/your/private_key' 替换成你的私钥文件的路径。
  2. key = paramiko.RSAKey.from_private_key_file(private_key_path) 从私钥文件中加载私钥。
  3. ssh.connect(..., pkey=key)ssh.connect() 方法中,使用 pkey 参数指定私钥。

七、 文件传输 (SFTP)

paramiko 提供了 SFTPClient 类,用于文件传输。

import paramiko

# 创建 SSHClient 对象
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    ssh.connect(hostname='your_server_ip',
                port=22,
                username='your_username',
                password='your_password')

    # 创建 SFTPClient 对象
    sftp = ssh.open_sftp()

    # 上传文件
    local_path = '/path/to/your/local/file'  # 替换成你的本地文件路径
    remote_path = '/path/to/remote/file'  # 替换成服务器上的目标路径
    sftp.put(local_path, remote_path)
    print(f"File uploaded successfully to {remote_path}")

    # 下载文件
    remote_path = '/path/to/remote/file'  # 替换成服务器上的文件路径
    local_path = '/path/to/your/local/file'  # 替换成本地的目标路径
    sftp.get(remote_path, local_path)
    print(f"File downloaded successfully to {local_path}")

    # 删除文件
    remote_path = '/path/to/remote/file'
    sftp.remove(remote_path)
    print(f"File {remote_path} deleted successfully.")

except Exception as e:
    print(f"SFTP operation failed: {e}")

finally:
    if 'sftp' in locals():
        sftp.close()
    ssh.close()

代码解释:

  1. sftp = ssh.open_sftp() 创建一个 SFTPClient 对象。
  2. sftp.put(local_path, remote_path) 上传文件。
  3. sftp.get(remote_path, local_path) 下载文件。
  4. sftp.remove(remote_path) 删除文件。
  5. sftp.close() 关闭 SFTP 连接。 重要: 必须关闭 SFTP 连接,否则可能会导致资源泄露。

八、 进阶技巧

  • 批量执行命令:
import paramiko

def execute_commands(host, username, password, commands):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        ssh.connect(hostname=host, port=22, username=username, password=password)
        for cmd in commands:
            print(f"Executing: {cmd} on {host}")
            stdin, stdout, stderr = ssh.exec_command(cmd)
            output = stdout.read().decode('utf-8')
            error = stderr.read().decode('utf-8')
            print(output)
            if error:
                print(f"Error: {error}")
    except Exception as e:
        print(f"Error connecting to {host}: {e}")
    finally:
        ssh.close()

# 示例
hosts = ['server1_ip', 'server2_ip']
username = 'your_username'
password = 'your_password'
commands = ['uptime', 'df -h', 'free -m']

for host in hosts:
    execute_commands(host, username, password, commands)
  • 使用代理: 如果你的服务器需要通过代理才能访问外网,可以使用 paramikoProxyCommand
import paramiko
import socket

# 创建 SSHClient 对象
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 使用代理
try:
    proxy = paramiko.ProxyCommand('ssh -q -W %h:%p proxy_server_username@proxy_server_ip')
    ssh.connect(hostname='your_server_ip',
                port=22,
                username='your_username',
                password='your_password',
                sock=proxy)

    print("SSH connection established successfully through proxy!")

    # 执行命令 (可选)
    stdin, stdout, stderr = ssh.exec_command('ls -l')
    output = stdout.read().decode('utf-8')
    print(output)

except Exception as e:
    print(f"SSH connection failed: {e}")

finally:
    ssh.close()

九、 最佳实践

  • 不要硬编码密码: 永远不要在代码中硬编码密码。可以使用环境变量、配置文件或者专门的密钥管理工具来存储密码。
  • 使用密钥认证: 尽量使用密钥认证,而不是密码认证。
  • 处理异常: 使用 try...except 块来捕获可能出现的异常,并进行适当的处理。
  • 关闭连接: 在使用完 SSH 连接后,一定要关闭它,释放资源。
  • 使用线程或进程: 如果需要同时连接多台服务器,可以使用线程或进程来提高效率。

十、 Paramiko 的局限性

  • 性能: paramiko 是用 Python 实现的,性能不如原生的 SSH 客户端。如果需要处理大量的 SSH 连接,或者执行对性能要求很高的操作,可以考虑使用其他方案。
  • 依赖: paramiko 依赖于 Python 和一些其他的 Python 库。

十一、 总结

paramiko 是一个非常强大的 Python 模块,可以让你轻松地实现 SSH 协议的自动化。掌握了 paramiko,你就拥有了一把打开自动化运维之门的钥匙。希望今天的讲座能帮助你更好地理解和使用 paramiko

十二、 练习题

  1. 编写一个脚本,使用 paramiko 连接到一台服务器,获取 CPU 使用率、内存占用、磁盘空间等信息,并将这些信息存储到文件中。
  2. 编写一个脚本,使用 paramiko 连接到多台服务器,批量执行相同的命令。
  3. 编写一个脚本,使用 paramiko 实现文件的自动备份功能,定期将服务器上的文件备份到本地。

表格总结常用函数:

函数/方法 描述
SSHClient() 创建一个 SSH 客户端对象。
set_missing_host_key_policy() 设置处理未知主机密钥的策略。 常用的策略包括 AutoAddPolicy (自动添加主机密钥) 和 RejectPolicy (拒绝连接未知主机)。
connect() 连接到 SSH 服务器。需要提供主机名、端口、用户名、密码或私钥。
exec_command() 在远程服务器上执行命令。返回 stdinstdoutstderr 对象。
open_sftp() 创建一个 SFTP 客户端对象,用于文件传输。
put() 将本地文件上传到远程服务器。
get() 从远程服务器下载文件到本地。
remove() 删除远程服务器上的文件。
close() 关闭 SSH 或 SFTP 连接。
RSAKey.from_private_key_file() 从私钥文件中加载 RSA 私钥,用于密钥认证。

好了,今天的讲座就到这里。希望大家都能成为 paramiko 的高手,让你的 Python 代码在运维的世界里叱咤风云! 记得点赞,投币,收藏! 咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注