在远程服务器的日常操作中,常常需要进行文件传输、命令执行等操作。使用手动SSH登录然后执行命令显然不够高效,特别是在需要自动化执行任务时。Python 的 paramiko
库提供了强大的 SSH 客户端功能,能够帮助开发者简化 SSH 连接和文件操作的实现。本文将介绍如何通过封装 paramiko
库,创建一个便于管理和操作的 SSHProxy
类,并通过面向对象的上下文管理方式优化代码结构。
paramiko
是一个用于 SSH 连接和 SFTP 文件传输的 Python 库。通过这个库,你可以在 Python 程序中建立 SSH 连接、远程执行命令、传输文件等。
核心功能:
exec_command
远程执行命令。我们通过封装 paramiko
的 Transport
和 SSHClient
,实现了一个简单的 SSHProxy
类,能够简化 SSH 的连接、命令执行和文件上传。下面是代码的详细实现。
pythonimport 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')
在某些场景下,基于密码的认证不够安全或方便,因此我们可以通过 SSH 密钥认证来连接远程服务器。以下是使用密钥认证的 SSHProxy
实现:
pythonclass 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()
在上述代码中,__enter__
和 __exit__
方法实现了上下文管理协议。通过这种方式,我们可以使用 with
语句简化资源管理。
上下文管理协议是 Python 面向对象中的一种特殊协议,允许对象控制 with
语句的行为。当进入 with
语句时,会自动调用 __enter__
方法;而当退出时,无论是否抛出异常,都会调用 __exit__
方法来确保资源释放。通过这种机制,我们可以避免忘记关闭资源。
一个简单的上下文管理类实现如下:
pythonclass 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()
通过封装 paramiko
,我们能够更加高效地管理 SSH 连接,简化了命令执行和文件上传的流程。此外,使用上下文管理协议可以确保资源在使用完毕后正确释放,从而避免内存泄漏或连接未关闭的问题。
这类封装适合于日常自动化任务的执行,比如定期备份、远程日志收集等。通过在代码中合理应用上下文管理协议和封装设计,可以使代码更加简洁和易维护。
Pythonimport 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')
本文作者:GYC
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!