開發要求:
1. 對主機進行批量管理
2. 可對單臺或主機組批量執行命令
3. 可上傳文件到對應的主機或組
4. 使用多線程實現
程序:
1. README
# 功能實現: 1. 對主機進行批量管理 2. 可對單臺或主機組批量執行命令 3. 可上傳文件到對應的主機或組 4. 使用多線程實現 # 目錄結構: batch/ ├── batch_server.py # 啓動程序 ├── conf/ # 配置文件目錄 │ ├── hosts.ini # 主機信息配置文件 │ └── settings.py # 程序配置文件 └── modules/ # 核心模塊 ├── batch_hosts.py # 主機信息模塊 └── execute.py # 執行命令模塊 # 使用說明: 通過序號選擇主機或組,'q'表示返回上一級;
2. 程序結構
3. 程序代碼
啓動程序:
#!/usr/bin/env python # -*- coding:utf-8 -*- import os, configparser from conf import settings from modules import execute from modules import batch_hosts from multiprocessing import Process import threading configfile = settings.configfile conf = configparser.ConfigParser() conf.read(configfile) config = batch_hosts.Config(conf, configfile) if not os.path.isfile(configfile): config.create_conf() if __name__ == '__main__': while True: for index, item in enumerate(conf.sections(), 1): # 循環主機或組信息 print(index, item) choice = input('-->').strip() if not choice: continue if choice == 'q': break if choice.isdigit() == False: print('輸入編號錯誤,請重新輸入。') elif int(choice) > len(conf.sections()) or int(choice) < 1: # 輸入的序號不在主機列表內 print('編號不在列表中,請重新輸入') else: section_host = config.show_host(choice) # 通過choice 作爲section索引獲取主機信息字典 section_index = int(choice) - 1 print('[%s]'.center(30, '*') % conf.sections()[section_index]) for host in section_host: print('主機IP:', host['ip']) print('[請輸入要執行的命令]') while True: command = input('-->').strip() if not command: continue if command == 'q': break process_list = [] # 通過多線程運行,每一臺主機任務通過一個線程去執行 for host in section_host: exec_cmd = execute.ExecCommand(host, command) t = threading.Thread(target=exec_cmd.run,) t.start() # 併發執行,這裏不需要join阻塞 process_list.append(t) for t in process_list: t.join()
conf /
主機信息文件:
[host1] password = 123456 username = root ip = 192.168.118.15 port = 22 [host2] password = 123456 username = root ip = 192.168.118.16 port = 22 [web group] group = host1,host2
程序環境變量配置:
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys, os import configparser # 程序主目錄 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, BASE_DIR) # 配置目錄 CONF_DIR = os.path.join(BASE_DIR, r'conf') # 配置文件目錄 configfile = os.path.join(CONF_DIR, 'hosts.ini')
modules /
主機信息處理模塊
#!/usr/bin/env python # -*- coding:utf-8 -*- import os import configparser, paramiko from conf import settings class Config(object): '''對配置文件的創建和查看''' def __init__(self, config, configfile): self.configfile = configfile self.config = config def create_conf(self): '''創建配置文件''' self.config['host1'] = { 'ip': '192.168.118.15', 'port': 22, 'username': 'root', 'password': '123456' } self.config['host2'] = { 'ip': '192.168.118.16', 'port': 22, 'username': 'root', 'password': '123456' } self.config['web group'] = { 'group': 'host1,host2' } with open(self.configfile, 'w') as file: self.config.write(file) def show_host(self, choice): '''獲取主機信息字典''' print('choice', choice) section_index = int(choice) - 1 section_name = self.config.sections()[section_index] section = self.config[section_name] host_data_list = [] if 'group' in section: host_list = section['group'].split(',') for host in host_list: host_data_list.append(self.config[host]) else: host_data_list.append(section) return host_data_list
命令執行模塊
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import os class ExecCommand(object): '''執行命令類''' def __init__(self, host, command): self.hostname = host['ip'] self.port = int(host['port']) self.username = host['username'] self.password = host['password'] self.command = command def run(self): cmd = self.command.split()[0] if cmd.startswith('put') and hasattr(self, cmd): func = getattr(self, cmd) func() else: setattr(self, cmd, self.exec_command) func = getattr(self, cmd) func() def put(self): transport = paramiko.Transport(self.hostname, self.port) transport.connect(username=self.username, password=self.password) sftp = paramiko.SFTPClient.from_transport(transport) sftp.put(self.command.split()[1], self.command.split()[2]) transport.close() print('【%s】上傳文件【%s】成功!' % (self.hostname, self.command.split()[1])) def exec_command(self): self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(self.hostname, self.port, self.username, self.password) stdin, stdout, stderr = self.ssh.exec_command(self.command) res, err = stdout.read(), stderr.read() result = res if res else err # 三元運算,默認stdout,錯誤登錄 stderr print('[%s]'.center(80, '*') % self.hostname) print(result.decode())
程序運行如下圖:
本文出處:http://www.cnblogs.com/hukey/p/8951871.html