LzayManage[python版]批量管理

基於python2.7,經過ssh批量併發管理linux服務器,能夠執行命令,傳送文件,執行腳本python

禁用root的ssh登陸也可自動經過普通用戶後在su操做linux


wKiom1LLqZPyYnWhAAGDhjIssbk016.jpg


#!/usr/bin/python
#encoding:utf8
# LzayManage.py
# config file: serverlist.conf
import paramiko
import multiprocessing
import sys,os,time,socket,re
def Ssh_Cmd(host_ip,Cmd,user_name,user_pwd,port=22):
    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    s.connect(hostname=host_ip,port=port,username=user_name,password=user_pwd)
    stdin,stdout,stderr = s.exec_command(Cmd)
    Result = '%s%s' %(stdout.read(),stderr.read())
    q.put('successful')
    s.close()
    return Result.strip()
def Ssh_Su_Cmd(host_ip,Cmd,user_name,user_pwd,root_name,root_pwd,port=22):
    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    s.connect(hostname=host_ip,port=port,username=user_name,password=user_pwd)
    ssh = s.invoke_shell()
    time.sleep(0.1)
    ssh.send('su - %s\n' %(root_name))
    buff = ''
    while not buff.endswith('Password: '):
        resp = ssh.recv(9999)
        buff +=resp
    ssh.send('%s\n' %(root_pwd))
    buff = ''
    while True:
        resp = ssh.recv(9999)
        buff +=resp
        if ': incorrect password' in buff:
            su_correct='passwd_error'
            break
        elif buff.endswith('# '):
            su_correct='passwd_correct'
            break
    if su_correct == 'passwd_correct':
        ssh.send('%s\n' %(Cmd))
        buff = ''
        while True:
            resp = ssh.recv(9999)
            if resp.endswith('# '):
                buff +=re.sub('\[.*@.*\]# $','',resp)
                break
            buff +=resp
        Result = buff.lstrip('%s' %(Cmd))
        q.put('successful')
    elif su_correct == 'passwd_error':
        Result = "\033[31mroot密碼錯誤\033[m"
    s.close()
    return Result.strip()
def Send_File(host_ip,PathList,user_name,user_pwd,Remote='/tmp',port=22):
    s=paramiko.Transport((host_ip,port))
    s.connect(username=user_name,password=user_pwd)
    sftp=paramiko.SFTPClient.from_transport(s)
    for InputPath in PathList:
        LocalPath = re.sub('^\./','',InputPath.rstrip('/'))
        RemotePath = '%s/%s' %( Remote , os.path.basename( LocalPath ))
        try:
            sftp.rmdir(RemotePath)
        except:
            pass
        try:
            sftp.remove(RemotePath)
        except:
            pass
        if os.path.isdir(LocalPath):
            sftp.mkdir(RemotePath)
            for path,dirs,files in os.walk(LocalPath):
                for dir in dirs:
                    dir_path = os.path.join(path,dir)
                    sftp.mkdir('%s/%s' %(RemotePath,re.sub('^%s/' %LocalPath,'',dir_path)))
                for file in files:
                    file_path = os.path.join(path,file)
                    sftp.put( file_path,'%s/%s' %(RemotePath,re.sub('^%s/' %LocalPath,'',file_path)))
        else:
            sftp.put(LocalPath,RemotePath)
    q.put('successful')
    sftp.close()
    s.close()
    Result = '%s  \033[32m傳送完成\033[m' % PathList
    return Result
def Ssh(host_ip,Operation,user_name,user_pwd,root_name,root_pwd,Cmd=None,PathList=None,port=22):
    msg = "\033[32m-----------Result:%s----------\033[m" % host_ip
    try:
        if Operation == 'Ssh_Cmd':
            Result = Ssh_Cmd(host_ip=host_ip,Cmd=Cmd,user_name=user_name,user_pwd=user_pwd,port=port)
        elif Operation == 'Ssh_Su_Cmd':
            Result = Ssh_Su_Cmd(host_ip=host_ip,Cmd=Cmd,user_name=user_name,user_pwd=user_pwd,root_name=root_name,root_pwd=root_pwd,port=port)
        elif Operation == 'Ssh_Script':
            Send_File(host_ip=host_ip,PathList=PathList,user_name=user_name,user_pwd=user_pwd,port=port)
            Script_Head = open(PathList[0]).readline().strip()
            LocalPath = re.sub('^\./','',PathList[0].rstrip('/'))
            Cmd = '%s /tmp/%s' %( re.sub('^#!','',Script_Head), os.path.basename( LocalPath ))
            Result = Ssh_Cmd(host_ip=host_ip,Cmd=Cmd,user_name=user_name,user_pwd=user_pwd,port=port)
        elif Operation == 'Ssh_Su_Script':
            Send_File(host_ip=host_ip,PathList=PathList,user_name=user_name,user_pwd=user_pwd,port=port)
            Script_Head = open(PathList[0]).readline().strip()
            LocalPath = re.sub('^\./','',PathList[0].rstrip('/'))
            Cmd = '%s /tmp/%s' %( re.sub('^#!','',Script_Head), os.path.basename( LocalPath ))
            Result = Ssh_Su_Cmd(host_ip=host_ip,Cmd=Cmd,user_name=user_name,user_pwd=user_pwd,root_name=root_name,root_pwd=root_pwd,port=port)
        elif Operation == 'Send_File':
            Result = Send_File(host_ip=host_ip,PathList=PathList,user_name=user_name,user_pwd=user_pwd,port=port)
        else:
            Result = '操做不存在'
                  
    except socket.error:
        Result = '\033[31m主機或端口錯誤\033[m'
    except paramiko.AuthenticationException:
        Result = '\033[31m用戶名或密碼錯誤\033[m'
    except paramiko.BadHostKeyException:
        Result = '\033[31mBad host key\033[m['
    except IOError:
        Result = '\033[31m遠程主機已存在非空目錄或沒有寫權限\033[m'
    except:
        Result = '\033[31m未知錯誤\033[m'
    r.put('%s\n%s\n' %(msg,Result))
def Concurrent(Conf,Operation,user_name,user_pwd,root_name,root_pwd,Cmd=None,PathList=None,port=22):
    # 讀取配置文件
    f=open(Conf)
    list = f.readlines()
    f.close()
    # 執行總計
    total = 0
    # 併發執行
    for host_info in list:
        # 判斷配置文件中註釋行跳過
        if host_info.startswith('#'):
            continue
        # 取變量,其中任意變量未取到就跳過執行
        try:
            host_ip=host_info.split()[0]
            #user_name=host_info.split()[1]
            #user_pwd=host_info.split()[2]
        except:
            print('Profile error: %s' %(host_info) )
            continue
        try:
            port=int(host_info.split()[3])
        except:
            port=22
        total +=1
        p = multiprocessing.Process(target=Ssh,args=(host_ip,Operation,user_name,user_pwd,root_name,root_pwd,Cmd,PathList,port))
        p.start()
    # 打印執行結果
    for j in range(total):
        print(r.get() )
    if Operation == 'Ssh_Script' or Operation == 'Ssh_Su_Script':
        successful = q.qsize() / 2
    else:
        successful = q.qsize()
    print('\033[32m執行完畢[總執行:%s 成功:%s 失敗:%s]\033[m' %(total,successful,total - successful) )
    q.close()
    r.close()
def Help():
    print('''   1.執行命令
    2.執行腳本      \033[32m[位置1腳本(必須帶腳本頭),後可帶執行腳本所須要的包\文件\文件夾路徑,空格分隔]\033[m
    3.發送文件      \033[32m[傳送的包\文件\文件夾路徑,空格分隔]\033[m
    退出: 0\exit\quit
    幫助: help\h\?
    注意: 發送文件默認爲/tmp下,如已存在同名文件會被強制覆蓋,非空目錄則中斷操做.執行腳本先將本地腳本及包發送遠程主機上,發送規則同發送文件
    ''')
if __name__=='__main__':
    # 定義root帳號信息
    root_name = 'root'
    root_pwd = 'peterli'
    user_name='peterli'
    user_pwd='xuesong'
    # 配置文件
    Conf='serverlist.conf'
    if not os.path.isfile(Conf):
        print('\033[33m配置文件 %s 不存在\033[m' %(Conf) )
        sys.exit()
    Help()
    while True:
        i = raw_input("\033[35m[請選擇操做]: \033[m").strip()
        q = multiprocessing.Queue()
        r = multiprocessing.Queue()
        if i == '1':
            if user_name == root_name:
                Operation = 'Ssh_Cmd'
            else:
                Operation = 'Ssh_Su_Cmd'
            Cmd = raw_input('CMD: ').strip()
            if len(Cmd) == 0:
                print('\033[33m命令爲空\033[m')
                continue
            Concurrent(Conf=Conf,Operation=Operation,user_name=user_name,user_pwd=user_pwd,root_name=root_name,root_pwd=root_pwd,Cmd=Cmd)
        elif i == '2':
            if user_name == root_name:
                Operation = 'Ssh_Script'
            else:
                Operation = 'Ssh_Su_Script'
            PathList = raw_input('\033[36m本地腳本路徑: \033[m').strip().split()
            if len(PathList) == 0:
                print('\033[33m路徑爲空\033[m')
                continue
            if not os.path.isfile(PathList[0]):
                print('\033[33m本地路徑 %s 不存在或不是文件\033[m' %(PathList[0]) )
                continue
            for LocalPath in PathList[1:]:
                if not os.path.exists(LocalPath):
                    print('\033[33m本地路徑 %s 不存在\033[m' %(LocalPath) )
                    break
            else:
                Concurrent(Conf=Conf,Operation=Operation,user_name=user_name,user_pwd=user_pwd,root_name=root_name,root_pwd=root_pwd,PathList=PathList)
        elif i == '3':
            Operation = 'Send_File'
            PathList = raw_input('\033[36m本地路徑: \033[m').strip().split()
            if len(PathList) == 0:
                print('\033[33m路徑爲空\033[m')
                continue
            for LocalPath in PathList:
                if not os.path.exists(LocalPath):
                    print('\033[33m本地路徑 %s 不存在\033[m' %(LocalPath) )
                    break
            else:
                Concurrent(Conf=Conf,Operation=Operation,user_name=user_name,user_pwd=user_pwd,root_name=root_name,root_pwd=root_pwd,PathList=PathList)
        elif i == '0' or i == 'exit' or i == 'quit':
            print("\033[34m退出LazyManage腳本\033[m")
            sys.exit()
        elif i == 'help' or i == 'h' or i == '?':
            Help()
#END
相關文章
相關標籤/搜索