paramiko模块
paramiko模块
通过ssh链接服务器并执行想要的命令,类似于XShell
ansible(远程批量管理服务器)底层源码其实就是paramiko模块实现的
一、安装
pip3 install paramiko
二、使用
前提须知:paramiko模块即支持用户名密码的方式也支持公钥私钥的方式操作服务器
2.1 通过密码连接
# 执行命令
# 创建链接对象
ssh = paramiko.SSHClient()
# 允许链接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 链接服务器
ssh.connect(hostname='192.168.219.170',port=22,username='root',password='123')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('ip a')
"""
stdin 是用来输入额外的参数的 -y
stdout 命令的返回结果
stderr 错误的结果
"""
# 获取命令执行的结果
res = stdout.read()
print(res.decode('utf-8'))
# 关闭链接
ssh.close()
2.2 通过私钥连接
需要自己生成私钥,上传至服务器
import paramiko
"""公钥私钥的方式执行命令"""
# 你要先生成公钥私钥 然后将你的公钥先发送到服务器上 之后通过私钥去链接即可
"""
mac
1 生成
ssh-keygen -t ras
2 拷贝公钥到远程服务器
ssh-copy-id -i ~/.ssh/id_rsa.pub username@hostname
3 你可以将私钥的内容单独保存到一个文件中
cat ~/.ssh/id_rsa
window百度一堆
"""
# 读取本地私钥
private_key = paramiko.RSAKey.from_private_key_file('a.txt')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='172.16.219.170', port=22, username='root', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls /')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭连接
ssh.close()
2.3 通过用户上传 下载文件
# 上传下载文件
# 用户名和密码的方式
import paramiko
# 用户名和密码
transport = paramiko.Transport(('172.16.219.170', 22))
transport.connect(username='root', password='jason123')
sftp = paramiko.SFTPClient.from_transport(transport)
# 上传文件
sftp.put("a.txt", '/data/tmp.txt') # 注意上传文件到远程某个文件下 文件必须存在
# 下载文件
sftp.get('/data/tmp.txt', 'hahaha.txt') # 将远程文件下载到本地并重新命令
transport.close()
2.4 通过密码上传下载文件
# 公钥和私钥
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('a.txt')
transport = paramiko.Transport(('172.16.219.170', 22))
# 创建连接
transport.connect(username='root', pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('manage.py', '/data/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
三、SSHProxy类的封装
连接服务器执行三条命令,并且上传一个文件内容,大部分都会操作几次命令就需要链接几次服务器,效率较低,代码冗余
实现一个类里面包含了执行命令和上传下载文件的操作:
3.1 封装
# 类的代码
import paramiko
class SSHProxy(object):
# 这里的参数 你可以再加公钥私钥的形式
def __init__(self, hostname, port, username, password):
"""
账户登录
:param hostname:
:param port:
:param username:
:param password:
"""
self.hostname = hostname
self.port = port
self.username = username
self.password = password
self.transport = None
def open(self):
"""
创建文件上传下载对象
:return:
"""
# 给对象赋值一个上传下载文件对象连接
self.transport = paramiko.Transport((self.hostname, self.port))
self.transport.connect(username=self.username, password=self.password)
# 执行命令
# self.ssh = paramiko.SSHClient()
# self.ssh._transport = self.transport
def command(self, cmd): # 正常执行命令的连接 至此对象内容就既有执行命令的连接又有上传下载链接
"""
执行命令
:param cmd:
:return:
"""
ssh = paramiko.SSHClient() # 也可以放到open中
ssh._transport = self.transport
# stdin, stdout, stderr = self.ssh.exec_command(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
return result.decode('utf-8')
def upload(self, local_path, remote_path):
"""
上传文件
:param local_path:
:param remote_path:
:return:
"""
sftp = paramiko.SFTPClient.from_transport(self.transport)
sftp.put(local_path, remote_path)
sftp.close()
def download(self,local_path, remote_path):
"""
下载文件
:param local_path:
:param remote_path:
:return:
"""
sftp = paramiko.SFTPClient.from_transport(self.transport)
sftp.get(local_path, remote_path)
sftp.close()
def close(self):
self.transport.close()
# self.ssh.close()
def __enter__(self): # 对象执行with上下文会自动触发
self.open()
return self # 这里发挥上面with语法内的as后面拿到的就是什么
def __exit__(self, exc_type, exc_val, exc_tb): # with执行结束自动触发
self.close()
3.2 使用
方式一
上述的封装操作在使用的使用 必须按照下面的顺序
obj = SSHProxy(...)
obj.open() # 产生的对象必须要先执行open方法
obj.command('ls /')
obj.command('cat /data/tmp.txt')
obj.upload(...)
obj.upload(...)
obj.close()
方式二:
"""
嫌上述操作麻烦 利用with上下文做处理了
with open() as f:
pass
as后面的值由__enter__方法返回值决定 返回什么就是什么
# 一旦对象被执行with会自动触发对象内部的__enter__方法 with结束之后还会自动触发__exit__方法
obj = SSHProxy(1,2,3,4)
with obj as f:
pass
封装之后按照下面的方式使用即可
with SSHProxy(....) as obj:
obj.command()
obj.command()
obj.upload()
obj.upload()
obj.command()
"""
with SSHProxy(hostname='47.103.140.218', port=22, username='root', password='123456.') as obj:
res = obj.command('ls /')
print(res)
在当下的阶段,必将由程序员来主导,甚至比以往更甚。