当前位置: 首页 > news >正文

python运维自动化Paramiko

文章目录

  • 一、Paramiko
    • 1、安装
    • 2、常用的类
    • 3、使用
      • (1)SSH执行远程命令
      • (2)SFTP上传/下载文件
      • (3)SSH简单封装
      • (4)SFTP简单封装
  • 参考资料

一、Paramiko

1、安装

pip install paramiko

2、常用的类

SSHClient: 最常用的类,表示一个SSH客户端连接。
SFTPClient: 用于SFTP传输操作。
Transport: 低级别的模块,可用来实现SSH2协议。
SSHClient主要方法
connect(hostname, port=22, username=None, password=None, pkey=None): 用于连接到远程服务器。可以选择使用用户名和密码或密钥进行认证。
exec_command(command): 在远程服务器上执行指令。
open_sftp(): 返回一个SFTPClient对象,可用于文件的上传与下载。
SFTPClient主要方法
get(remotepath, localpath, callback=None): 下载远程文件。
put(localpath, remotepath, callback=None, confirm=True): 上传本地文件。
listdir(path=“.”): 列出远程目录的内容。

3、使用

(1)SSH执行远程命令

import paramiko# 创建SSH客户端
client = paramiko.SSHClient()# 自动添加未知的服务器密钥及策略
'''
AutoAddPolicy:自动添加主机名及主机密钥到本地的known_hosts,不依赖load_system_host_key的配置。即新建立ssh连接时不需要再输入yes或no进行确认。最为常用。
WarningPolicy 用于记录一个未知的主机密钥的python警告。并接受,功能上和AutoAddPolicy类似,但是会提示是新连接。
RejectPolicy 自动拒绝未知的主机名和密钥,依赖load_system_host_key的配置。此为默认选项
'''
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 连接SSH服务端
'''
hostname(str类型),连接的目标主机地址;
port(int类型),连接目标主机的端口,默认为22;
username(str类型),校验的用户名(默认为当前的本地用户名);
password(str类型),密码用于身份校验或解锁私钥;
pkey(Pkey类型),私钥方式用于身份验证;
key_filename(str or list(str)类型),一个文件名或文件名列表,用于私钥的身份验证;
timeout(float类型),一个可选的超时时间(以秒为单位)的TCP连接;
allow_agent(bool类型),设置为False时用于禁用连接到SSH代理;
look_for_keys(bool类型),设置为False时用于来禁用在~/.ssh中搜索私钥文件;
compress(bool类型),设置为True时打开压缩。
'''
client.connect('192.168.56.10', port=22, username='root', password='vagrant')# 执行命令
stdin, stdout, stderr = client.exec_command('ls -l')# 获取命令执行结果
result = stdout.read()print(result.decode())# 关闭连接
client.close()

(2)SFTP上传/下载文件

import paramiko# 创建SSH客户端
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.56.10', port=22, username='root', password='vagrant')# 创建SFTP会话
sftp = client.open_sftp()# 上传文件
sftp.put('localfile.txt', '/remote/path/remote.txt')# 下载文件
sftp.get('/remote/path/remote.txt', 'localfile.txt')'''
mkdir,在SFTP服务端创建目录,如sftp.mkdir("/home/userdir",mode=0777),默认模式是0777(八进制),在某些系统上,mode被忽略。在使用它的地方,当前的umask值首先被屏蔽掉。
remove,删除SFTP服务端指定目录,如sftp.remove("/home/userdir")。
rename,重命名SFTP服务端文件或目录,如sftp.rename("/home/test.sh","/home/testfile.sh")
stat,获取远程SFTP服务端指定文件信息,如sftp.stat("/home/testfile.sh")。
listdir,获取远程SFTP服务端指定目录列表,以Python的列表(List)形式返回,如sftp.listdir("/home")。
'''# 关闭SFTP会话和SSH连接
sftp.close()
client.close()

(3)SSH简单封装

import paramikoclass SSHClient:def __init__(self, hostname, port=22, username=None, password=None, pkey=None, use_proxy=False, proxy_hostname=None,proxy_port=None, proxy_username=None, proxy_password=None, timeout=5):"""初始化SSH客户端。:param hostname: 主机名或IP地址:param port: 端口号,默认是22:param username: 用户名:param password: 密码:param pkey: 私钥文件对象,用于密钥认证:param use_proxy: 是否使用代理标志:param proxy_hostname: 代理的主机名称:param proxy_port: 代理的端口号:param proxy_username: 代理的用户名:param proxy_password: 代理的密码"""self.hostname = hostnameself.port = portself.username = usernameself.password = passwordself.pkey = pkeyself.use_proxy = use_proxyself.proxy_hostname = proxy_hostnameself.proxy_port = proxy_portself.proxy_username = proxy_usernameself.proxy_password = proxy_passwordself.client = Noneself.timeout = timeoutdef _setup_proxy(self):"""配置代理。"""if self.use_proxy:proxy_ssh = paramiko.SSHClient()proxy_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())proxy_ssh.connect(hostname=self.proxy_hostname, port=self.proxy_port, username=self.proxy_username,password=self.proxy_password, timeout=self.timeout)vm_transport = proxy_ssh.get_transport()remote_address = (self.hostname, self.port)local_address = (self.proxy_hostname, self.proxy_port)vm_channel = vm_transport.open_channel("direct-tcpip", remote_address, local_address)return vm_channelelse:return Nonedef _connect(self):"""创建SSH连接。"""self.client = paramiko.SSHClient()self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())proxy = self._setup_proxy()self.client.connect(self.hostname, port=self.port, username=self.username, password=self.password,pkey=self.pkey, sock=proxy, timeout=self.timeout)def exec_command(self, command):"""在远程服务器上执行命令。:param command: 要执行的命令字符串:return: 命令输出结果的标准输出和标准错误"""if self.client is None:self._connect()stdin, stdout, stderr = self.client.exec_command(command)return stdout.read().decode(), stderr.read().decode()def close(self):"""关闭SSH连接。"""if self.client:self.client.close()self.client = None# 使用示例
if __name__ == "__main__":# 直接连接单个服务器'''ssh = SSHClient(hostname='192.168.56.10', port=22, username='root', password='vagrant')stdout, stderr = ssh.exec_command('ls -l')print(stdout)ssh.close()'''# 通过代理连接'''ssh_with_proxy = SSHClient(hostname='hostname', port=22, username='username', password='password', use_proxy=True,proxy_hostname='proxy_hostname', proxy_port=22, proxy_username='proxy_username',proxy_password='proxy_password')stdout, stderr = ssh_with_proxy.exec_command('ls -l')print(stdout)ssh_with_proxy.close()'''# 连接多个服务器执行多个命令servers = {'192.168.56.10': {'port': 22,'username': 'root','password': '123'},'192.168.56.11': {'port': 22,'username': 'root','password': '123'},'192.168.56.12': {'port': 22,'username': 'root','password': '123'},}commands = ['ls -l','cd xxx',]for ip, info in servers.items():ssh = SSHClient(hostname=ip, port=info.get('port'), username=info.get('username'), password=info.get('password'))for command in commands:stdout, stderr = ssh.exec_command(command)print(stdout)ssh.close()

(4)SFTP简单封装

#!/usr/bin/env python
# coding:utf-8
from stat import *
import os
import paramikoclass RemotLHost(object):'''封装一个远程Linux主机类,并将paramiko远程上传下载单个文件或目录的行为封装为其相应的方法'''# 通过IP, 用户名,密码,超时时间初始化一个远程Linux主机def __init__(self, ip, username, password, timeout=30):self.ip = ipself.username = usernameself.password = passwordself.timeout = timeout# transportself.t = None# 链接失败的重试次数self.conn_times = 3# get单个文件def sftp_get(self, remotefile, localfile):t = paramiko.Transport((self.ip, 22))t.connect(username=self.username, password=self.password)sftp = paramiko.SFTPClient.from_transport(t)sftp.get(remotefile, localfile)t.close()# put单个文件def sftp_put(self, localfile, remotefile):t = paramiko.Transport((self.ip, 22))t.connect(username=self.username, password=self.password)sftp = paramiko.SFTPClient.from_transport(t)sftp.put(localfile, remotefile)t.close()# 获取远端linux主机上指定目录及其子目录下的所有文件def __get_all_files_in_remote_dir(self, sftp, remote_dir):# 保存所有文件的列表all_files = list()# 去掉路径字符串最后的字符'/',如果有的话if remote_dir[-1] == '/':remote_dir = remote_dir[0:-1]# 获取当前指定目录下的所有目录及文件,包含属性值files = sftp.listdir_attr(remote_dir)for x in files:# remote_dir目录中每一个文件或目录的完整路径filename = remote_dir + '/' + x.filenameprint("remote file is "+ filename)# 如果是目录,则递归处理该目录,这里用到了stat库中的S_ISDIR方法,与linux中的宏的名字完全一致if S_ISDIR(x.st_mode):all_files.extend(self.__get_all_files_in_remote_dir(sftp, filename))else:all_files.append(filename)return all_filesdef sftp_get_dir(self, remote_dir, local_dir):t = paramiko.Transport((self.ip, 22))t.connect(username=self.username, password=self.password)sftp = paramiko.SFTPClient.from_transport(t)# 获取远端linux主机上指定目录及其子目录下的所有文件all_files = self.__get_all_files_in_remote_dir(sftp, remote_dir)# 依次get每一个文件for x in all_files:filename = x.replace(remote_dir, "")if os.name=="nt":filename = filename.replace('/',os.sep).lstrip(os.sep)local_filename = os.path.join(local_dir, filename)filepath=os.sep.join(local_filename.split(os.sep)[0:-1])if not os.path.exists(filepath):os.mkdir(filepath)print(u'Get  <------- %s'% x)sftp.get(x, local_filename)#获取本地指定目录及其子目录下的所有文件def __get_all_files_in_local_dir(self, local_dir):# 保存所有文件的列表all_files = list()# 获取当前指定目录下的所有目录及文件,包含属性值files = os.listdir(local_dir)for x in files:# local_dir目录中每一个文件或目录的完整路径filename = os.path.join(local_dir, x)# 如果是目录,则递归处理该目录if os.path.isdir(filename):all_files.extend(self.__get_all_files_in_local_dir(filename))else:all_files.append(filename)return all_filesdef sftp_put_dir(self, local_dir, remote_dir):if remote_dir[-1] != '/':remote_dir = remote_dir + "/"t = paramiko.Transport((self.ip, 22))t.connect(username=self.username, password=self.password)sftp = paramiko.SFTPClient.from_transport(t)for root, dirs, files in os.walk(local_dir):for filespath in files:local_file = os.path.join(root, filespath)a=local_file.replace(local_dir, '')if os.name=="nt":a = a.replace('\\','/').lstrip('/')remote_file = os.path.join(remote_dir, a)try:sftp.put(local_file,remote_file)except Exception as e:sftp.mkdir(os.path.split(remote_file)[0])sftp.put(local_file,remote_file)print("Put %s to remote %s" % (local_file, remote_file))for name in dirs:local_path = os.path.join(root, name)a = local_path.replace(local_dir, '')if os.name=="nt":a = a.replace('\\','/').lstrip('/')remote_path = os.path.join(remote_dir, a)try:sftp.mkdir(remote_path)print("mkdir path %s" % remote_path)except Exception as e:print(e)t.close()if __name__ == '__main__':host = RemotLHost('192.168.56.10', 'root', 'vagrant')remote_path = '/root/doc'local_path = 'D:\\test'# 将远端remote_path目录中的所有文件get到本地local_path目录host.sftp_get_dir(remote_path, local_path)# 将本地local_path目录中的所有文件put到远端remote_path目录local_path= 'D:\ltest'remote_path = '/root/doc2'host.sftp_put_dir(local_path, remote_path)

参考资料

https://blog.csdn.net/weixin_41238626/article/details/138603792

相关文章:

  • 【信创,国产化】信息化系统信创改造,国产化改造方案,云建设
  • 鸿蒙NEXT开发-ArkUI(基于最新api12稳定版)
  • Vue Element UI 打包上线后icon偶发性乱码问题
  • 鸿蒙NEXT入门到实战(基于最新api12稳定版)
  • C语言常用标准库 -- 5.<time.h>
  • 使用fastapi搭建ChatGPT对话后台
  • 前端规范工程-5:Git提交信息规范(commitlint + czg)
  • 企业数据安全从0到1建设方法
  • sql server每天定时执行sql语句
  • RabbitMQ 界面管理说明
  • 【Orange Pi 5嵌入式应用编程】-用户空间GPIO控制
  • Lenovo SR850服务器亮黄灯维修和升级CPU扩展模块
  • qt使用QDomDocument读写xml文件
  • SpringBoot 流式输出时,正常输出后为何突然报错?
  • 《Windows PE》3.2.3 NT头-扩展头
  • ECMAScript6(0):ES6简明参考手册
  • es6--symbol
  • express.js的介绍及使用
  • Magento 1.x 中文订单打印乱码
  • Mysql5.6主从复制
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • python docx文档转html页面
  • socket.io+express实现聊天室的思考(三)
  • SSH 免密登录
  • Vue.js 移动端适配之 vw 解决方案
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 从PHP迁移至Golang - 基础篇
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 关于Java中分层中遇到的一些问题
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 回顾2016
  • 设计模式走一遍---观察者模式
  • 实习面试笔记
  • 再谈express与koa的对比
  • k8s使用glusterfs实现动态持久化存储
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​用户画像从0到100的构建思路
  • ###STL(标准模板库)
  • #{}和${}的区别是什么 -- java面试
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (10)ATF MMU转换表
  • (PySpark)RDD实验实战——求商品销量排行
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (二)丶RabbitMQ的六大核心
  • (简单) HDU 2612 Find a way,BFS。
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)LINQ之路
  • ****三次握手和四次挥手
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET CF命令行调试器MDbg入门(一)
  • .NET Core WebAPI中封装Swagger配置