python主機批量管理程序

開發要求:


    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章