EasyXMS 多線程批量管理Linux/Unix系統

1、EasyXMS簡介python


EasyXMS是一個用於批量管理Linux/Unix服務器的簡易系統,如:多線程批量執行命令、多線程批量上傳文件等功能,EasyXMS使用Python2.7編寫,並使用paramiko模塊來實現SSH鏈接和SFTP功能。linux


關注項目主頁以獲取最新版本git


http://git.oschina.net/leedays/EasyXMS算法


有什麼優點?shell


  1. 簡單易用vim

  2. 輕量級,只須要一個腳本文件,不須要安裝Client端bash

  3. 安裝部署快,一鍵安裝所需的環境服務器


2、主要功能多線程


  1. 批量執行命令
    app

  2. 批量上傳文件

  3. 記錄每次輸入的命令到文件

  4. 記錄每次執行命令的結果到文件



3、環境安裝


1.Python2.7

下載地址:http://www.python.org


2.easy_install 工具(是Python安裝模塊的一個工具,像yum,能夠自動解決依賴)

下載地址: http://peak.telecommunity.com/dist/ez_setup.py


3.PyCrypto 2.1+ 模塊(PyCrypto是使用Python編寫的加密工具包)

下載地址:https://www.dlitz.net/software/pycrypto/


4.paramiko 模塊(是用Python編寫的支持SSH協議的模塊)

使用easy_install 進行安裝


具體的安裝過程,參看上一篇文章:

http://linux5588.blog.51cto.com/65280/1275180


想省事? 可下載博客附件的一鍵安裝腳本,來安裝paramiko模塊須要的環境

請使用 < source 腳本名 > 的方式執行腳本


四.運行過程當中產生的文件


在腳本的執行過程當中,默認是會在當前目錄下生成如下文件


1. server.conf

該文件是用於存儲各個服務器的鏈接信息如 IP地址:端口:用戶名:密碼,存儲的信息是通過簡單的加密,固然使用的可逆的加密算法,以下所示每行表明一個IP信息:


MTkyLjE2OC4xMDAuMjAxOjIyOnJvb3Q6MTIzNDU2
MTkyLjE2OC4xMDAuMjAyOjIyOnJvb3Q6MTIzNDU2


2.paramiko.log

該文件是paramiko模塊在運行過程當中產生的日誌文件


3.command_history.log

該文件是記錄執行過的命令


4.command_result_history.log

該文件是記錄執行過的命令的結果


5、怎麼執行腳本?


1. 使用 python 腳本名 方式來執行


python EasyXMS.py


2. 使用 腳本的絕對路徑來執行,注意加上可執行權限


./EasyXMS.py


若是出現如下狀況,使用dos2unix轉換一下便可

132014260.png


若是沒有dos2unix,那麼在Windows上使用像EmEditor這類的文本編輯器(不要使用Windows自帶的記事本),把換行符修改成僅Unix,便可

132155803.png


6、操做演示


點擊這裏看動態演示


1.主菜單


輸入? 便可得到主菜單幫助


140735674.png


功能描述:

0 增長服務器的IP信息到配置文件(server.conf 如下都指的是該配置文件)
1 加載一個包含多個服務器IP信息的文件,用於批量添加服務器到
2 列出當前配置文件中存在的服務器
3 從配置文件中刪除指定的服務器信息
4 清空配置文件
5 批量執行命令
6 批量上傳文件
7 清屏


2.選項 0 增長服務器的IP信息到配置文件

140822508.png

140825366.png


3.選項1 加載一個包含多個服務器IP信息的文件


準備一個文本文件,裏面的包含這些內容 IP地址:端口(22端口能夠不寫):用戶名:密碼 每行一個 例如:

192.168.100.204:root:123456

192.168.100.205:root:123

192.168.100.206:root:123

140916568.png

140918500.png


4.選項 2 列出當前配置文件中存在的服務器


133051256.gif


5.選項 3 從配置文件中刪除指定的服務器信息


141001828.png


6.選項 4 清空配置文件


141025183.png


7.選項 5 批量執行命令


141051527.png


8.選項 6 批量上傳文件


141136673.png

141139733.png


9.選項 7 清屏


141211426.png


7、注意事項


1.不能使用vi或者vim編輯遠程文件


2.目前不支持tab鍵補全命令


3.在按 Backspace 鍵出現如下狀況時

133745354.png

可用以下方式來解決:


若是你使用的SecureCRT,能夠這樣解決

133857467.png


若是使用的是Xshell,能夠這樣解決:

133952543.png


putty 使用下來沒這個問題,可是若是有這個問題,找到相似設置的地方 設置一下便可


八.腳本內容


#!/usr/bin/env python
# coding=utf-8
#---------------------------------------------------------------------
# Name:         EasyXMS
# Purpose:      Multithreading Batch Execution Commands and Upload Files
# Version:      1.0
# Author:       LEO
# BLOG:         http://linux5588.blog.51cto.com
# EMAIL:        chanyipiaomiao@163.com
# Created:      2013-7-29
# Copyright:    (c) LEO 2013
#---------------------------------------------------------------------
from base64 import encodestring,decodestring
from os.path import basename,exists,isfile
from sys import exit,platform
from time import strftime
from Queue import Queue
from os import system
import threading
import paramiko
# 控制輸出類
class PrintHelp(object):
    def __init__(self):
        """定義命令列表"""
        self.cmd_list = [' Add      Server ',
                         ' Load     File',
                         ' List     Servers ',
                         ' Delete   Server ',
                         ' Empty    File',
                         ' Execute  Command ',
                         ' Upload   File ',
                         ' Clear    Screen',
                         ]
        self.name = 'EasyXMS'
        self.example = '*** Example *** : '
        self.example_ip = '%s192.168.1.1:22:root:123456 192.168.1.3:test:123456 ' % self.example
        self.example_delete = '%s192.168.1.1 192.168.1.2 ' % self.example
        self.example_filepath = '%s: /tmp/1.txt /tmp' % self.example
    def printPrompt(self):
        """腳本運行提示符"""
        return "%s( ? Help ) >>> " % self.name
    def loopPrintCmd(self):
        """循環打印命令列表"""
        print
        print "Please Choose A Number : "
        print
        for i, v in enumerate(self.cmd_list):
            print "%5s %-5s" % (i, v)
        print
    def printHead(self):
        """輸出頭部提示信息"""
        print_string = 'Welcome to Use < %s > , Please Input < ? > ' \
                       'Get Help Or Direct < Enter > Exit' % self.name
        string_temp = "-" * len(print_string)
        print string_temp
        print
        print print_string
        print
        print string_temp
        print
    def wantQuit(self):
        """退出提示"""
        return "Want Quit? (y/n) [y|Enter]: "
    def printInputWrong(self):
        """提示命令輸入有誤"""
        print
        print "Wrong Input,Enter < ? > Get Help Or Enter Exit ! "
        print
    def printFileError(self, e):
        """提示讀取主機配置文件出錯"""
        print "Oops! Read File Occur Wrong : %s" % e
    def printFileNotExistOrEmpty(self):
        """提示主機配置文件不存在或者爲空,請建立或者添加IP地址到文件"""
        print
        print "The File [ %s ] Not Exist Or Empty," \
              " Enter < 0/1 > to Create Or Add Server IP." % configfile
        print
    def printInvalidIP(self,info):
        """提示無效的信息"""
        print "Invalid Format [ %s ] !!! " % info
        print
    def printIPFormat(self):
        """添加服務器IP地址的格式"""
        print
        print self.example_ip
    def printDeleteIPFormat(self):
        """刪除服務器IP時的格式"""
        print
        print self.example_delete
        print
    def printInputIP(self):
        """提示輸入IP地址以空格分開"""
        return "Enter Server Info : "
    def printInputIPForDelete(self):
        """提示輸入服務器的IP地址"""
        return "Enter Server IP (Only IP Address) : "
    def printAddIPSuccessful(self, ip):
        """提示增長服務器IP到配置文件成功"""
        print "Add Server [ %s ] to [ %s ] Successful !!! " % (ip, configfile)
        print
    def printRemoveIPSuccessful(self,ip):
        """提示從配置文件中刪除IP地址成功"""
        print "Remove [ %s ] From [ %s ] Successful !!!" % (ip,configfile)
        print
    def printIPNotInFile(self, ip):
        """輸出IP地址不在配置文件中"""
        print "%s is Not in [ %s ]" % (ip, configfile)
        print
    def printIPAlreadyInFile(self, ip):
        """輸出IP地址已經在配置文件中"""
        print "IP [ %s ] Already in [ %s ] !!!" % (ip, configfile)
        print
    def youSureEmptyFile(self):
        """提示用戶是否確認清空文件"""
        return "Are You Sure Empty [ %s ] (y/n) : " % configfile
    def emptySuccessful(self):
        """輸出清空文件成功"""
        print "Empty Config File [ %s ] Successful !!!" % configfile
        print
    def emptyFileFailure(self, e):
        """輸出清空文件失敗"""
        print "Empyt File %s Failure !!! ( %s )" % (configfile, e)
    def enterCommand(self):
        """提示輸入命令"""
        return "Enter Command( q|Q Quit ) : "
    def enterFilePath(self):
        """提示輸入文件的路徑"""
        return "Enter [ Local ] Path And < Remote > Path : "
    def enterFilePath2(self):
        """加載文件時,提示輸入文件路徑"""
        return "Enter File Path( File Include ip:username:password ) : "
    def invaildCommand(self):
        """輸出無效的命令"""
        print "Invaild Command !!!"
        print
    def invaildFilePath(self,filepath):
        """無效的文件路徑"""
        print "Invaild File Path ' %s ' !!!" % filepath
        print
    def printSSHBePatient(self):
        """輸出正在初始化SSH鏈接,請耐心等待"""
        print "Initializing < SSH > Connections, Please Be Patient ..."
        print
    def printSFTPBePatient(self):
        """輸出正在初始化SFTP鏈接,請耐心等待"""
        print "Initializing < SFTP > Connections, Please Be Patient ..."
        print
    def printCommandResult(self,ip,cmd,out,error):
        """輸出命令執行的結果"""
        result = "======== [ %s ] Execute Command: ' %s ',The Result is : \n\n%s%s" % (ip,cmd,out,error)
        print result
        return result
    def printCanNotConnectIP(self,ip):
        """輸出不能鏈接到該IP地址"""
        print "[ Error ] ... Can't Connect This IP ' %s ', Please Check !!!" % ip
        print
    def uploadFileOK(self, src, ip):
        """上傳文件成功"""
        print "Upload File < %s > to %s ... OK " % (src, ip)
        print
    def uploadFileError(self, src, ip, e):
        """上傳文件出現錯誤"""
        print "Upload File < %s > to %s ... Error: %s " % (src, ip, e)
        print
    def printFilePath(self):
        """輸出上傳文件時路徑的例子"""
        print
        print self.example_filepath
    def printArgsNotenough(self):
        """輸出參數不夠提示"""
        print "Arguments Not Enough !!!"
        print
    def getDateTime(self):
        """獲取日期和時間"""
        return strftime('%Y-%m-%d %H:%M:%S')
    def returnDateString(self):
        """返回一個日期加星號的字符串用於標識命令執行的結果"""
        return '\n********** %s **********\n\n' % self.getDateTime()
    def printCannotCreateFile(self,filename,error):
        """提示沒法建立文件"""
        print
        print "Can't Create < %s > !!! : %s" % (filename, error)
        print
# 控制輸入類
class InputValue(object):
    def __init__(self):
        self.inputValue = None
    def setInputvalue(self):
        """提示輸入命令"""
        self.inputValue = raw_input(printhelp_obj.printPrompt())
        return self.inputValue
    def closeConnections(self):
        """關閉鏈接函數"""
        ssh_connect_pool_dict = connectSSH_obj.getConnectionPool()
        sftp_connect_pool_dict = connectSFTP_obj.getConnectionPool()
        if ssh_connect_pool_dict:
            for i in ssh_connect_pool_dict:
                ssh_connect_pool_dict[i].close()
        if sftp_connect_pool_dict:
            for j in sftp_connect_pool_dict:
                sftp_connect_pool_dict[j].close()
    def exitFunction(self):
        """退出本程序"""
        try:
            print
            quitp = raw_input(printhelp_obj.wantQuit())
            print
        except EOFError:
            self.closeConnections()
            print
            print
            exit(0)
        if not quitp or quitp == 'y' or quitp == 'Y':
            self.closeConnections()
            exit(0)
        else:
            self.loopGetValue()
    def loopGetValue(self):
        """循環獲得用戶的輸入,並判斷"""
        try:
            while self.setInputvalue():
                if self.inputValue == '?':
                    printhelp_obj.loopPrintCmd()
                elif self.inputValue == '0':
                    readwriteconfigFile_obj.writeIPToFile()
                elif self.inputValue == '1':
                    readwriteconfigFile_obj.loadFile()
                elif self.inputValue == '2':
                    readwriteconfigFile_obj.readIPFromFile()
                elif self.inputValue == '3':
                    readwriteconfigFile_obj.deleteIPFromFile()
                elif self.inputValue == '4':
                    readwriteconfigFile_obj.emptyConfigFile()
                elif self.inputValue == '5':
                    startExecAction_obj.startExecCommand()
                elif self.inputValue == '6':
                    startExecAction_obj.startSFTP()
                elif self.inputValue == '7':
                    startExecAction_obj.clearScreen()
                else:
                    printhelp_obj.printInputWrong()
            else:
                self.exitFunction()
        except EOFError :
            print
            self.exitFunction()
        except KeyboardInterrupt:
            print
            self.exitFunction()
# 操做配置文件類
class ReadWriteConfigFile(object):
    def readIPAsDict(self):
        """讀取全部的IP地址爲一個字典
        像這樣: {'192.168.1.1':{'port':22,'user':root,'pwd':123456}, }
        """
        ip_dict = {}
        try:
            data = open(configfile,'r')
            config_file = data.readlines()
            if config_file:
                for i in config_file:
                    i = decodestring(i)
                    tempstring = i.split(':')
                    ip = tempstring[0]
                    if ip not in ip_dict:
                        ip_dict[ip] = {'port':int(tempstring[1]),
                                       'user':tempstring[2],
                                       'pwd':tempstring[3]}
        except:
            pass
        # 若是文件句柄被打開過,則關閉
        try:
            data.close()
        except:
            pass
        return ip_dict
    def readIPFromFile(self):
        """返回一個IP地址列表"""
        ip_list = self.readIPAsDict().keys()
        if ip_list:
            print
            for i in ip_list:
                print i
            print
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def fileAppendObject(self,filename):
        """以追加方式打開文件並返回對象"""
        data = None
        error = None
        try:
            data = open(filename,'a')
        except IOError,e:
            error = e
        return data,error
    def writeFile(self,data,server_list):
        """寫文件函數,用於寫服務器的配置信息"""
        ip_list = self.readIPAsDict().keys()
        for ip_info in server_list:
            ip,info = self.checkIPInfo(ip_info)
            if ip and info:
                if ip not in ip_list:
                    data.write(encodestring(info))
                    printhelp_obj.printAddIPSuccessful(ip)
                else:
                    printhelp_obj.printIPAlreadyInFile(ip)
    def loadFile(self):
        """加載一個包含 IP地址:端口:用戶名:密碼 的文件批量進行添加"""
        data2,error = self.fileAppendObject(configfile)
        if data2:
            print
            filename = raw_input(printhelp_obj.enterFilePath2())
            print
            if filename:
                try:
                    data = open(filename,'r')
                    file_ip_list = data.readlines()
                    data.close()
                    self.writeFile(data2, file_ip_list)
                except IOError,e:
                    printhelp_obj.printFileError(e)
                    print
                data2.close()
            else:
                printhelp_obj.printArgsNotenough()
        else:
            printhelp_obj.printCannotCreateFile(configfile,error)
    def checkIPInfo(self,ipinfo):
        """簡單的檢查輸入的IP等信息格式是否正確"""
        ip,info = None,None
        maohao_num = ipinfo.count(':')
        if maohao_num in (2,3):
            if ipinfo.count('.') == 3:
                info_list = ipinfo.split(':')
                if maohao_num == 3:
                    ip, port, user, passwd = info_list
                if maohao_num == 2:
                    ip, user, passwd = info_list
                    port = 22
                if passwd:
                    info = '%s:%s:%s:%s' % (ip, port, user, passwd)
                else:
                    printhelp_obj.printInvalidIP(ipinfo)
            else:
                printhelp_obj.printInvalidIP(ipinfo)
        else:
            printhelp_obj.printInvalidIP(ipinfo)
        return ip,info
    def writeIPToFile(self):
        """寫入IP地址到配置文件"""
        data,error = self.fileAppendObject(configfile)
        if data:
            printhelp_obj.printIPFormat()
            print
            hosts = raw_input(printhelp_obj.printInputIP())
            print
            if not hosts:
                printhelp_obj.printArgsNotenough()
            else:
                server_list = hosts.split()
                self.writeFile(data,server_list)
            data.close()
        else:
            printhelp_obj.printCannotCreateFile(configfile, error)
    def deleteIPFromFile(self):
        """從配置文件中刪除指定的IP地址"""
        ip_from_configfile_dict = self.readIPAsDict()
        if ip_from_configfile_dict:
            printhelp_obj.printDeleteIPFormat()
            hosts = raw_input(printhelp_obj.printInputIPForDelete())
            print
            if len(hosts) == 0:
                printhelp_obj.printArgsNotenough()
            else:
                delete_ip_list = hosts.split()
                for i in delete_ip_list:
                    if i in ip_from_configfile_dict:
                        del ip_from_configfile_dict[i]
                        printhelp_obj.printRemoveIPSuccessful(i)
                    else:
                        printhelp_obj.printIPNotInFile(i)
                if ip_from_configfile_dict:
                    try:
                        data = open(configfile, 'w')
                        for key,value in ip_from_configfile_dict.items():
                            tempstring = "%s:%s:%s:%s" % (key, value['port'], value['user'], value['pwd'])
                            data.write(encodestring(tempstring))
                    except IOError, e:
                        print
                        printhelp_obj.printFileError(e)
                        print
                else:
                    data = open(configfile, 'w')
                try:
                    data.close()
                except:
                    pass
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def emptyConfigFile(self):
        """清空整個主機配置文件"""
        if self.readIPAsDict():
            print
            ok = raw_input(printhelp_obj.youSureEmptyFile())
            print
            if ok == 'y' or ok == 'Y':
                try:
                    data = open(configfile, 'w')
                except IOError,e:
                    printhelp_obj.emptyFileFailure(e)
                # 若是文件句柄被打開過,則關閉
                try:
                    data.close()
                    printhelp_obj.emptySuccessful()
                except:
                    pass
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def readCommandHistory(self):
        """讀取歷史執行命令"""
        command_history_list = []
        try:
            data = open(command_history,'r')
            for cmd in data.readlines():
                command_history_list.append(cmd.strip('\n'))
            data.close()
        except IOError:
            pass
        return command_history_list
    def writeCommandToFile(self,cmd):
        """命令寫入到文件"""
        command_history_list = self.readCommandHistory()
        data,error = self.fileAppendObject(command_history)
        if data:
            if cmd not in command_history_list:
                data.write(cmd+'\n')
            data.close()
        else:
            printhelp_obj.printCannotCreateFile(command_history, error)
    def writeCommandResultToFile(self, result_list):
        """命令輸出結果寫入到文件"""
        data,error = self.fileAppendObject(command_result_history)
        if data:
            data.write(printhelp_obj.returnDateString())
            data.write(''.join(result_list))
            data.write('\n')
            data.close()
        else:
            printhelp_obj.printCannotCreateFile(command_result_history,error)
# 鏈接SSH和SFTP類的父類
class Connect(object):
    def __init__(self):
        self.connect_pool_dict = {}
        self.ip_list = []     
        self.thread_num = None
    def getIPList(self):
        """獲取SSH/SFTP鏈接成功的IP地址"""
        return self.ip_list
    def getThreadNum(self):
        """獲取到線程數量,是經過計算IP地址數量獲得"""
        return self.thread_num
    def getConnectionPool(self):
        """獲取SFTP/SSH鏈接池信息"""
        return self.connect_pool_dict
# 鏈接SSH類
class ConnectSSH(Connect):
    def connectSSH(self):
        """鏈接到SSH服務"""
        paramiko.util.log_to_file(EasyXMS_log)
        server_dict = readwriteconfigFile_obj.readIPAsDict() # 首先得到ServerIP地址列表
        if server_dict:
            # 這一段就是判斷,在ssh的connect_pool_dict這裏面現存的IP地址列表跟從配置文件讀取出來的列表是否一致
            # 若是不一致,那麼以配置文件讀取出來的IP地址列表爲準,刪除多餘的鏈接
            if self.connect_pool_dict:
                connect_pool_list = self.connect_pool_dict.keys()
                for i in connect_pool_list:
                    if i not in server_dict:
                        del self.connect_pool_dict[i]
                        self.ip_list.remove(i)
            # 這一段是增長 成功進行SSH鏈接的IP地址到self.connect_pool_dict中去,同時也增長到成功IP地址列表去
            for ip,value in server_dict.items():
                if ip not in self.connect_pool_dict:
                    conn = paramiko.SSHClient()
                    conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                    try:
                        conn.connect(ip,value['port'],value['user'],value['pwd'], timeout=0.8)
                        self.connect_pool_dict[ip] = conn
                        self.ip_list.append(ip)
                    except:
                        printhelp_obj.printCanNotConnectIP(ip)
            self.thread_num = len(self.ip_list)
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def setCommand(self,command):
        """設定命令行輸入的命令"""
        self.command = command
    def getCommand(self):
        """返回命令"""
        return self.command
# 鏈接到SFTP類
class ConnectSFTP(Connect):
    def connectSFTP(self):
        """鏈接到SFTP服務"""
        paramiko.util.log_to_file(EasyXMS_log)
        server_dict = readwriteconfigFile_obj.readIPAsDict() # 首先得到ServerIP地址列表
        if server_dict:
            # 這一段就是判斷,在sftp的connect_pool_dict這裏面現存的IP地址列表跟從配置文件讀取出來的列表是否一致
            # 若是不一致,那麼以配置文件讀取出來的IP地址列表爲準,刪除多餘的鏈接
            if self.connect_pool_dict:
                connect_pool_list = self.connect_pool_dict.keys()
                for i in connect_pool_list:
                    if i not in server_dict:
                        del self.connect_pool_dict[i]
                        self.ip_list.remove(i)
            # 這一段是增長 成功進行SFTP鏈接的IP地址到self.connect_pool_dict中去,同時也增長到成功IP地址列表去
            for ip,value in server_dict.items():
                if ip not in self.connect_pool_dict:
                    try:
                        conn = paramiko.Transport((ip, value['port']))
                        conn.connect(username=value['user'], password=value['pwd'])
                        sftp = paramiko.SFTPClient.from_transport(conn)
                        self.connect_pool_dict[ip] = sftp
                        self.ip_list.append(ip)
                    except:
                        printhelp_obj.printCanNotConnectIP(ip)
            self.thread_num = len(self.ip_list)
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def getDirectoryName(self, filename, dest):
        """拼接目標文件名"""
        if dest.endswith('/'):
            dest = '%s/%s' % (dest.rstrip('/'), filename)
        else:
            dest = '%s/%s' % (dest, filename)
        return dest
    def setFilePath(self,filepath):
        """設定當前命令行輸入的文件路徑"""
        self.filepath = filepath
    def getFilePath(self):
        """返回命令行輸入的文件路徑"""
        return self.filepath
# 多線程類
class MutilThreadControl(threading.Thread):
    def setConnectionPool(self, pool):
        """設置使用那個鏈接池 有SSH和SFTP鏈接池"""
        self.init_pool = pool
    def initIPQueueAndtConnectionPool(self):
        """初始一個隊列並把IP地址放入隊列,返回IP地址列表的長度(指定產生線程的數量)和隊列"""
        if self.init_pool == 'ssh':
            ip_list = connectSSH_obj.getIPList()
            connect_pool_dict = connectSSH_obj.getConnectionPool()
        elif self.init_pool == 'sftp':
            ip_list = connectSFTP_obj.getIPList()
            connect_pool_dict = connectSFTP_obj.getConnectionPool()
        thread_num = len(ip_list)
        ip_queue = Queue(thread_num)
        for ip in ip_list:
            ip_queue.put(ip)
        return ip_queue, thread_num, connect_pool_dict
    def run(self):
        """開始多線程執行命令和SFTP上傳文件"""
        ip_queue, threads_num, connect_pool_dict = self.initIPQueueAndtConnectionPool()
        result_list = []
        if self.init_pool == 'ssh':
            cmd = connectSSH_obj.getCommand()
            for i in xrange(threads_num):
                ip = ip_queue.get()
                stdin,stdout,stderr = connect_pool_dict[ip].exec_command(cmd)
                result = printhelp_obj.printCommandResult(ip, cmd, stdout.read(), stderr.read())
                result_list.append(result)
            readwriteconfigFile_obj.writeCommandResultToFile(result_list)
        elif self.init_pool == 'sftp':
            file_path = connectSFTP_obj.getFilePath().split()
            if len(file_path) == 2:
                src,dest = file_path
                if exists(src) and isfile(src):
                    filename = basename(src)
                    dest = connectSFTP_obj.getDirectoryName(filename, dest)
                    for i in xrange(threads_num):
                        ip = ip_queue.get()
                        try:
                            connect_pool_dict[ip].put(src, dest)
                            printhelp_obj.uploadFileOK(src, ip)
                        except IOError, e:
                            printhelp_obj.uploadFileError(src, ip, e)
                else:
                    printhelp_obj.invaildFilePath(src)
            else:
                printhelp_obj.printArgsNotenough()
# 執行指定的動做(執行命令 上傳文件 清屏)
class StartExecAction(object):
    def startExecCommand(self):
        """開始多線程執行命令"""
        mutilThreadControl_ssh_obj = MutilThreadControl()
        mutilThreadControl_ssh_obj.setConnectionPool('ssh')
        if readwriteconfigFile_obj.readIPAsDict():
            print
            cmd = raw_input(printhelp_obj.enterCommand())
            print
            if cmd:
                if cmd == 'q' or cmd == 'Q':
                    pass
                else:
                    readwriteconfigFile_obj.writeCommandToFile(cmd)
                    connectSSH_obj.setCommand(cmd)             
                    if not connectSSH_obj.getConnectionPool(): 
                        printhelp_obj.printSSHBePatient()      
                    connectSSH_obj.connectSSH()                
                    mutilThreadControl_ssh_obj.start()        
                    mutilThreadControl_ssh_obj.join()         
                    self.startExecCommand()                    
            else:
                printhelp_obj.invaildCommand()
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def startSFTP(self):
        """開始上傳文件"""
        mutilThreadControl_sftp_obj = MutilThreadControl()
        mutilThreadControl_sftp_obj.setConnectionPool('sftp')  
        if readwriteconfigFile_obj.readIPAsDict():
            printhelp_obj.printFilePath()
            print
            filepath = raw_input(printhelp_obj.enterFilePath())
            print
            if filepath:
                connectSFTP_obj.setFilePath(filepath)        
                if not connectSFTP_obj.getConnectionPool():
                    printhelp_obj.printSFTPBePatient()       
                connectSFTP_obj.connectSFTP()                  
                mutilThreadControl_sftp_obj.start()           
                mutilThreadControl_sftp_obj.join()            
            else:
                printhelp_obj.printArgsNotenough()
        else:
            printhelp_obj.printFileNotExistOrEmpty()
    def clearScreen(self):
        """清屏"""
        clear_screen = {'win32':'cls','linux2':'clear',
                        'linux':'clear','darwin':'clear'}[platform]
        system(clear_screen)
if __name__ == '__main__':
    configfile = 'server.conf'                        
    EasyXMS_log = 'paramiko.log'                     
    command_history = 'command_history.log'          
    command_result_history = 'command_result_history.log'
    printhelp_obj = PrintHelp()                        
    printhelp_obj.printHead()                      
    readwriteconfigFile_obj = ReadWriteConfigFile()   
    connectSSH_obj = ConnectSSH()                      
    connectSFTP_obj = ConnectSFTP()              
    startExecAction_obj = StartExecAction()            
    input_obj = InputValue()                          
    input_obj.loopGetValue()
相關文章
相關標籤/搜索