python加shell快速部署叢集

來源:互聯網
上載者:User

最近痛感在叢集裡逐台部署ganglia, cacti這些監控的東西很麻煩,就寫了個小程式去批量自動部署。原理是通過python的pexpect用ssh去複製檔案和執行系統命令,我用它來部署ganglia等,但是其他的東西也可以通過這個指令碼來批量部署,只要自己編寫部署指令碼就可以了。主要是提出一個解決思路,看對大家是否有所協助。


先約定一個概念,我們把放置python和指令碼的伺服器叫做主控節點或者server,把需要安裝的節點叫做受控節點或者client。以下均以server和client代稱。


首先是設定檔,我需要先定義一個設定檔,來約定server的一些路徑,和client具體資訊。

#-*-coding:UTF-8 -*-log_dir = './logs/'             #定義日誌路徑,不過我還沒寫,打算用log4py來做client_tmp_dir = '/tmp/'        #定義client端存放指令碼路徑ssh_port = '22'                 #SSH連接埠script_dir = './shells/'        #server端指令碼存放路徑node_list = [    {'ip':'192.168.1.1', 'user':'root', 'passwd':'123456', 'cmd':'sh /tmp/dpkg_client_ubuntu_x.x86_64.sh'},    #cmd為在client端執行的命令,別的不解釋    {'ip':'192.168.1.2', 'user':'root', 'passwd':'123456', 'cmd':'sh /tmp/dpkg_client_ubuntu_x.x86_64.sh'},]


接下來是主程式

#!/usr/bin/env python#-*-coding:UTF-8 -*-import osimport sysimport platform#用import方式引入conf.pyimport confimport subprocess'''判斷server(本機)作業系統類型和版本的類'''class System:    def GetBranch(self):        Branch = platform.dist()[0]        return Branch    def GetRelease(self):        Release = platform.dist()[1]        return Release    def GetInstaller(self):        if self.GetBranch() in ['Ubuntu', 'debian']:            installer = 'apt-get'        elif self.GetBranch() in ['redhat', 'fedora', 'centos']:            installer = 'yum'        elif self.GetBranch() in ['SuSE']:            installer = 'zypper'        else:            installer = 'unknown'        return installer'''以作業系統版本為依據擷取相應的pexpect包並嘗試引入,因pexpect非預設作業系統安裝,這部分支援RH,Ubuntu,Debian,SuSE'''try:    import pexpectexcept ImportError:    installer = System()    inst = install.GetInstaller()    if (inst == 'apt-get') or (inst == 'zypper'):        cmd = '%s install python-pexpect' % (inst)    elif inst == 'yum':        cmd = '$s install pexpect' % (inst)    else:        cmd = 'echo "Not support yet:)"';    try:        fd = subprocess.Popen( cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE )        out = fd.stdout.readlines()        err = fd.stderr.readlines()        all = out+err        all = "".join(all)    except OSError,e:        all = "Cannot run command, Exception:"+e+os.linesep    import pexpect#print all'''pexpect執行類,分兩個方法,ssh和scp,自動判斷是否首次串連,並自動完成yes或輸入密碼的應答。'''class Expect:    #定義ssh方法,入口變數包括ip, port,username,password,執行命令    def ssh(self, ip, port, user, passwd, cmd):        #建立串連子進程對象        ssh = pexpect.spawn('ssh -p %s %s@%s "%s"' % (port, user, ip, cmd))        r = ''        try:            #判斷是否首次串連,如果是首次,則回答yes並輸入密碼,否則直接輸入密碼            i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5)            if i == 0 :                ssh.sendline(passwd)            elif i == 1:                ssh.sendline('yes')                ssh.expect('password:')                ssh.sendline(passwd)        except pexpect.EOF:            ssh.close()        else:            r = ssh.read()            ssh.expect(pexpect.EOF)            ssh.close()        return r    #定義scp方法,入口變數包括ip,port,username,password,需要複製到client的檔案名稱,複製到client的路徑    def scp(self, ip, port, user, passwd, srcfile = "index.html", distpath):        #建立串連子進程對象        ssh = pexpect.spawn('scp -P %s %s %s@%s:%s ' % (port, file, user, ip, distpath))        r= ''        try:            #判斷是否首次串連,如果是首次,則回答yes並輸入密碼,否則直接輸入密碼            i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5)            if i == 0:                ssh.sendline(passwd)            elif i == 1:                ssh.senline('yes')                ssh.expect('password:')                ssh.sendline(passwd)        except pexpect.EOF:            ssh.close()        else:            r = ssh.read()            ssh.expect(pexpect.EOF)            ssh.close()        return r#建立conf中的對象,只是為了寫起來方便。不建立直接用也行packages = conf.package_dirlogs = conf.log_dirc_tmp = conf.client_tmp_dirport = conf.ssh_portscripts = conf.script_dirnodes = conf.node_listexpect = Expect()#在本機執行server端指令碼。該指令碼會安裝Ganglia gmetad,gmond,cacti,nagios,gangliaweb,mysql,apache等等os.system("sh " + scripts + "dpkg_server_ubuntu_x.x86_64.sh")#迴圈列出conf的列表中配置的主機,使用者名稱,密碼,執行命令for i in range(len(nodes)):    ip = nodes[i]['ip']    user = nodes[i]['user']    passwd = nodes[i]['passwd']    cmd = nodes[i]['cmd']    #將原生client執行指令碼複製到client端的conf.py中定義的路徑client_tmp_dir    r = expect.scp(ip, port, user, passwd, scripts+'dpkg_client_ubuntu_x.x86_64.sh', c_tmp)    print r    #在client端執行剛複製過去的指令碼,指令碼中包含gmond,nagios-client,snmpd等等    r = expect.ssh(ip, port, user, passwd, cmd)    print r


我還沒寫按自動判斷client端作業系統安裝不同指令碼的邏輯,有興趣的可以自己改改,其實本身指令碼並不難,核心都是在pexpect,我主要是不想用puppet,不想用puppet的主要原因是不想學ruby和他那複雜的設定檔。不光是部署監控,自己寫shell指令碼,隨便部署什麼都可以。nginx,php,反正能用指令碼完成的事都可以幹。

本文出自 “實踐檢驗真理” 部落格,謝絕轉載!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.