编辑
2024-05-23
Python
00

目录

背景
1. Paramiko简介
2. SSHProxy类封装
密码认证的 SSHProxy 实现
3. 基于密钥的认证实现
4. 面向对象的上下文管理协议
5. 总结
我的示例

背景

在远程服务器的日常操作中,常常需要进行文件传输、命令执行等操作。使用手动SSH登录然后执行命令显然不够高效,特别是在需要自动化执行任务时。Python 的 paramiko 库提供了强大的 SSH 客户端功能,能够帮助开发者简化 SSH 连接和文件操作的实现。本文将介绍如何通过封装 paramiko 库,创建一个便于管理和操作的 SSHProxy 类,并通过面向对象的上下文管理方式优化代码结构。

1. Paramiko简介

paramiko 是一个用于 SSH 连接和 SFTP 文件传输的 Python 库。通过这个库,你可以在 Python 程序中建立 SSH 连接、远程执行命令、传输文件等。

核心功能:

  • 通过密码或密钥进行身份验证的 SSH 连接。
  • 通过 exec_command 远程执行命令。
  • 通过 SFTP 传输文件。

2. SSHProxy类封装

我们通过封装 paramikoTransportSSHClient,实现了一个简单的 SSHProxy 类,能够简化 SSH 的连接、命令执行和文件上传。下面是代码的详细实现。

密码认证的 SSHProxy 实现
python
import paramiko class SSHProxy(object): def __init__(self, hostname, port, username, password): self.hostname = hostname self.port = port self.username = username self.password = password self.transport = None def open(self): """ 打开SSH连接 """ self.transport = paramiko.Transport((self.hostname, self.port)) self.transport.connect(username=self.username, password=self.password) def command(self, cmd): """ 远程执行命令 """ ssh = paramiko.SSHClient() ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(cmd) result = stdout.read() return result def upload(self, local_path, remote_path): """ 上传文件 """ sftp = paramiko.SFTPClient.from_transport(self.transport) sftp.put(local_path, remote_path) sftp.close() def close(self): """ 关闭SSH连接 """ self.transport.close() def __enter__(self): """ 上下文管理协议:进入 """ self.open() return self def __exit__(self, exc_type, exc_val, exc_tb): """ 上下文管理协议:退出 """ self.close() if __name__ == '__main__': with SSHProxy("123.206.16.61", 22, 'root', 'password') as ssh: ssh.command('df') ssh.upload(r'D:\path\file.txt', '/data/file.txt')

3. 基于密钥的认证实现

在某些场景下,基于密码的认证不够安全或方便,因此我们可以通过 SSH 密钥认证来连接远程服务器。以下是使用密钥认证的 SSHProxy 实现:

python
class SSHProxy(object): def __init__(self, hostname, port, username, private_key_path): self.hostname = hostname self.port = port self.username = username self.private_key_path = private_key_path self.transport = None def open(self): """ 使用RSA密钥打开SSH连接 """ private_key = paramiko.RSAKey.from_private_key_file(self.private_key_path) self.transport = paramiko.Transport((self.hostname, self.port)) self.transport.connect(username=self.username, pkey=private_key) def close(self): """ 关闭SSH连接 """ self.transport.close() def command(self, cmd): """ 远程执行命令 """ ssh = paramiko.SSHClient() ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(cmd) result = stdout.read() return result def upload(self, local_path, remote_path): """ 上传文件 """ sftp = paramiko.SFTPClient.from_transport(self.transport) sftp.put(local_path, remote_path) sftp.close() def __enter__(self): """ 上下文管理协议:进入 """ self.open() return self def __exit__(self, exc_type, exc_val, exc_tb): """ 上下文管理协议:退出 """ self.close()

4. 面向对象的上下文管理协议

在上述代码中,__enter____exit__ 方法实现了上下文管理协议。通过这种方式,我们可以使用 with 语句简化资源管理。

上下文管理协议是 Python 面向对象中的一种特殊协议,允许对象控制 with 语句的行为。当进入 with 语句时,会自动调用 __enter__ 方法;而当退出时,无论是否抛出异常,都会调用 __exit__ 方法来确保资源释放。通过这种机制,我们可以避免忘记关闭资源。

一个简单的上下文管理类实现如下:

python
class Context: def __enter__(self): print('进入上下文') return self def __exit__(self, exc_type, exc_val, exc_tb): print('退出上下文') def do_something(self): print('执行操作') # 使用上下文管理 with Context() as ctx: ctx.do_something()

5. 总结

通过封装 paramiko,我们能够更加高效地管理 SSH 连接,简化了命令执行和文件上传的流程。此外,使用上下文管理协议可以确保资源在使用完毕后正确释放,从而避免内存泄漏或连接未关闭的问题。

这类封装适合于日常自动化任务的执行,比如定期备份、远程日志收集等。通过在代码中合理应用上下文管理协议和封装设计,可以使代码更加简洁和易维护。

我的示例

Python
import paramiko class SSHProxy(object): def __init__(self, hostname, port, username, private_key_path): self.hostname = hostname self.port = port self.username = username self.private_key_path = private_key_path self.transport = None def open(self): private_key = paramiko.RSAKey.from_private_key_file(self.private_key_path) self.transport = paramiko.Transport((self.hostname, self.port)) self.transport.connect(username=self.username, pkey=private_key) def close(self): self.transport.close() def command(self, cmd): ssh = paramiko.SSHClient() ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(cmd) result = stdout.read() # ssh.close() return result def upload(self, local_path, remote_path): sftp = paramiko.SFTPClient.from_transport(self.transport) sftp.put(local_path, remote_path) sftp.close() def __enter__(self): self.open() return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() if __name__ == '__main__': with SSHProxy('10.211.55.25', 22, 'root', '/Users/wupeiqi/.ssh/id_rsa') as ssh: # v1 = ssh.command('sudo ifconfig') # print(v1) ssh.upload('your.tar', '/data/your.tar')
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:GYC

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!