paramiko模块
1.模块作用
通过ssh远程连接服务器并执行想要命令 类似于Xshell
ansible批量管理机器,ansible底层用的就是paramiko模块
2.使用
1.安装
pip3 install paramiko
2.执行命令
1.用户名和密码的方式 #1.导入模块 import paramiko #2.创建ssh对象 ssh = paramiko.SSHClient() #3.允许链接不在know_hosts文件中主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #4.链接服务器:地址,端口号,用户名,密码 ssh.connect(hostname='0.0.0.0',port=3306,username='root',password='123') # 5.执行命令: stdin, stdout, stderr = ssh.exec_command('ip a') # 6.获取结果 res = stdout.read() # 基于网络传输 该结果是一个bytes类型 print(res.decode('utf-8')) # 7.断开链接 ssh.close() 2.公钥和私钥(先讲公钥保存到服务器上)
#1.导入模块 import paramiko #2. 读取本地私钥:a.txt为文件路径 private_key = paramiko.RSAKey.from_private_key_file('a.txt') # 3.创建SSH对象 ssh = paramiko.SSHClient() # 4.允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 5.连接服务器 ssh.connect(hostname='0.0.0.0', port=22, username='root', pkey=private_key) # 6.执行命令 stdin, stdout, stderr = ssh.exec_command('ls /') # 7.获取命令结果 result = stdout.read() print(result.decode('utf-8')) # 8.关闭连接 ssh.close()
3.上传和下载文件
1.#用户名密码方式 import paramiko #2.ip端口 用户名和密码 transport = paramiko.Transport(('172.16.219.168', 22)) transport.connect(username='root', password='jason123') sftp = paramiko.SFTPClient.from_transport(transport) # 3.上传文件:本地文件,上传后位置路径 sftp.put("a.txt", '/data/tmp.txt') # 注意上传文件到远程某个文件下 文件必须存在 #4.下载文件:服务器文件,本地路径 sftp.get('/data/tmp.txt', 'hahahha.txt') # 将远程文件下载到本地并重新命令
#5.关闭链接
transport.close() 2.# 公钥私钥方式 import paramiko #1.链接 private_key = paramiko.RSAKey.from_private_key_file('a.txt') transport = paramiko.Transport(('172.16.219.168', 22)) transport.connect(username='root', pkey=private_key) sftp = paramiko.SFTPClient.from_transport(transport) # 2.将location.py 上传至服务器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 3.将remove_path 下载到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
4.封装总结
秘钥和用户名密码的区别在于链接时参数的不同而已: 1.密码 ssh.connect(hostname='0.0.0.0',port=3306,username='root',password='123') 2.秘钥 ssh.connect(hostname='0.0.0.0', port=22, username='root', pkey=private_key) 文件上传下载同理
transport.connect(username='root', password='123')
transport.connect(username='root', pkey=private_key)
疑问点:如果我想链接服务器执行多条命令并且还想上传下载文件,那么你所能看到的一般做法都是执行一次命令创建一次链接
我们封装成一个类,类的内部有一系列的方法,并且这些方法都可以在同一个链接下执行多次
# 1.基于用户名密码使用封装
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): # 给对象赋值一个上传下载文件对象连接 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): self.transport.close() def __enter__(self): print('with开始') self.open() return self # 该方法返回什么 with ... as 后面就拿到什么 def __exit__(self, exc_type, exc_val, exc_tb): print('with结束') self.close() if __name__ == '__main__':
#1. with上下文管理使用(推荐) obj = SSHProxy(hostname='172.16.219.168',port=22,username='root',password='jason123') with obj as ssh: # 默认不支持 对象执行with会自动触发内部的__enter__方法 print('with内部代码')
# with上下文执行完毕之后 会自动触发__exit__方法
#2.使用方式2:
#2.尝试基于用户名密码秘钥封装
mport paramiko class SSHProxy(object): def __init__(self, hostname, port, username, password,pkey): self.hostname = hostname self.port = port self.username = username self.password = password self.pkey = pkey self.transport = None def open(self): # 给对象赋值一个上传下载文件对象连接 self.transport = paramiko.Transport((self.hostname, self.port)) self.transport.connect(username=self.username, password=self.password,pkey=self.pkey) 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 down(self,remote_path,local_path): sftp = paramiko.SFTPClient.from_transport(self.transport) sftp.get(remote_path,local_path) sftp.close() def close(self): self.transport.close() def __enter__(self): print('with开始') self.open() return self # 该方法返回什么 with ... as 后面就拿到什么 def __exit__(self, exc_type, exc_val, exc_tb): print('with结束') self.close()