简单主机批量管理工具(这里实现了paramiko 用su切换到root用户) 泽桐

项目名:简单主机批量管理工具

一、需求

1主机分组

2可批量执行命令、发送文件,结果实时返回,执行格式如下

batch_run  -h h1,h2,h3   -g web_clusters,db_servers    -cmd  "df -h" 

batch_scp   -h h1,h2,h3   -g web_clusters,db_servers  -action put  -local test.py  -remote /tmp/ 

3、主机用户名密码、端口可以不同

 

二、设计表结构(model原型)

 

 

三、代码结构

 

model.py  表结构(model)

 1 # -*- coding: utf-8 -*-
 2 from lib import commons
 3 from multiprocessing import Lock
 4 
 5 
 6 class Host(object):
 7     MUTEX = Lock()
 8 
 9     def __init__(self, host, port, user, password):
10         self.MUTEX.acquire()
11         self.hostId = commons.create_id('host')
12         self.host = host
13         self.port = port
14         self.user = user
15         self.password = password
16         self.MUTEX.release()
17 
18     def __eq__(self, other):
19         res = False
20         if type(other) == type(self):
21             if self.host == other.host:
22                 res = True
23         return res
24 
25     def __str__(self):
26         return 'hostId:%s host:%s' % (self.hostId, self.host)
27 
28 
29 class Group(object):
30     MUTEX = Lock()
31 
32     def __init__(self, groupName):
33         self.MUTEX.acquire()
34         self.groupId = commons.create_id('group')
35         self.groupName = groupName
36         self.MUTEX.release()
37 
38     def __eq__(self, other):
39         res = False
40         if type(other) == type(self):
41             if self.groupName == other.groupName:
42                 res = True
43         return res
44 
45     def __str__(self):
46         return 'groupId:%s group:%s' % (self.groupId, self.groupName)
47 
48 
49 class Group2Host(object):
50     MUTEX = Lock()
51 
52     def __init__(self, hostId, groupId):
53         self.MUTEX.acquire()
54         self.g2hId = commons.create_id('group2Host')
55         self.hostId = hostId
56         self.groupId = groupId
57         self.MUTEX.release()
58 
59     def __eq__(self, other):
60         res = False
61         if type(other) == type(self):
62             if self.hostId == other.hostId and self.groupId == other.groupId:
63                 res = True
64         return res
65 
66     def __str__(self):
67         return 'g2hId:%s group2Host:%s' % (self.g2hId, (self.hostId, self.groupId),)
model.py

main.py(这里实现了paramiko 用su - root 切换到root用户,再继续执行命令)

  1 # Author:ton
  2 # -*- coding: utf-8 -*-
  3 import paramiko
  4 import os
  5 import threading
  6 import shelve
  7 import re
  8 import time
  9 import xlrd
 10 import xlwt
 11 import json
 12 from conf import settings
 13 from models import models
 14 from core.db_handler import Db_handler
 15 from core.color import Colors
 16 from core import logger
 17 from threading import Thread
 18 
 19 
 20 # paramiko.util.log_to_file(os.path.join(settings.LOG_PATH, 'paramiko.log'))
 21 class Ideploy(object):
 22     def __init__(self):
 23         self.initDb()
 24         self.logger = logger.logger('MyIdeploy.log')
 25         self.host_db = shelve.open(os.path.join(settings.HOST_TABLE_PATH, 'host'))
 26         self.group_db = shelve.open(os.path.join(settings.GROUP_TABLE_PATH, 'group'))
 27         self.g2h_db = shelve.open(os.path.join(settings.G2H_TABLE_PATH, 'group2Host'))
 28         # 默认有default主机组
 29         self.default_group_obj = Db_handler.getGroupObjByGroupName(self.group_db, 'default')
 30         if not self.default_group_obj:
 31             self.default_group_obj = models.Group('default')
 32             Db_handler.insert_group(self.group_db, self.default_group_obj)
 33         self.thread_list = []
 34         self.instructions()
 35         self.run()
 36         self.host_db.close()
 37         self.group_db.close()
 38         self.g2h_db.close()
 39 
 40     @staticmethod
 41     def exit():
 42         exit('Bye')
 43 
 44     @staticmethod
 45     def instructions():
 46         """使用说明"""
 47         msg = """
 48         1、在conf/setttings下配置好需要暴力尝试密码的password_list和host_list
 49         2、在Terminal终端运行工具:python bin/ideploy.py -t start
 50         3、输入violentCipher,回车,完成后提示"暴力尝试密码完毕!"
 51         4、输入manageHosts,回车,可以查看管理暴力尝试密码成功的主机列表,记住默认主机组(default)的groupId为1,输入b,退出
 52         5、输入executeCommand,回车,输入批量执行命令:batch_run -g 1 -cmd "hostname",该hostname命令执行的主机对象为默认主机组(default)下的所有主机
 53         6、输入show_task,回车,可以看到批量执行命令的结果
 54         7、继续输入批量执行命令:batch_scp -g 1 -action put -local __init__.py -remote /tmp/target.py,把本地文件__init__.py上传至远端/tmp/下,并取名为target.py
 55         8、输入show_task,回车,可以看到批量执行上传文件的结果
 56         9、输入q,退出批量执行命令的界面,输入exit,退出程序
 57         """
 58         print(msg)
 59 
 60     @staticmethod
 61     def initDb():
 62         """初始化数据库、日志目录"""
 63         # 初始化各表目录及其自增长ID记录文件
 64         for table_name in settings.TABLE_LIST:
 65             table_path = os.path.join(settings.DATABASE_PATH, table_name)
 66             table_id_file = os.path.join(table_path, 'countId')
 67             if not os.path.isdir(table_path):  # 创建数据文件路径
 68                 os.mkdir(table_path)
 69             if not os.path.isfile('%s.dat' % table_id_file):  # 创建自增长ID记录文件
 70                 data_dic = shelve.open(table_id_file)
 71                 data_dic['id'] = '0'
 72                 data_dic.close()
 73         # 初始化日志目录
 74         if not os.path.isdir(os.path.join(settings.BASE_PATH, 'logs')):
 75             os.mkdir(os.path.join(settings.BASE_PATH, 'logs'))
 76 
 77     def run(self):
 78         while True:
 79             print("欢迎来到Ideploy".center(45, '-'))
 80             msg = """
 81                 violentCipher暴力尝试密码
 82                 createGroups创建主机组
 83                 manageHosts管理主机
 84                 executeCommand批量执行命令
 85                 exportHostToExcel导出主机信息到excel表
 86                 importHostFromExcel从excel表导入主机信息
 87                 exit退出
 88             """
 89             print(Colors(msg))
 90             print('thread number:%s' % threading.active_count())
 91             print("".center(50, '-'))
 92             choice = input('输入命令>>').strip()
 93             if hasattr(self, choice):
 94                 getattr(self, choice)()
 95 
 96     def violentCipher(self):
 97         """为每个主机分配线程尝试ssh密码"""
 98         for host in settings.host_list:
 99             # 多线程尝试ssh密码
100             t = Thread(target=self.tryPasswordForHost, args=(host, settings.port, settings.user))
101             t.setDaemon(True)
102             self.thread_list.append(t)
103             # 单线程尝试ssh密码
104             # self.try_password_for_host(ip, settings.port, settings.user)
105         for t in self.thread_list:
106             t.start()
107         for t in self.thread_list:
108             t.join()
109         self.thread_list = []
110         print(Colors('暴力尝试密码完毕!输入"manageHosts"可以管理主机', 'green'))
111 
112     def tryPasswordForHost(self, host, port, user):
113         """循环ssh密码列表尝试密码,并把正确密码保存文件"""
114         password_list = settings.password_list
115         for passwd in password_list:
116             try:
117                 ssh = paramiko.SSHClient()
118                 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
119                 ssh.connect(hostname=host, port=port, username=user, password=passwd, timeout=3)
120                 msg = 'correct ip:%s user:%s password:%s' % (host, user, passwd)
121                 print(Colors(msg, 'green'))
122                 # 更新host、g2h表
123                 host_obj = models.Host(host, port, user, passwd)
124                 Db_handler.update_host(self.host_db, host_obj)
125                 return_host_obj = Db_handler.check_unique_host(self.host_db, host_obj)
126                 if return_host_obj:
127                     host_obj = return_host_obj
128                 Db_handler.insert_g2h(self.g2h_db, host_obj, self.default_group_obj)
129                 break
130             except KeyError as e:
131                 raise e  # 调试
132             except Exception as e:
133                 print(Colors(str(e), 'red'))
134                 msg = 'wrong ip:%s user:%s password:%s' % (host, user, passwd)
135                 print(Colors(msg, 'red'))
136             finally:
137                 ssh.close()
138 
139     def checkPassword(self):
140         """检查ssh密码和root密码的有效性"""
141         pass
142 
143     def exportHostToExcel(self):
144         """从数据库导出所有主机信息到excel表里"""
145         # 创建workbook和sheet对象
146         workbook = xlwt.Workbook()  # 注意Workbook的开头W要大写
147         sheet1 = workbook.add_sheet('sheet1', cell_overwrite_ok=True)
148         # 向sheet页中写入列名数据
149         column_names = ['host', 'groupName', 'user', 'password', 'port']
150         for index, col in enumerate(column_names):
151             sheet1.write(0, index, col)
152         # 读取数据库,按group读取host
153         group_list = []
154         for key in self.group_db:
155             group_list.append(self.group_db[key])
156         group_list.sort(key=lambda group_obj: group_obj.groupId, reverse=False)  # 根据groupId排序
157         for g_obj in group_list:
158             # 根据主机组Id,获取该主机组所有主机Obj列表
159             host_list = Db_handler.getHostObjListByGroupId(self.host_db, self.g2h_db, g_obj.groupId)
160             host_list.sort(key=lambda obj: obj.host, reverse=False)  # 根据主机的ip排序
161             # 向sheet页中写入host数据
162             for row_num, host_obj in enumerate(host_list, 1):
163                 col_values = [host_obj.host, g_obj.groupName, host_obj.user, host_obj.password, host_obj.port]
164                 for col_num, col_val in enumerate(col_values):
165                     sheet1.write(row_num, col_num, col_val)
166         workbook.save(os.path.join(settings.BASE_PATH, 'hosts.xls'))
167         print(Colors('导出成功!导出文件:%s' % os.path.join(settings.BASE_PATH, 'hosts.xls'), 'green'))
168 
169     def importHostFromExcel(self):
170         """从excel表中导入主机信息并存入数据库"""
171         # 打开一个workbook
172         workbook = xlrd.open_workbook(os.path.join(settings.BASE_PATH, 'hosts.xls'))
173         # 定位到sheet1
174         sheet1 = workbook.sheets()[0]
175         # 遍历sheet1中所有行row
176         num_rows = sheet1.nrows
177         for row_num in range(1, num_rows):
178             row_val = sheet1.row_values(row_num)
179             group_obj = Db_handler.getGroupObjByGroupName(self.group_db, row_val[1])
180             if group_obj:
181                 host_obj = models.Host(row_val[0], int(row_val[4]), row_val[2], row_val[3])
182                 Db_handler.update_host(self.host_db, host_obj)
183                 return_host_obj = Db_handler.check_unique_host(self.host_db, host_obj)
184                 if return_host_obj:
185                     host_obj = return_host_obj
186                     Db_handler.insert_g2h(self.g2h_db, host_obj, group_obj)
187             else:
188                 print(Colors('没有该主机组名[%s]' % row_val[1], 'red'))
189         else:
190             print(Colors("导入成功!请输入'manageHosts'查看导入的主机", 'green'))
191 
192     def createGroups(self):
193         while True:
194             create_groupName = input('请输入需要创建的主机组名(b退出):').strip()
195             if not create_groupName: continue
196             if create_groupName == 'b': break
197             create_group = models.Group(create_groupName)
198             result_code = Db_handler.insert_group(self.group_db, create_group)
199             if result_code:
200                 print(Colors('创建主机组成功', 'green'))
201             else:
202                 print(Colors('该主机组已存在', 'red'))
203 
204     def manageHosts(self):
205         """分配主机到主机组"""
206         # 解析分配的hostId和groupId,判断是否存在
207         while True:
208             print('所有主机信息如下:')
209             self.displayHosts()
210             choice_action = input('请输入要对主机组执行的操作(add添加,del删除,b退出):').strip()
211             if choice_action == 'b':
212                 break
213             elif choice_action != 'add' and choice_action != 'del':
214                 continue
215             quit_flag = True
216             while quit_flag:
217                 choice_hostIds = input('请输入hostId(用空格隔开)(b退出):').strip()
218                 if not choice_hostIds: continue
219                 if choice_hostIds == 'b': break
220                 hostId_list = choice_hostIds.split()
221                 exist_flag = True
222                 for hostId in hostId_list:
223                     if hostId not in self.host_db:
224                         exist_flag = False
225                         print(Colors('输入要操作的hostId:%s 不存在' % hostId, 'red'))
226                 if not exist_flag: continue
227                 while quit_flag:
228                     choice_groupId = input('请输入要操作的groupId(b退出):').strip()
229                     if not choice_groupId: continue
230                     if choice_groupId == 'b': break
231                     if choice_groupId not in self.group_db:
232                         print(Colors('输入的groupId:%s 不存在' % choice_groupId, 'red'))
233                         continue
234                     # 开始更新g2h表
235                     for hostId in hostId_list:
236                         if choice_action == 'add':
237                             Db_handler.insert_g2h(self.g2h_db, self.host_db[hostId], self.group_db[choice_groupId])
238                         else:
239                             Db_handler.delete_g2h(self.g2h_db, self.host_db[hostId], self.group_db[choice_groupId])
240                     print(Colors('配置成功', 'green'))
241                     quit_flag = False
242 
243     def displayHosts(self):
244         """展示管理的主机"""
245         group_list = []
246         for key in self.group_db:
247             group_list.append(self.group_db[key])
248         group_list.sort(key=lambda group_obj: group_obj.groupId, reverse=False)  # 根据groupId排序
249         for g_obj in group_list:
250             # 根据主机组Id,获取该主机组所有主机Obj列表
251             host_list = Db_handler.getHostObjListByGroupId(self.host_db, self.g2h_db, g_obj.groupId)
252             print(Colors(
253                 'Group:%s[%d](groupId:%s)' % (g_obj.groupName, len(host_list), g_obj.groupId), 'cyan'))
254             host_list.sort(key=lambda obj: obj.host, reverse=False)  # 根据主机的ip排序
255             for host_obj in host_list:
256                 print('\t%s' % host_obj)
257 
258     def executeCommand(self):
259         """批量执行ssh命令"""
260         SSHClient(self)
261 
262 
263 class TaskList(list):
264     def __init__(self, item=()):
265         super().__init__(item)
266         self.logger = logger.logger('task_list')
267 
268     def append(self, p_object):
269         if not isinstance(p_object, dict):
270             raise TypeError
271         super().append(p_object)
272         # with open(os.path.join(settings.BASE_PATH, 'task_list'), 'a') as f:
273         #     f.write(json.dumps(p_object) + '\n')
274         self.logger.info(json.dumps(p_object))
275 
276 
277 class SSHClient(object):
278     def __init__(self, ideploy_obj):
279         self.ideploy_obj = ideploy_obj
280         self.task_list = TaskList()
281         self.interactive()
282 
283     @staticmethod
284     def help_msg():
285         """ssh命令帮助信息"""
286         msg = """注意:-h 后为hostId,-g 后为groupId
287         batch_run -h 1,2,3 -g 1,2 -cmd "df -h"
288         batch_scp -h 1,2,3 -g 1,2 -action put -local test.py -remote /tmp/ 
289         show_task  查看ssh命令结果
290         """
291         print(msg)
292 
293     def interactive(self):
294         while True:
295             print('\n thread number:%s' % threading.active_count())
296             cmd = input(Colors('批量执行命令>>', 'cyan')).strip()
297             if not cmd: continue
298             if cmd == 'q': break
299             if hasattr(self, cmd[:9]):
300                 getattr(self, cmd[:9])(cmd[9:].strip())
301             else:
302                 self.help_msg()
303 
304     @staticmethod
305     def create_task_dic(hostId, host, command, result, date):
306         task_dic = {
307             'hostId': hostId,
308             'host': host,
309             'command': command,
310             'result': result,
311             'date': date,
312         }
313         return task_dic
314 
315     def show_task(self, cmd):
316         for task_dic in self.task_list:
317             print(
318                 '\033[36m(hostId:%s)host:\033[0m%s \033[36mcommand:\033[0m%s \033[36mresult:\033[0m\n%s \033[36mdate:\033[0m%s' % (
319                     task_dic['hostId'], task_dic['host'], task_dic['command'], task_dic['result'], task_dic['date']))
320 
321     def batch_run(self, cmd):
322         """批量执行batch_run命令"""
323         argv_dic = self.parse_run_command(cmd)
324         if argv_dic['cmd']:
325             self.batch('batch_run', argv_dic)
326         else:
327             self.help_msg()
328 
329     def connect_batch_run(self, host_obj, argv_dic):
330         """与ssh服务端通讯执行远程ssh命令"""
331         ssh = paramiko.SSHClient()
332         try:
333             ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
334             ssh.connect(hostname=host_obj.host, port=host_obj.port, username=host_obj.user, password=host_obj.password,
335                         timeout=5)
336             channel = ssh.invoke_shell()
337             result = ''
338             if host_obj.user != 'root':
339                 # channel.send("sudo su - \n")
340                 channel.send("su - \n")
341                 # 下面几行代码是发送 su - root命令时所需要输入的root密码,配置了/etc/sudoers NOPASSWD就不用密码了
342                 while not re.search(r'(P|p)assword: $', result):
343                     result += channel.recv(8196).decode('utf-8')
344                 self.ideploy_obj.logger.info(b"++" + result.encode('utf-8') + b'++')
345                 result = ''
346                 channel.send('%s\n' % settings.root_pwd)
347             while not re.search(r'#[^#]{0,13}$', result):
348                 result += channel.recv(8196).decode('utf-8')
349             self.ideploy_obj.logger.info(b"++" + result.encode('utf-8') + b'++')
350             result = ''
351             channel.send('%s\n' % argv_dic['cmd'])
352             while not re.search(r'#[^#]{0,13}$', result):
353                 result += channel.recv(8196).decode('utf-8')
354             self.ideploy_obj.logger.info(b"++" + result.encode('utf-8') + b'++')
355             result_list = re.findall(r".*\n", result)[1:]
356             result = ''.join(result_list)
357             channel.close()
358             self.task_list.append(self.create_task_dic(host_obj.hostId, host_obj.host,
359                                                        argv_dic['cmd'], result,
360                                                        time.strftime("%Y-%m-%d %X", time.localtime())))
361         except Exception as e:
362             self.task_list.append(
363                 self.create_task_dic(host_obj.hostId, host_obj.host, argv_dic['cmd'], str(e),
364                                      time.strftime("%Y-%m-%d %X", time.localtime())))
365         finally:
366             ssh.close()
367 
368     def connect_batch_scp(self, host_obj, argv_dic):
369         """与ssh服务端建立sftp通道执行远程scp命令"""
370         try:
371             transport = paramiko.Transport((host_obj.host, host_obj.port))
372             transport.connect(username=host_obj.user, password=host_obj.password, )
373             sftp = paramiko.SFTPClient.from_transport(transport)
374             if argv_dic['action'] == 'put':
375                 # 将location.py 上传至服务器 /tmp/test.py
376                 sftp.put(argv_dic['local'], argv_dic['remote'])
377             else:
378                 # 将remove_path 下载到本地 local_path
379                 sftp.get(argv_dic['remote'], argv_dic['local'])
380             self.task_list.append(
381                 self.create_task_dic(host_obj.hostId, host_obj.host,
382                                      'action[%s] local[%s] remote[%s]' % (
383                                          argv_dic['action'], argv_dic['local'], argv_dic['remote']), 'OK',
384                                      time.strftime("%Y-%m-%d %X", time.localtime())))
385         except Exception as e:
386             self.task_list.append(
387                 self.create_task_dic(host_obj.hostId, host_obj.host,
388                                      'action[%s] local[%s] remote[%s]' % (
389                                          argv_dic['action'], argv_dic['local'], argv_dic['remote']), str(e),
390                                      time.strftime("%Y-%m-%d %X", time.localtime())))
391         finally:
392             try:
393                 transport.close()
394             except UnboundLocalError:
395                 pass
396 
397     def batch(self, batch_type, argv_dic):
398         """为每个host分配一个线程去连接ssh服务端批量执行batch_run或batch_scp命令"""
399         finished_hostId_list = []
400         batch_type_func = 'connect_%s' % batch_type
401         if argv_dic.get('group_list'):
402             for groupId in argv_dic['group_list']:
403                 if groupId in self.ideploy_obj.group_db:
404                     host_list = Db_handler.getHostObjListByGroupId(self.ideploy_obj.host_db, self.ideploy_obj.g2h_db,
405                                                                    groupId)
406                     for host_obj in host_list:
407                         t = Thread(target=getattr(self, batch_type_func), args=(host_obj, argv_dic))
408                         t.setDaemon(True)
409                         t.start()
410                         finished_hostId_list.append(host_obj.hostId)
411                 else:
412                     self.task_list.append(self.create_task_dic("groupId[%s]" % groupId, None,
413                                                                None, "groupId[%s] is not exist" % groupId,
414                                                                time.strftime("%Y-%m-%d %X", time.localtime())))
415         if argv_dic.get('host_list'):
416             for hostId in argv_dic['host_list']:
417                 if hostId in self.ideploy_obj.host_db:
418                     if hostId not in finished_hostId_list:
419                         t = Thread(target=getattr(self, batch_type_func),
420                                    args=(self.ideploy_obj.host_db[hostId], argv_dic))
421                         t.setDaemon(True)
422                         t.start()
423                 else:
424                     self.task_list.append(self.create_task_dic(hostId, None,
425                                                                None, "hostId[%s] is not exist" % hostId,
426                                                                time.strftime("%Y-%m-%d %X", time.localtime())))
427 
428     def batch_scp(self, cmd):
429         """批量执行batch_scp命令"""
430         argv_dic = self.parse_scp_command(cmd)
431         if argv_dic['action'] and argv_dic['local'] and argv_dic['remote']:
432             self.batch('batch_scp', argv_dic)
433         else:
434             self.help_msg()
435 
436     @staticmethod
437     def parse_target(cmd):  # -h h1,h2,h3 -g web_clusters,db_servers -cmd "df -h"
438         """解析-h、-g参数,获取主机、主机组列表"""
439         host_str = re.match(r"-h[ ]+[^-]+", cmd)
440         host_list = host_str.group().strip()[2:].strip().replace(r" ", "").split(",") if host_str else None
441         group_str = re.search(r"-g[ ]+[^-]+", cmd)
442         group_list = group_str.group().strip()[2:].strip().replace(r" ", "").split(",") if group_str else None
443         return host_list, group_list
444 
445     def parse_run_command(self, cmd):  # -h h1,h2,h3 -g web_clusters,db_servers -cmd "df -h"
446         """解析batch_run命令参数"""
447         host_list, group_list = self.parse_target(cmd)
448         real_cmd_str = re.search(r"-cmd[ ]+(\'|\")(?P<cmd>.*)(\'|\")", cmd)
449         if real_cmd_str:
450             real_cmd_dic = real_cmd_str.groupdict()
451             real_cmd_str = real_cmd_dic['cmd'].strip()
452         else:
453             real_cmd_str = None
454         argv_dic = {
455             'host_list': host_list,
456             'group_list': group_list,
457             'cmd': real_cmd_str
458         }
459         return argv_dic
460 
461     def parse_scp_command(self, cmd):  # -h h1,h2,h3 -g web_clusters,db_servers -action put -local test.py -remote /tmp/
462         """解析batch_scp命令参数"""
463         host_list, group_list = self.parse_target(cmd)
464         action_str = re.search(r"-action[ ]+[^-]+", cmd)
465         action_str = action_str.group().strip()[7:].strip() if action_str else None
466         local_str = re.search(r"-local[ ]+[^-]+", cmd)
467         local_str = local_str.group().strip()[6:].strip() if local_str else None
468         remote_str = re.search(r"-remote[ ]+[^-]+", cmd)
469         remote_str = remote_str.group().strip()[7:].strip() if remote_str else None
470         argv_dic = {
471             'host_list': host_list,
472             'group_list': group_list,
473             'action': action_str,
474             'local': local_str,
475             'remote': remote_str
476         }
477         return argv_dic
mian.py

db_handler.py

  1 import shelve
  2 from models import models
  3 from core.color import Colors
  4 from multiprocessing import Lock
  5 
  6 
  7 class Db_handler(object):
  8     HOST_MUTEX = Lock()
  9     GROUP_MUTEX = Lock()
 10     G2H_MUTEX = Lock()
 11 
 12     @staticmethod
 13     # 根据主机组名称,获取该主机组Obj
 14     def getGroupObjByGroupName(group_db, groupName):
 15         for key in group_db:
 16             if group_db[key].groupName == groupName:
 17                 return group_db[key]
 18         return
 19 
 20     @staticmethod
 21     # 根据主机组Id,获取该主机组所有主机Obj列表
 22     def getHostObjListByGroupId(host_db, g2h_db, groupId):
 23         host_list = []
 24         for key in g2h_db:
 25             if g2h_db[key].groupId == groupId:
 26                 host_list.append(host_db[g2h_db[key].hostId])
 27         return host_list
 28 
 29     # 检查主机表唯一性(host字段唯一)(判断一个host对象是否存在)
 30     @classmethod
 31     def check_unique_host(cls, host_db, host_obj):
 32         for key in host_db:
 33             if host_db[key] == host_obj:
 34                 # print('存在host:%s'%host_db[key])
 35                 return host_db[key]
 36         return
 37 
 38     # 检查主机组表唯一性(groupName字段唯一)(判断一个group对象是否存在)
 39     @classmethod
 40     def check_unique_group(cls, group_db, group_obj):
 41         for key in group_db:
 42             if group_db[key] == group_obj:
 43                 # print('存在group:%s'%group_db[key])
 44                 return group_db[key]
 45         return
 46 
 47     # 检查主机组-主机表唯一性(记录中存在重复的hostId和groupId)(判断一个group2Host对象是否存在)
 48     @classmethod
 49     def check_unique_g2h(cls, g2h_db, g2h_obj):
 50         for key in g2h_db:
 51             if g2h_db[key] == g2h_obj:
 52                 # print('存在g2h:%s'%g2h_db[key])
 53                 return g2h_db[key]
 54         return
 55 
 56     # update host table
 57     @classmethod
 58     def update_host(cls, host_db, host_obj):
 59         cls.HOST_MUTEX.acquire()
 60         return_host_obj = cls.check_unique_host(host_db, host_obj)
 61         if not return_host_obj:
 62             host_db[host_obj.hostId] = host_obj
 63             print(Colors('insert host table 1 row', bcolor='green'))
 64         else:
 65             host_obj.hostId = return_host_obj.hostId
 66             host_db[return_host_obj.hostId] = host_obj
 67             print(Colors('update host table 1 row', bcolor='cyan'))
 68         cls.HOST_MUTEX.release()
 69 
 70     # insert group table
 71     @classmethod
 72     def insert_group(cls, group_db, group_obj):
 73         result_code = False
 74         cls.GROUP_MUTEX.acquire()
 75         if not cls.check_unique_group(group_db, group_obj):
 76             group_db[group_obj.groupId] = group_obj
 77             result_code = True
 78             print(Colors('insert group table 1 row', bcolor='green'))
 79         cls.GROUP_MUTEX.release()
 80         return result_code
 81 
 82     # insert g2h table
 83     @classmethod
 84     def insert_g2h(cls, g2h_db, host_obj, group_obj):
 85         result_code = False
 86         cls.G2H_MUTEX.acquire()
 87         g2h_obj = models.Group2Host(host_obj.hostId, group_obj.groupId)
 88         if not cls.check_unique_g2h(g2h_db, g2h_obj):
 89             g2h_db[g2h_obj.g2hId] = g2h_obj
 90             result_code = True
 91             print(Colors('insert g2h table 1 row', bcolor='green'))
 92         cls.G2H_MUTEX.release()
 93         return result_code
 94 
 95     # delete g2h table
 96     @classmethod
 97     def delete_g2h(cls, g2h_db, host_obj, group_obj):
 98         result_code = False
 99         cls.G2H_MUTEX.acquire()
100         for key in g2h_db:
101             if g2h_db[key].hostId == host_obj.hostId and g2h_db[key].groupId == group_obj.groupId:
102                 g2h_db.pop(key)
103                 result_code = True
104                 print(Colors('delete g2h table 1 row', bcolor='yellow'))
105         cls.G2H_MUTEX.release()
106         return result_code
db_handler.py

logger.py

 1 # -*- coding: utf-8 -*-
 2 import logging
 3 import os
 4 from logging import handlers
 5 from conf import settings
 6 
 7 
 8 def logger(log_file):
 9     log_level = settings.log_level
10     if log_level == 'debug':
11         log_level = logging.DEBUG
12     elif log_level == 'info':
13         log_level = logging.INFO
14     elif log_level == 'warning':
15         log_level = logging.WARNING
16     elif log_level == 'error':
17         log_level = logging.ERROR
18     else:
19         log_level = logging.CRITICAL
20     # 1.生成logger对象
21     logger = logging.getLogger(log_file)
22     logger.setLevel(logging.DEBUG)
23     # 2.生成handler对象
24     fh = handlers.TimedRotatingFileHandler(filename=os.path.join(settings.LOG_PATH, log_file),
25                                            when='D', interval=1, backupCount=3)
26     fh.setLevel(log_level)
27     # 2.1 把handler对象绑定到logger
28     if not logger.handlers:
29         logger.addHandler(fh)
30     # 3.生成formatter对象
31     f = logging.Formatter(fmt='%(asctime)s %(name)s [%(levelname)s] %(message)s', datefmt=None)
32     # 3.1 把formatter对象绑定到handler
33     fh.setFormatter(f)
34     return logger
logger.py

color.py

 1 def Colors(text, fcolor=None, bcolor=None, style=None):
 2     """自定义字体样式及颜色"""
 3     # 字体颜色
 4     fg = {
 5         'black': '\033[30m',  # 字体黑
 6         'red': '\033[31m',  # 字体红
 7         'green': '\033[32m',  # 字体绿
 8         'yellow': '\033[33m',  # 字体黄
 9         'blue': '\033[34m',  # 字体蓝
10         'magenta': '\033[35m',  # 字体紫
11         'cyan': '\033[36m',  # 字体青
12         'white': '\033[37m',  # 字体白
13         'end': '\033[0m'  # 默认色
14     }
15     # 背景颜色
16     bg = {
17         'black': '\033[40m',  # 背景黑
18         'red': '\033[41m',  # 背景红
19         'green': '\033[42m',  # 背景绿
20         'yellow': '\033[43m',  # 背景黄
21         'blue': '\033[44m',  # 背景蓝
22         'magenta': '\033[45m',  # 背景紫
23         'cyan': '\033[46m',  # 背景青
24         'white': '\033[47m',  # 背景白
25     }
26     # 内容样式
27     st = {
28         'bold': '\033[1m',  # 高亮
29         'url': '\033[4m',  # 下划线
30         'blink': '\033[5m',  # 闪烁
31         'seleted': '\033[7m',  # 反显
32     }
33 
34     if fcolor in fg:
35         text = fg[fcolor] + text + fg['end']
36     if bcolor in bg:
37         text = bg[bcolor] + text + fg['end']
38     if style in st:
39         text = st[style] + text + fg['end']
40     return text
color.py

settings.py

 1 # Author:ton
 2 # -*- coding: utf-8 -*-
 3 import os
 4 
 5 BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 6 LOG_PATH = os.path.join(BASE_PATH, 'logs')
 7 DATABASE_PATH = os.path.join(BASE_PATH, 'db')
 8 HOST_TABLE_PATH = os.path.join(DATABASE_PATH, 'host')
 9 GROUP_TABLE_PATH = os.path.join(DATABASE_PATH, 'group')
10 G2H_TABLE_PATH = os.path.join(DATABASE_PATH, 'group2Host')
11 TABLE_LIST = ['host', 'group', 'group2Host']
12 
13 
14 # 暴力破解配置项
15 user = 'sshusr'
16 password_list = ['123', 'sshusr123', '123456', ]
17 host_list = ['10.0.0.11', '10.0.0.12', '10.0.0.13', '10.0.0.14']
18 port = 22
19 root_pwd = '123456'
20 
21 # 日志记录配置项
22 log_level = 'debug'
settings.py

四、使用说明

1、在conf/setttings下配置好需要暴力尝试密码的password_list和host_list
2、在Terminal终端运行工具:python bin/ideploy.py -t start
3、输入violentCipher,回车,完成后提示"暴力尝试密码完毕!"
4、输入manageHosts,回车,可以查看管理暴力尝试密码成功的主机列表,记住默认主机组(default)的groupId为1,输入b,退出
5、输入executeCommand,回车,输入批量执行命令:batch_run -g 1 -cmd "hostname",该hostname命令执行的主机对象为默认主机组(default)下的所有主机
6、输入show_task,回车,可以看到批量执行命令的结果
7、继续输入批量执行命令:batch_scp -g 1 -action put -local __init__.py -remote /tmp/target.py,把本地文件__init__.py上传至远端/tmp/下,并取名为target.py
8、输入show_task,回车,可以看到批量执行上传文件的结果
9、输入q,退出批量执行命令的界面,输入exit,退出程序

截图:

PS:任务列表(show_task)会同时记录到logs/task_list文件,永久保存


 

原文地址:https://www.cnblogs.com/linzetong/p/8290133.html