通过封装Paramiko这个SSH模块,我们可以实现远程批量管理Linux主机,在上一篇文章中我们封装过一个MySSH类,这个类可以执行命令上传下载文件等,我们在这个类的基础上,实现一个简单的任务执行功能。

  • 执行方式
  • 程序会在Json文件中解析参数,并将参数与所对应的主机进行关联,对不同的主机组执行不同的命令,实现批量脚本执行。

实现批量命令执行: 首先利用封装好的MySSH类为基础,实现一个批量命令执行器,该工具通过命令行参数传递执行不同的操作。

import os,json,sys
from MySSH import MySSH def ping(group):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:6} \t {2:5}".format("IP地址", "用户名", "状态"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.GetPing()
if ref == True:
print("{0:15} \t {1:6} \t {2:5}".format(x[0],x[1],"已连接"))
else:
print("{0:15} \t {1:6} \t {2:5}".format(x[0], x[1], "未连接"))
print("\n") def run(group,command):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.BatchCMD(command)
print("\n")
print("-" * 120)
print("执行IP: {0:15} ".format(x[0]))
print("-" * 120)
print(ref) def memory(group):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format("IP地址", "总内存", "剩余内存", "利用率(百分比)"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.GetAllMemSpace()
if ref != None:
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format(x[0],ref["Total"],ref["Free"],ref["Percentage"])) def disk(group):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
print("-" * 120)
print("IP地址: {0:15} \t".format(x[0]))
print("-" * 120) ref = ssh.GetAllDiskSpace()
if len(ref) !=0:
for k,v in ref.items():
print("磁盘路径: {0:30} \t 磁盘利用率: {1:8}".format(k,v)) def cpu(group):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format("IP地址", "用户态", "内核态", "空闲率(百分比)"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.GetCPUPercentage()
if len(ref)!=0:
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format(x[0], ref["us"], ref["sys"], ref["idea"])) def load_avg(group):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format("IP地址", "一分钟负载", "五分钟负载", "十五分钟负载"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.GetLoadAVG()
if len(ref)!=0:
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format(x[0], ref["1avg"], ref["5avg"], ref["15avg"])) def checkproc(group,proc):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format("IP地址", "PID号","CPU占用率", "内存占用率"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.CheckProcessName(proc)
if len(ref):
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format(x[0], ref["PID"], ref["CPU"], ref["Mem"]))
else:
print("{0:15} \t {1:7} \t {2:7} \t {3:5} \t".format(x[0], 0, 0, 0)) def put_group(group,src,dst):
with open("config.json" , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
ptr = config_load.get(group)
print("-" * 120)
print("{0:15} \t {1:7} \t {2:7} \t ".format("IP地址", "源文件","传输到"))
print("-" * 120) for x in ptr:
ssh = MySSH(x[0],x[1],x[2],22)
ssh.Init()
ref = ssh.PutLocalFile(src,dst)
if ref:
print("{0:15} \t {1:7} \t {2:7} \t ".format(x[0], src,dst)) if __name__ == '__main__':
while True:
try:
cmd = str(input("[LyShark Shell] # ")).split()
cmd_len = len(cmd)
if (cmd == ""):
continue
elif (cmd[0] == "exit"):
exit(1) # ping --group=aix
elif (cmd[0] == "ping"):
if (cmd_len - 1 >= 1):
arg = cmd[1].split("=")[1]
ping(arg) # run --group=aix --cmd=ls
elif (cmd[0] == "run"):
if (cmd_len - 1 >= 2):
arg1 = cmd[1].split("=")[1]
arg2 = cmd[2].split("=")[1]
run(arg1,arg2) # memory --group=aix
elif (cmd[0] =="memory"):
if (cmd_len - 1 >= 1):
arg1 = cmd[1].split("=")[1]
memory(arg1) # disk --group=aix
elif (cmd[0] =="disk"):
if (cmd_len - 1 >= 1):
arg1 = cmd[1].split("=")[1]
disk(arg1) # cpu --group=aix
elif (cmd[0] =="cpu"):
if (cmd_len - 1 >= 1):
arg1 = cmd[1].split("=")[1]
cpu(arg1) # load --group=aix
elif (cmd[0] =="load"):
if (cmd_len - 1 >= 1):
arg1 = cmd[1].split("=")[1]
load_avg(arg1) # checkproc --group=aix --process=bash
elif (cmd[0] =="checkproc"):
if (cmd_len - 1 >= 1):
arg1 = cmd[1].split("=")[1]
arg2 = cmd[2].split("=")[1]
checkproc(arg1,arg2) # put_group --group=aix --src=./aaa.txt --dst=/tmp/aaa.txt
elif (cmd[0] =="put_group"):
if (cmd_len - 1 >= 3):
arg1 = cmd[1].split("=")[1]
arg2 = cmd[2].split("=")[1]
arg3 = cmd[3].split("=")[1]
put_group(arg1,arg2,arg3)
else:
print("[-] error version 1.0")
except Exception:
continue

解析文件config.json配置如下所示,每个组中包括一定数量的机器。

{
"aix":
[
["127.0.0.1","root","1233"],
["127.0.0.1","root","123456"] ],
"suse":
[
["127.0.0.1","root","123123123"]
],
}

程序运行后会进入交互Shell环境,我们可以根据需要执行不同的key获取数据。

此外脚本还支持如下参数.

  • 运行命令: run --group=aix --cmd=ls
  • 内存检查: memory --group=aix
  • 磁盘检查: disk --group=aix
  • CPU检查: cpu --group=aix
  • 负载检查: load --group=aix
  • 进程检查: checkproc --group=aix --process=bash
  • 文件上传: put_group --group=aix --src=./aaa.txt --dst=/tmp/aaa.txt

剧本执行器,这部分内容为扩展部分,我们定义两个函数,函数DisplayAllRule用来获取特定目录下的特定剧本,而RunRule函数则用于解析这个剧本并执行剧本中的命令集合。

import MySSH
import os,json,sys # 获取特定目录下所有的剧本
def DisplayAllRule():
print("{0:15} \t {1:10} \t {2:10} \t {3:15} \t {4:5} \t {5:30}".
format("名称","应用平台","端口","主机组","命令条数","描述信息")) for switch in all_files:
# 首先判断文件结尾是否为Json
if( switch.endswith(".json") == True):
all_switch_dir = rootdir + switch
try:
# 判断文件内部是否符合JSON规范
with open(all_switch_dir , "r" ,encoding="utf-8") as read_file:
# 判断是否存在指定字段来识别规范
load = json.loads(read_file.read())
if load.get("framework") != None and load.get("task_sequence") != None:
print("{0:15} \t {1:10} \t {2:10} \t {3:15} \t {4:5} \t\t {5:30}".
format(switch,load.get("framework"),load.get("default_port"),load.get("Group"),len(load.get("task_sequence")),load.get("describe")))
except ValueError:
pass # 执行命令行
def RunRule(rule_name):
# 先打开配置恩建并读取到数据
with open(config_dir , "r" ,encoding="utf-8") as read_config_ptr:
config_load = json.loads(read_config_ptr.read())
# 接着读取选中剧本
with open(rule_dir,"r",encoding="utf-8") as read_rule_ptr:
rule_load = json.loads(read_rule_ptr.read())
# 先找到组名称,并以组名称查询组内主机数
ref = config_load.get(rule_load.get("Group"))
if ref != None:
# 加载剧本中的任务命令
task_sequence = rule_load.get("task_sequence") # 循环执行针对组内主机
for addr in ref:
print("-" * 130 , "\n针对地址执行: {}\n".format(addr[0]),"-" * 130)
# 每个主机需要执行的命令
for cmd in task_sequence:
ssh = MySSH.MySSH(addr[0],addr[1],addr[2],int(rule_load.get("default_port")))
ssh.Init()
if cmd[0] == "PUT" and len(cmd) >= 3:
if ssh.PutLocalFile(cmd[1],cmd[2]):
print("命令序列: {0} {1}".format("PUT",cmd[2]))
else:
break
else:
ret = ssh.BatchCMD_NotRef(cmd[0])
print("命令序列: {0}".format(cmd[0]))
else:
print("[-] 主机组不存在,无法继续执行.")
exit(0) if __name__ == "__main__":
arg = sys.argv
if arg[1] == "display":
DisplayAllRule()
elif arg[1] == "run":
RunRule(arg[2])

文件规划put_file目录用于存放需要上传的文件,rule目录用来存放执行剧本内容,我们先来看一个编译安装Apache服务器的剧本写法。

{
"framework": "Linux",
"default_port": "22",
"describe": "编译安装Apache组件",
"Group": "MyWebServer",
"task_sequence":
[
["iptables -F"],
["setenforce 0"],
["yum -y install gcc make pcre-devel openssl-devel expat-devel bzip2"], ["PUT","./put_file/httpd-2.4.46.tar.gz","/tmp/apache.tar.gz"],
["PUT","./put_file/apr-1.7.0.tar.bz2","/tmp/apr-1.7.0.tar.bz2"],
["PUT","./put_file/apr-util-1.6.1.tar.bz2","/tmp/apr-util-1.6.1.tar.bz2"], ["tar -xzf /tmp/apache.tar.gz -C /tmp/"],
["tar -xf /tmp/apr-1.7.0.tar.bz2 -C /tmp/"],
["tar -xf /tmp/apr-util-1.6.1.tar.bz2 -C /tmp/"], ["mv /tmp/apr-util-1.6.1 /tmp/httpd-2.4.46/srclib/apr-util"],
["mv /tmp/apr-1.7.0 /tmp/httpd-2.4.46/srclib/apr"], ["/tmp/httpd-2.4.46/configure --prefix=/tmp/httpd --with-zlib -with-included-apr"],
["make && make install"], ["echo 'hello lyshark' > /tmp/httpd/htdocs/index.html"],
["/tmp/httpd/bin/httpd"]
]
}

如上剧本中的Group字段则是需要执行编译安装的所属组,该组内存放执行地址,来看一下组的规划。

{
"MyWebServer":
[
["192.168.191.4","root","1233"],
["192.168.191.5","root","1233"],
["192.168.191.6","root","1233"]
]
}

我们首先可以执行main.py display命令,获取当前设备中的所有剧本信息。

在需要执行时输入main.py run test.json尾部加上剧本名字即可。

Python MySSH 实现剧本执行器的更多相关文章

  1. 《零压力学Python》 之 第三章知识点归纳

    第三章(第一个程序)知识点归纳 编程犹如写剧本.Python函数与剧本差别不大,你可以反复调用函数,而它每次都执行预定的“脚本”(脚本也可以指整个程序). 在Python IDLE中,真正的编程是从编 ...

  2. 大规模数据分析统一引擎Spark最新版本3.3.0入门实战

    @ 目录 概述 定义 Hadoop与Spark的关系与区别 特点与关键特性 组件 集群概述 集群术语 部署 概述 环境准备 Local模式 Standalone部署 Standalone模式 配置历史 ...

  3. 巨蟒python全栈开发-第11阶段 ansible3_3入门playbook剧本

    1.playbook剧本 2.playbook传参 3.setup模块介绍 4.playbook的tags 5.playbook的handlers&&templates模块 6.条件和 ...

  4. ansible的剧本

    ansible的playbook的介绍-yaml ansible的playbook是使用yaml语言写的 YAML标记语言介绍YAML是一个可读性高的用来表达资料序列的格式.YAML参考了其他多种语言 ...

  5. Python实现Paramiko的二次封装

    Paramiko是一个用于执行SSH命令的Python第三方库,使用该库可实现自动化运维的所有任务,如下是一些常用代码的封装方式,多数代码为半成品,只是敲代码时的备份副本防止丢失,仅供参考,目前本人巡 ...

  6. Python任务调度模块 – APScheduler

    APScheduler是一个Python定时任务框架,使用起来十分方便.提供了基于日期.固定时间间隔以及crontab类型的任务,并且可以持久化任务.并以daemon方式运行应用.目前最新版本为3.0 ...

  7. 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL

    周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...

  8. Python学习笔记(2) Python提取《釜山行》人物关系

    参考:http://www.jianshu.com/p/3bd06f8816d7 项目原理:   实验基于简单共现关系,编写 Python 代码从纯文本中提取出人物关系网络,并用Gephi 将生成的网 ...

  9. python自动化测试(3)- 自动化框架及工具

    python自动化测试(3) 自动化框架及工具 1   概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到 ...

随机推荐

  1. python风格对象

    对象表示形式 python提供了两种获取对象字符串表示形式的标准方式 repr()         //便于开发者理解的方式返回对象的字符串表示形式(一般来说满足obj==eval(repr(obj) ...

  2. bzoj4025-二分图【线段树分治,并查集】

    正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 \(n\)个点\(m\)条边,每条边会在一个\(T\)以内的时间段内出现,对于任意一个\(T\)以内的时刻求 ...

  3. Docker小白到实战之Docker网络简单了解一下

    前言 现在对于Docker容器的隔离性都有所了解了,但对容器IP地址的分配.容器间的访问等还是有点小疑问,如果容器的IP由于新启动导致变动,那又怎么才能保证原有业务不会被影响,这就和网络有挂钩了,接下 ...

  4. 三、mybatis多表关联查询和分布查询

    前言 mybatis多表关联查询和懒查询,这篇文章通过一对一和一对多的实例来展示多表查询.不过需要掌握数据输出的这方面的知识.之前整理过了mybatis入门案例和mybatis数据输出,多表查询是在前 ...

  5. Dapr + .NET Core实战(十-终篇)K8S运行Dapr

    工作原理 为了实现在k8s上安装Dapr,Dapr需要部署dapr-sidecar-injector.dapr-operator.dapr-placement和dapr-sentry服务. dapr- ...

  6. android 使用SQLite的基本操作

    Android操作数据库SQLite使用sql语句基本操作 1:自定义自己的SQLiteOpenHelper public class DBHelper extends SQLiteOpenHelpe ...

  7. iptables配置操作

    1.防火墙添加配置规则(正向) vim /etc/sysconfig/iptables 指定服务器的ip访问内访问某个端口 -A INPUT -p tcp -m iprange --src-range ...

  8. ShardingSphere 知识库更新 | 官方样例集助你快速上手

    Apache ShardingSphere 作为 Apache 顶级项目,是数据库领域最受欢迎的开源项目之一.经过 5 年多的发展,ShardingSphere 已获得超 14K Stars 的关注, ...

  9. Hibernate的介绍及入门小案例

    1.Hibernate的诞生 在以前使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是对于大型应用系统的开发,使用JDBC就会显得力不从心,例如对几十,几百张包含几十个字段 ...

  10. Frida-RPC调用

    Python Frida RPC 调用示例 JS_CODE var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs ...