1. 程式人生 > 其它 >python實現批量操作主機(自己可以選擇互動式和非互動式兩種)

python實現批量操作主機(自己可以選擇互動式和非互動式兩種)

程式碼開始------------------------------------------------------------

#!/usr/bin/env python

# _*_ coding:utf-8 _*_

from paramiko import SSHClient, AutoAddPolicy

import select

import re

 

host_list = [

    {'hostname': '192.168.174.130', 'port': 22, 'username': 'root', 'password': 'mana.2021'},

]  # 這是一個原始的主機資訊列表;你也可以自己在程式碼中新增,也可以遍歷excel進行新增;

conn_deon = []  # 第一次驗證主機成功的主機列表

conn_fail = []  # 第一次驗證主機報錯的主機列表

conn_amend = []  # 修改埠後的主機列表;說明:修改埠的列表修改的是“第一次驗證失敗的列表【conn_fail】”

host_version_filtration = []  # 過濾符合版本的主機;擴充套件功能

no_host_version_filtration = []  # 過濾不符合版本的主機;擴充套件功能

 

 

def ssh_ex(hostname, port, username, password):

    '''

    這是一個測試連線是否成功的函式;

    會將成功連線的主機傳入“conn_deon“列表;

    將連線失敗的主機登入資訊追加到“conn_fail”列表

    :param hostname: 測試主機IP

    :param port: 測試主機埠

    :param username: 測試主機使用者名稱

    :param password: 測試主機密碼

    :return:

    '''

    ssh_client = SSHClient()  # 建立一個連線例項

    ssh_client.set_missing_host_key_policy(AutoAddPolicy)  # 自動處理SSH彈出的yes/no

    try:

        ssh_client.connect(hostname, port, username, password)  # 進行SSH連線

        # 將成功連線的主機追加“conn_deon“列表

        conn_deon.append({'hostname': hostname, 'port': port,

                          'username': username, 'password': password})

        print('\033[0;32mhost:\033[0m%s' % hostname)

        ssh_client.close()  # 關閉連線

    except Exception as e:

        print('\033[0;31mhost:\033[0m%s' % hostname)  # 列印連線失敗的主機

        # 將連線失敗的主機登入資訊追加到“conn_fail”列表

        conn_fail.append({'hostname': hostname, 'port': port,

                          'username': username, 'password': password})

        print(e)  # 列印錯誤

        print('', end='\n\n')

 

 

def ssh_host_filtration(hostname, port, username, password,filtration_parameter):

    '''

    這是一個過濾函式;是一個擴充套件功能;

    :param hostname:主機IP

    :param port:登入埠

    :param username:使用者名稱

    :param password:使用者密碼

    :param filtration_parameter:過濾引數

    :return:如果輸入的命令正確,return就會進行返回;反之return就會返回空資料;

    '''

    ssh_client = SSHClient()

    ssh_client.set_missing_host_key_policy(AutoAddPolicy)

    ssh_client.connect(hostname, port, username, password)

    print('\033[0;32mhost:\033[0m%s開始過濾...' % hostname)

    stdin, stdout, stderr = ssh_client.exec_command(filtration_parameter)

    result_out = stdout.read().decode('utf-8')

    result_err = stderr.read().decode('utf-8')

    ssh_client.close()

    return result_out

 

 

def ssh_ex_official(hostname, port, username, password):

    '''

    這是一個進行批量操作主機的函式;

    :param hostname: 測試主機IP

    :param port: 測試主機埠

    :param username: 測試主機使用者名稱

    :param password: 測試主機密碼

    :return:

    '''

    ssh_client = SSHClient()

    ssh_client.set_missing_host_key_policy(AutoAddPolicy)

    ssh_client.connect(hostname, port, username, password)

    print('\033[0;32mhost:\033[0m%s' % hostname)

    while True:

        cmd = yield

        if cmd != 'quit_shell':

            stdin, stdout, stderr = ssh_client.exec_command(cmd)

            result = stdout.read().decode('utf-8')

            err = stderr.read().decode('utf-8')

            if len(err) != 0:

                print(err)  # 列印錯誤

                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)

            else:

                print(result)  # 列印服務端主機返回資訊

                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)

        else:

            print('主機“%s”已退出連線...' % hostname)

            ssh_client.close()

 

 

def ssh_interaction_official(hostname, port, username, password):

    '''

    這是一個互動式的SSH函式;

    :param hostname:

    :param port:

    :param username:

    :param password:

    :return:

    '''

    ssh_shell = SSHClient()

    ssh_shell.set_missing_host_key_policy(AutoAddPolicy)

    ssh_shell.connect(hostname, port, username, password)

    chan = ssh_shell.invoke_shell()

    inputs = [chan, ]

    outputs = []

    while True:

        while True:

            readable, writeable, exceptional = select.select(inputs, outputs, inputs, 1)  # 解決列印完整的問題;

            # 但是select會進行阻塞;關於select.select()函式超時,只要超時就會向下執行;

 

            if readable:

                info = chan.recv(1024).decode('utf-8')

                print(info)

                continue

            else:

                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)

                break

 

        cmd = yield

        if cmd != 'quit_shell':

            chan.send(cmd.encode('utf-8') + b'\n')

        else:

            print('“%s”主機退出連線...' % hostname)

            # 最後這段程式碼“print('“%s”主機退出連線...' % hostname)”非常關鍵,如果下面繼續增加“break”就會出現報錯;

            # 新增break報錯內容是“File "<string>", line 1, in <module> StopIteration";

            # 新增“ssh_shell.close()”程式碼會進入一個死迴圈,一直列印空白行;

            # 所以僅僅只有“print('“%s”主機退出連線...' % hostname)”這段程式碼就夠了;

 

 

def bath_handle_host_ex(input_list):

    '''

    這是一個“非互動式”批量操作主機發送操作命令的函式;

    :param input_list: 傳入驗證使用者通過的字典資訊

    :return:

    '''

    ssh_conn_list = []  # 將生成的多個批量變數加入這個列表

    count_1 = 1

    for i in input_list:

        print('開始連線第%s個主機...' % count_1)

        hostname = i['hostname']

        port = i['port']

        username = i['username']

        password = i['password']

        # 將批量生成的遍歷加入“ssh_conn_list”列表

        ssh_conn_list.append("conn%s = ssh_ex_official('%s', %s, '%s', '%s')"

                             % (input_list.index(i), hostname, port, username, password))

        count_1 += 1

    print('所有主機準備就緒...回車繼續')

    input()

    for i in ssh_conn_list:

        exec(i)  # 執行遍歷出的【conn%s = ssh_ex_official('%s', %s, '%s', '%s')】變數

    for_number = len(input_list)  # 將遍歷的次數進行賦值

    for i in range(for_number):

        exec('next(conn%s)' % i)  # exec函式是一個將字串型別的程式碼進行執行

    while True:

        print('', end='\n\n\n')

        cmds = input('請輸入需要批量處理的命令>>:').strip()  # strip去掉開頭和結尾的回車和空格

        if len(cmds) == 0:

            continue

        else:

            for i in range(for_number):

                exec('conn%s.send(cmds)' % i)

            if cmds == 'quit_shell':

                input('返回上級選單')

                break

 

 

def bath_handle_host_interaction(input_list):

    '''

    這是一個“互動式”批量操作主機發送操作命令的函式;

    :param input_list: 傳入驗證使用者通過的字典資訊

    :return:

    '''

    ssh_conn_list = []  # 將生成的多個批量變數加入這個列表

    count_1 = 1

    for i in input_list:

        print('開始連線第%s個主機...' % count_1)

        hostname = i['hostname']

        port = i['port']

        username = i['username']

        password = i['password']

        # 將批量生成的遍歷加入“ssh_conn_list”列表

        ssh_conn_list.append("conn%s = ssh_interaction_official('%s', %s, '%s', '%s')"

                             % (input_list.index(i), hostname, port, username, password))

        count_1 += 1

    print('所有主機準備就緒...回車繼續')

    input()

    for i in ssh_conn_list:

        exec(i)  # 執行遍歷出的【conn%s = ssh_ex_official('%s', %s, '%s', '%s')】變數

    for_number = len(ssh_conn_list)  # 將遍歷的次數進行賦值

    for i in range(for_number):

        exec('next(conn%s)' % i)  # exec函式是一個將字串型別的程式碼進行執行

    while True:

        print('', end='\n\n\n')

        cmds = input('請輸入需要批量處理的命令>>:').strip()  # strip去掉開頭和結尾的回車和空格

        if len(cmds) == 0:

            continue

        else:

            for i in range(for_number):

                exec('conn%s.send(cmds)' % i)

            if cmds == 'quit_shell':

                input('返回上級選單')

                break

 

 

def test_login(print_info, host_list_info):

    print(print_info, '-' * 30)

    count = 1

    for i in host_list_info:

        print('開始進行第%s個主機使用者驗證...' % count)

        ssh_ex(hostname=i['hostname'], port=i['port'],

               username=i['username'], password=i['password'])

        count += 1

    print('連線成功主機列表', '-' * 20)

    conn_count = 0

    for i in conn_deon:

        print(i['hostname'])

        conn_count += 1

    return conn_count

 

 

if __name__ == '__main__':

    while True:

        print('''

---------------------------------------------------------------------------

功能說明:

    1.登入過濾主機

    2.批量操作主機

    3.修改過濾後主機埠

    4.檢視指令碼使用說明

    提示:選擇輸入對應的功能編號!!!

---------------------------------------------------------------------------

        ''')

        func_in = input('輸入對應的功能編號:')

        if func_in == '1':

            while True:

                test_port = input('''

1.登入過濾主機-----------------------------------

 

請輸入需要驗證登入的主機列表

提示只可以輸入:

1.驗證原始主機是否可以登入

2.驗證修改埠後的主機是否可以登入

"quit"返回上一級

>>:

                ''')

                if test_port == '1':

                    del conn_deon[:]

                    number = test_login(print_info='驗證所有原始主機資訊列表', host_list_info=host_list)

                    input('''

驗證完成...

\033[0;32m成功連線%s個主機\033[0m

回車繼續

                        ''' % number)

                    break

                elif test_port == '2':

                    count = 0

                    for i in conn_deon:

                        count += 1

                    number = test_login(print_info='驗證修改埠後的主機列表', host_list_info=conn_amend)

                    new_number = count - number

                    input('''

驗證完成...

\033[0;32m修改SSH連線埠後成功連線%s個主機\033[0m

回車繼續

                        ''' % new_number)

                    break

                elif test_port == 'quit':

                    break

                else:

                    continue

        elif func_in == '2':

            while True:

                handle_list = input('''

2.批量操作主機-----------------------------------

 

請輸入需要批量操作的主機列表

提示只可以輸入:

1.開始非互動批量操作主機

2.開始互動式批量操作主機

3.過濾符合條件的主機加入新列表進行批量操作;注意這是一個擴充套件功能

"quit"返回上一級

>>:

                ''')

                if handle_list == '1':

                    input('''

\033[0;31m提示:輸入“quit_shell”就會退出批量操作主機\033[0m

回車繼續

                    ''')

                    bath_handle_host_ex(conn_deon)

                elif handle_list == '2':

                    input('''

\033[0;31m提示:輸入“quit_shell”就會退出批量操作主機\033[0m

回車繼續

                    ''')

                    bath_handle_host_interaction(conn_deon)

                elif handle_list == '3':

                    for i in conn_deon:

                        hostname = i['hostname']

                        port = i['port']

                        username = i['username']

                        password = i['password']

                        re_parameter = ssh_host_filtration(hostname=hostname, port=port, username=username,

                                                 password=password,

                                                 filtration_parameter='cat /etc/.kyinfo |grep milestone')

                        if re_parameter:

                            re_version = '\d\.\d'

                            res = re.search(re_version, re_parameter, re.I).group()

                            if res == '3.3':

                                host_version_filtration.append(i)

                            else:

                                no_host_version_filtration.append({'hostname':hostname, '系統版本':res})

                        else:

                            no_host_version_filtration.append({'hostname':hostname, '系統版本':'非麒麟系統'})

                    if len(host_version_filtration) == 0:

                        print('', end='\n\n\n')

                        print('沒有符合過濾條件的主機...')

                        print('\033[0;31m不符合主機過濾規則的主機和版本如下', '-' * 30)

                        for i in no_host_version_filtration:

                            for k in i:

                                print('\033[0;31m%s\033[0m' % i[k], end=' ')

                            print('')

                        input('回車繼續')

                        del no_host_version_filtration[:]

                    else:

                        bath_handle_host_interaction(host_version_filtration)

                        print('', end='\n\n\n')

                        print('\033[0;31m不符合主機過濾規則的主機和版本\033[0m', '-' * 30)

                        for i in no_host_version_filtration:

                            for k in i:

                                print('\033[0;31m%s\033[0m' % i[k], end=' ')

                            print('')

                        input('回車繼續')

                        del no_host_version_filtration[:]

                        del host_version_filtration[:]

                elif handle_list == 'quit':

                    break

                else:

                    print('輸入的列表名存在錯誤!請重新輸入!')

                    continue

        elif func_in == '3':

            print('3.修改過濾主機埠-----------------------------------')

            func_in_3 = input('''

是否開始修改連線失敗的埠號?

yes/no

>>:

            ''')

            if func_in_3 == 'yes':

                port_new = int(input('請輸入新的埠號:'))

                for i in conn_fail:

                    i['port'] = port_new

                    conn_amend.append(i)

                print('\033[0;32m-\033[0m' * 90)

                count = 0

                for i in conn_amend:

                    print(i)

                    count += 1

                input('''

已完成主機列表的埠\033[0;32m%s\033[0m修改;

共計:完成\033[0;32m%s\033[0m個

回車繼續

                ''' % (port_new, count))

            else:

                continue

        elif func_in == '4':

            print('4.檢視指令碼使用說明-----------------------------------')

            input('''

本指令碼使用步驟:

        1.執行‘1.1’過濾主機

        2.執行‘3’修改過濾後的主機埠

        3.執行‘1.2’繼續過濾主機

        4.執行‘2.1’開始批量操作主機

        回車返回上級選單...

            ''')

        else:

 

            exit(0)

程式碼結束------------------------------------------------------------

使用方法:

1.每使用一次指令碼就需要執行1.1過濾一次主機

2.一般批量操作主機使用2.2互動式操作就可以了

3.程式碼缺點:它不是多執行緒的,for迴圈比較慢-需要一個一個為主機下發命令;

      另外一個缺點就是,主機賬號資訊需要手動輸入host_list列表中;

      host_list中的資訊不是使用hash加密的,存在安全隱患;

      你可以自己寫一個登入加密的列表進行給它加密;

 

 

 

  #!/usr/bin/env python# _*_ coding:utf-8 _*_from paramiko import SSHClient, AutoAddPolicyimport selectimport re
host_list = [    {'hostname': '192.168.174.130', 'port': 22, 'username': 'root', 'password': 'mana.2021'},]  # 這是一個原始的主機資訊列表;你也可以自己在程式碼中新增,也可以遍歷excel進行新增;conn_deon = []  # 第一次驗證主機成功的主機列表conn_fail = []  # 第一次驗證主機報錯的主機列表conn_amend = []  # 修改埠後的主機列表;說明:修改埠的列表修改的是“第一次驗證失敗的列表【conn_fail】”host_version_filtration = []  # 過濾符合版本的主機;擴充套件功能no_host_version_filtration = []  # 過濾不符合版本的主機;擴充套件功能

def ssh_ex(hostname, port, username, password):    '''    這是一個測試連線是否成功的函式;    會將成功連線的主機傳入“conn_deon“列表;    將連線失敗的主機登入資訊追加到“conn_fail”列表    :param hostname: 測試主機IP    :param port: 測試主機埠    :param username: 測試主機使用者名稱    :param password: 測試主機密碼    :return:    '''    ssh_client = SSHClient()  # 建立一個連線例項    ssh_client.set_missing_host_key_policy(AutoAddPolicy)  # 自動處理SSH彈出的yes/no    try:        ssh_client.connect(hostname, port, username, password)  # 進行SSH連線        # 將成功連線的主機追加“conn_deon“列表        conn_deon.append({'hostname': hostname, 'port': port,                          'username': username, 'password': password})        print('\033[0;32mhost:\033[0m%s' % hostname)        ssh_client.close()  # 關閉連線    except Exception as e:        print('\033[0;31mhost:\033[0m%s' % hostname)  # 列印連線失敗的主機        # 將連線失敗的主機登入資訊追加到“conn_fail”列表        conn_fail.append({'hostname': hostname, 'port': port,                          'username': username, 'password': password})        print(e)  # 列印錯誤        print('', end='\n\n')

def ssh_host_filtration(hostname, port, username, password,filtration_parameter):    '''    這是一個過濾函式;是一個擴充套件功能;    :param hostname:主機IP    :param port:登入埠    :param username:使用者名稱    :param password:使用者密碼    :param filtration_parameter:過濾引數    :return:如果輸入的命令正確,return就會進行返回;反之return就會返回空資料;    '''    ssh_client = SSHClient()    ssh_client.set_missing_host_key_policy(AutoAddPolicy)    ssh_client.connect(hostname, port, username, password)    print('\033[0;32mhost:\033[0m%s開始過濾...' % hostname)    stdin, stdout, stderr = ssh_client.exec_command(filtration_parameter)    result_out = stdout.read().decode('utf-8')    result_err = stderr.read().decode('utf-8')    ssh_client.close()    return result_out

def ssh_ex_official(hostname, port, username, password):    '''    這是一個進行批量操作主機的函式;    :param hostname: 測試主機IP    :param port: 測試主機埠    :param username: 測試主機使用者名稱    :param password: 測試主機密碼    :return:    '''    ssh_client = SSHClient()    ssh_client.set_missing_host_key_policy(AutoAddPolicy)    ssh_client.connect(hostname, port, username, password)    print('\033[0;32mhost:\033[0m%s' % hostname)    while True:        cmd = yield        if cmd != 'quit_shell':            stdin, stdout, stderr = ssh_client.exec_command(cmd)            result = stdout.read().decode('utf-8')            err = stderr.read().decode('utf-8')            if len(err) != 0:                print(err)  # 列印錯誤                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)            else:                print(result)  # 列印服務端主機返回資訊                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)        else:            print('主機“%s”已退出連線...' % hostname)            ssh_client.close()

def ssh_interaction_official(hostname, port, username, password):    '''    這是一個互動式的SSH函式;    :param hostname:    :param port:    :param username:    :param password:    :return:    '''    ssh_shell = SSHClient()    ssh_shell.set_missing_host_key_policy(AutoAddPolicy)    ssh_shell.connect(hostname, port, username, password)    chan = ssh_shell.invoke_shell()    inputs = [chan, ]    outputs = []    while True:        while True:            readable, writeable, exceptional = select.select(inputs, outputs, inputs, 1)  # 解決列印完整的問題;            # 但是select會進行阻塞;關於select.select()函式超時,只要超時就會向下執行;
            if readable:                info = chan.recv(1024).decode('utf-8')                print(info)                continue            else:                print('\033[0;32m%s\033[0m' % hostname, '^' * 100)                break
        cmd = yield        if cmd != 'quit_shell':            chan.send(cmd.encode('utf-8') + b'\n')        else:            print('“%s”主機退出連線...' % hostname)            # 最後這段程式碼“print('“%s”主機退出連線...' % hostname)”非常關鍵,如果下面繼續增加“break”就會出現報錯;            # 新增break報錯內容是“File "<string>", line 1, in <module> StopIteration";            # 新增“ssh_shell.close()”程式碼會進入一個死迴圈,一直列印空白行;            # 所以僅僅只有“print('“%s”主機退出連線...' % hostname)”這段程式碼就夠了;

def bath_handle_host_ex(input_list):    '''    這是一個“非互動式”批量操作主機發送操作命令的函式;    :param input_list: 傳入驗證使用者通過的字典資訊    :return:    '''    ssh_conn_list = []  # 將生成的多個批量變數加入這個列表    count_1 = 1    for i in input_list:        print('開始連線第%s個主機...' % count_1)        hostname = i['hostname']        port = i['port']        username = i['username']        password = i['password']        # 將批量生成的遍歷加入“ssh_conn_list”列表        ssh_conn_list.append("conn%s = ssh_ex_official('%s', %s, '%s', '%s')"                             % (input_list.index(i), hostname, port, username, password))        count_1 += 1    print('所有主機準備就緒...回車繼續')    input()    for i in ssh_conn_list:        exec(i)  # 執行遍歷出的【conn%s = ssh_ex_official('%s', %s, '%s', '%s')】變數    for_number = len(input_list)  # 將遍歷的次數進行賦值    for i in range(for_number):        exec('next(conn%s)' % i)  # exec函式是一個將字串型別的程式碼進行執行    while True:        print('', end='\n\n\n')        cmds = input('請輸入需要批量處理的命令>>:').strip()  # strip去掉開頭和結尾的回車和空格        if len(cmds) == 0:            continue        else:            for i in range(for_number):                exec('conn%s.send(cmds)' % i)            if cmds == 'quit_shell':                input('返回上級選單')                break

def bath_handle_host_interaction(input_list):    '''    這是一個“互動式”批量操作主機發送操作命令的函式;    :param input_list: 傳入驗證使用者通過的字典資訊    :return:    '''    ssh_conn_list = []  # 將生成的多個批量變數加入這個列表    count_1 = 1    for i in input_list:        print('開始連線第%s個主機...' % count_1)        hostname = i['hostname']        port = i['port']        username = i['username']        password = i['password']        # 將批量生成的遍歷加入“ssh_conn_list”列表        ssh_conn_list.append("conn%s = ssh_interaction_official('%s', %s, '%s', '%s')"                             % (input_list.index(i), hostname, port, username, password))        count_1 += 1    print('所有主機準備就緒...回車繼續')    input()    for i in ssh_conn_list:        exec(i)  # 執行遍歷出的【conn%s = ssh_ex_official('%s', %s, '%s', '%s')】變數    for_number = len(ssh_conn_list)  # 將遍歷的次數進行賦值    for i in range(for_number):        exec('next(conn%s)' % i)  # exec函式是一個將字串型別的程式碼進行執行    while True:        print('', end='\n\n\n')        cmds = input('請輸入需要批量處理的命令>>:').strip()  # strip去掉開頭和結尾的回車和空格        if len(cmds) == 0:            continue        else:            for i in range(for_number):                exec('conn%s.send(cmds)' % i)            if cmds == 'quit_shell':                input('返回上級選單')                break

def test_login(print_info, host_list_info):    print(print_info, '-' * 30)    count = 1    for i in host_list_info:        print('開始進行第%s個主機使用者驗證...' % count)        ssh_ex(hostname=i['hostname'], port=i['port'],               username=i['username'], password=i['password'])        count += 1    print('連線成功主機列表', '-' * 20)    conn_count = 0    for i in conn_deon:        print(i['hostname'])        conn_count += 1    return conn_count

if __name__ == '__main__':    while True:        print('''---------------------------------------------------------------------------功能說明:    1.登入過濾主機    2.批量操作主機    3.修改過濾後主機埠    4.檢視指令碼使用說明    提示:選擇輸入對應的功能編號!!!---------------------------------------------------------------------------        ''')        func_in = input('輸入對應的功能編號:')        if func_in == '1':            while True:                test_port = input('''1.登入過濾主機-----------------------------------
請輸入需要驗證登入的主機列表提示只可以輸入:1.驗證原始主機是否可以登入2.驗證修改埠後的主機是否可以登入"quit"返回上一級>>:                ''')                if test_port == '1':                    del conn_deon[:]                    number = test_login(print_info='驗證所有原始主機資訊列表', host_list_info=host_list)                    input('''驗證完成...\033[0;32m成功連線%s個主機\033[0m回車繼續                        ''' % number)                    break                elif test_port == '2':                    count = 0                    for i in conn_deon:                        count += 1                    number = test_login(print_info='驗證修改埠後的主機列表', host_list_info=conn_amend)                    new_number = count - number                    input('''驗證完成...\033[0;32m修改SSH連線埠後成功連線%s個主機\033[0m回車繼續                        ''' % new_number)                    break                elif test_port == 'quit':                    break                else:                    continue        elif func_in == '2':            while True:                handle_list = input('''2.批量操作主機-----------------------------------
請輸入需要批量操作的主機列表提示只可以輸入:1.開始非互動批量操作主機2.開始互動式批量操作主機3.過濾符合條件的主機加入新列表進行批量操作;注意這是一個擴充套件功能"quit"返回上一級>>:                ''')                if handle_list == '1':                    input('''\033[0;31m提示:輸入“quit_shell”就會退出批量操作主機\033[0m回車繼續                    ''')                    bath_handle_host_ex(conn_deon)                elif handle_list == '2':                    input('''\033[0;31m提示:輸入“quit_shell”就會退出批量操作主機\033[0m回車繼續                    ''')                    bath_handle_host_interaction(conn_deon)                elif handle_list == '3':                    for i in conn_deon:                        hostname = i['hostname']                        port = i['port']                        username = i['username']                        password = i['password']                        re_parameter = ssh_host_filtration(hostname=hostname, port=port, username=username,                                                 password=password,                                                 filtration_parameter='cat /etc/.kyinfo |grep milestone')                        if re_parameter:                            re_version = '\d\.\d'                            res = re.search(re_version, re_parameter, re.I).group()                            if res == '3.3':                                host_version_filtration.append(i)                            else:                                no_host_version_filtration.append({'hostname':hostname, '系統版本':res})                        else:                            no_host_version_filtration.append({'hostname':hostname, '系統版本':'非麒麟系統'})                    if len(host_version_filtration) == 0:                        print('', end='\n\n\n')                        print('沒有符合過濾條件的主機...')                        print('\033[0;31m不符合主機過濾規則的主機和版本如下', '-' * 30)                        for i in no_host_version_filtration:                            for k in i:                                print('\033[0;31m%s\033[0m' % i[k], end=' ')                            print('')                        input('回車繼續')                        del no_host_version_filtration[:]                    else:                        bath_handle_host_interaction(host_version_filtration)                        print('', end='\n\n\n')                        print('\033[0;31m不符合主機過濾規則的主機和版本\033[0m', '-' * 30)                        for i in no_host_version_filtration:                            for k in i:                                print('\033[0;31m%s\033[0m' % i[k], end=' ')                            print('')                        input('回車繼續')                        del no_host_version_filtration[:]                        del host_version_filtration[:]                elif handle_list == 'quit':                    break                else:                    print('輸入的列表名存在錯誤!請重新輸入!')                    continue        elif func_in == '3':            print('3.修改過濾主機埠-----------------------------------')            func_in_3 = input('''是否開始修改連線失敗的埠號?yes/no>>:            ''')            if func_in_3 == 'yes':                port_new = int(input('請輸入新的埠號:'))                for i in conn_fail:                    i['port'] = port_new                    conn_amend.append(i)                print('\033[0;32m-\033[0m' * 90)                count = 0                for i in conn_amend:                    print(i)                    count += 1                input('''已完成主機列表的埠\033[0;32m%s\033[0m修改;共計:完成\033[0;32m%s\033[0m個回車繼續                ''' % (port_new, count))            else:                continue        elif func_in == '4':            print('4.檢視指令碼使用說明-----------------------------------')            input('''本指令碼使用步驟:        1.執行‘1.1’過濾主機        2.執行‘3’修改過濾後的主機埠        3.執行‘1.2’繼續過濾主機        4.執行‘2.1’開始批量操作主機        回車返回上級選單...            ''')        else:            exit(0)