好的,各位观众老爷,欢迎来到今天的“摸鱼也能搞定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()
代码解释:
import paramiko
: 导入paramiko
模块。ssh = paramiko.SSHClient()
: 创建一个SSHClient
对象。ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
: 这行代码非常重要!当你第一次连接到一台服务器时,SSH 客户端会提示你是否信任该服务器的公钥。如果你选择信任,服务器的公钥会被添加到known_hosts
文件中。以后再次连接时,SSH 客户端会验证服务器的公钥是否与known_hosts
文件中的记录匹配。如果匹配,就认为连接是安全的。如果不匹配,就认为连接可能受到了中间人攻击。paramiko.AutoAddPolicy()
的作用是自动添加新的主机密钥到known_hosts
文件中,这样你就不用手动确认了。注意: 在生产环境中,不建议使用AutoAddPolicy()
,因为它可能会导致安全问题。更安全的做法是手动添加主机密钥,或者使用paramiko.RejectPolicy()
拒绝连接未知的服务器。ssh.connect(...)
: 连接服务器。你需要提供服务器的 IP 地址、端口号、用户名和密码。try...except...finally
: 使用try...except
块来捕获连接过程中可能出现的异常。finally
块中的代码会在连接成功或失败后都会执行,用于关闭 SSH 连接。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()
代码解释:
stdin, stdout, stderr = ssh.exec_command('ls -l')
: 执行命令。ssh.exec_command()
方法返回三个对象:stdin
、stdout
和stderr
。stdin
用于向命令发送输入,stdout
用于接收命令的输出,stderr
用于接收命令的错误信息。output = stdout.read().decode('utf-8')
: 从stdout
对象中读取命令的输出,并将其解码为 UTF-8 字符串。error = stderr.read().decode('utf-8')
: 从stderr
对象中读取命令的错误信息,并将其解码为 UTF-8 字符串。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()
代码解释:
private_key_path = '/path/to/your/private_key'
: 替换成你的私钥文件的路径。key = paramiko.RSAKey.from_private_key_file(private_key_path)
: 从私钥文件中加载私钥。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()
代码解释:
sftp = ssh.open_sftp()
: 创建一个SFTPClient
对象。sftp.put(local_path, remote_path)
: 上传文件。sftp.get(remote_path, local_path)
: 下载文件。sftp.remove(remote_path)
: 删除文件。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)
- 使用代理: 如果你的服务器需要通过代理才能访问外网,可以使用
paramiko
的ProxyCommand
。
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
。
十二、 练习题
- 编写一个脚本,使用
paramiko
连接到一台服务器,获取 CPU 使用率、内存占用、磁盘空间等信息,并将这些信息存储到文件中。 - 编写一个脚本,使用
paramiko
连接到多台服务器,批量执行相同的命令。 - 编写一个脚本,使用
paramiko
实现文件的自动备份功能,定期将服务器上的文件备份到本地。
表格总结常用函数:
函数/方法 | 描述 |
---|---|
SSHClient() |
创建一个 SSH 客户端对象。 |
set_missing_host_key_policy() |
设置处理未知主机密钥的策略。 常用的策略包括 AutoAddPolicy (自动添加主机密钥) 和 RejectPolicy (拒绝连接未知主机)。 |
connect() |
连接到 SSH 服务器。需要提供主机名、端口、用户名、密码或私钥。 |
exec_command() |
在远程服务器上执行命令。返回 stdin 、stdout 和 stderr 对象。 |
open_sftp() |
创建一个 SFTP 客户端对象,用于文件传输。 |
put() |
将本地文件上传到远程服务器。 |
get() |
从远程服务器下载文件到本地。 |
remove() |
删除远程服务器上的文件。 |
close() |
关闭 SSH 或 SFTP 连接。 |
RSAKey.from_private_key_file() |
从私钥文件中加载 RSA 私钥,用于密钥认证。 |
好了,今天的讲座就到这里。希望大家都能成为 paramiko
的高手,让你的 Python 代码在运维的世界里叱咤风云! 记得点赞,投币,收藏! 咱们下期再见!