• 简单主机批量管理工具(这里实现了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文件,永久保存

    
    

     

  • 相关阅读:
    阅读任务-阅读笔记-4
    阅读任务-阅读提问-3
    阅读任务-阅读笔记-3
    阅读任务-阅读提问-2
    阅读任务-阅读提问-1
    构建之法:现代软件工程-阅读笔记1
    个人编程作业1-GIT应用
    《构建之法:现代软件工程-阅读笔记》
    课后作业-阅读任务-阅读提问-1
    结对编程项目作业5
  • 原文地址:https://www.cnblogs.com/linzetong/p/8290133.html
Copyright © 2020-2023  润新知