目录
1. Paramiko 概述
是什么?
Paramiko 是一个纯 Python 实现的 SSHv2 协议库,支持:
- 远程命令执行
- 安全文件传输(SFTP)
- 端口转发与隧道
- RSA/DSA 密钥认证
应用场景
- 自动化运维:批量执行服务器命令(部署、日志分析)。
- 安全文件传输:替代
scp
/sftp
命令行工具。 - 网络设备管理:管理路由器、交换机等支持 SSH 的设备。
- 内网穿透:通过 SSH 隧道访问隔离网络资源。
2. 核心功能与模块框架
核心模块
模块/类 | 功能描述 |
---|---|
SSHClient | 封装 SSH 会话,管理连接与命令执行 |
SFTPClient | 提供 SFTP 文件操作接口 |
Transport | 底层连接管理,支持复用与扩展协议 |
Channel | SSH 通道,实现交互式会话或端口转发 |
RSAKey /DSSKey | 处理密钥的生成与加载 |
工作流程
- 建立连接:
SSHClient.connect()
- 认证方式:密码、密钥或混合认证
- 执行操作:命令、文件传输、端口转发
- 关闭连接:显式调用
close()
或使用with
语句
3. 安装与依赖
安装命令
pip install paramiko
系统依赖(Linux)
sudo apt-get install libssl-dev # 确保加密库支持
4. 基础用法与案例详解
案例 1:SSH 连接与命令执行
import paramiko
# 创建客户端并设置自动添加主机密钥(生产环境慎用)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# 连接远程主机
ssh.connect(
hostname='192.168.1.100',
username='user',
password='password',
timeout=5
)
# 执行命令并获取输出
stdin, stdout, stderr = ssh.exec_command('ls -l /tmp')
output = stdout.read().decode('utf-8')
error = stderr.read().decode('utf-8')
print(f"Output:\n{output}\nError:\n{error}")
except paramiko.AuthenticationException:
print("认证失败!")
finally:
ssh.close()
关键点
AutoAddPolicy
:自动信任未知主机密钥(仅限测试环境)。stdin/stdout/stderr
:分别对应命令的输入、输出和错误流。decode('utf-8')
:将字节流转换为字符串,解决编码问题。
案例 2:密钥认证
import paramiko
# 加载加密的 RSA 私钥
private_key = paramiko.RSAKey.from_private_key_file(
filename='~/.ssh/id_rsa',
password='your_key_password' # 若密钥有密码
)
ssh = paramiko.SSHClient()
ssh.connect(
hostname='host',
username='user',
pkey=private_key
)
注意事项
- 私钥文件权限需为
600
:chmod 600 ~/.ssh/id_rsa
- 支持
.pem
和 OpenSSH 格式密钥。
案例 3:SFTP 文件传输
with paramiko.SSHClient() as ssh:
ssh.connect('host', username='user', password='pass')
sftp = ssh.open_sftp()
# 上传文件
sftp.put('local_file.txt', '/remote/path/file.txt')
# 下载文件
sftp.get('/remote/path/file.txt', 'local_download.txt')
# 遍历目录
for file in sftp.listdir('/tmp'):
print(file)
扩展功能
sftp.mkdir()
:创建远程目录sftp.stat()
:获取文件属性
案例 4:交互式 Shell 会话
channel = ssh.invoke_shell() # 创建交互式通道
channel.send('ls -l\n') # 发送命令
# 等待响应并读取输出
while not channel.recv_ready():
time.sleep(0.1) # 避免 CPU 空转
output = channel.recv(1024).decode()
print(output)
关键参数
recv(1024)
:每次读取 1024 字节的缓冲区。get_pty=True
:为命令分配伪终端(解决sudo
交互问题)。
案例 5:本地端口转发
transport = paramiko.Transport(('host', 22))
transport.connect(username='user', password='pass')
# 将本地 8080 端口转发到远程主机的 80 端口
transport.request_port_forward('localhost', 8080, '', 80)
# 此时访问 localhost:8080 将转发到远程 80 端口
业务场景
- 访问内网 Web 服务(如
http://localhost:8080
→ 远程80
端口)。 - 绕过防火墙限制。
5. 高级功能与实战技巧
1. 复用 Transport 连接
transport = paramiko.Transport(('host', 22))
transport.connect(...)
# 复用 Transport 创建 SFTP
sftp = paramiko.SFTPClient.from_transport(transport)
# 复用 Transport 执行命令
ssh = paramiko.SSHClient()
ssh._transport = transport
2. 使用 SSH 配置文件
from paramiko.config import SSHConfig
config = SSHConfig()
with open(os.path.expanduser("~/.ssh/config")) as f:
config.parse(f)
host_info = config.lookup('myhost')
ssh.connect(
hostname=host_info['hostname'],
username=host_info['user'],
key_filename=host_info['identityfile'][0]
)
3. 超时与重试机制
from retry import retry
@retry(tries=3, delay=2)
def connect_with_retry():
ssh.connect(..., timeout=10)
6. 常见问题与解决方案
问题 1:认证失败
- 原因:密码错误、密钥权限问题、密钥格式不兼容。
- 解决:
chmod 600 ~/.ssh/id_rsa # 修复密钥权限 ssh-keygen -p -m PEM -f ~/.ssh/id_rsa # 转换密钥为 PEM 格式
问题 2:sudo
命令卡住
- 原因:未分配伪终端(PTY)。
- 解决:
stdin, stdout, stderr = ssh.exec_command('sudo cmd', get_pty=True) stdin.write('password\n') stdin.flush() # 必须刷新缓冲区
问题 3:中文乱码
- 原因:远程输出编码非 UTF-8。
- 解决:
output = stdout.read().decode('gbk', errors='ignore') # Windows 主机
问题 4:连接超时
- 原因:网络阻塞或防火墙限制。
- 解决:
ssh.connect(..., timeout=10) # 显式设置超时
7. 总结
核心要点
- 安全优先:生产环境避免
AutoAddPolicy
,严格校验主机密钥。 - 资源管理:使用
with
语句或finally
确保连接关闭。 - 性能优化:复用连接、设置超时、合理处理编码。