python统一管理多台linux机器

来源:互联网 发布:映客刷人气软件 购买 编辑:程序博客网 时间:2024/06/04 19:59

一:使用方法

1. 该脚本可以统一管理多台linux, 测试发行版为redhat 和 suse,同时支持基于口令的连接和基于秘钥的连接

2. 其中BatchMan的目录内容如下:

[root@admin BatchMan]# ls
node.conf  pexpect  README  runcmd.py

注:其中目录pexpect内为suse10,11和rhel5,6发行版所需要的pexpect二进制包,内容如下

linux-xwc7:~ # ls Unify/pexpect

pexpect-2.3-1.rhel5.rpm  pexpect-2.3-1.sles10.rpm
pexpect-2.3-1.rhel6.rpm  pexpect-2.3-1.sles11.rpm

3. node.conf 的格式如下:

[NodeInfo]
User = root                  
Passwd = 111111
Port = 22
Nodes = suse[1-2]


User为连接时使用的用户名,Passwd为对应的用户名密码, SSHport为ssh服务监听端口

注: 使用时只需要按实际情况修改该文件即可


4.具体格式可查看README:

[root@admin BatchMan]# cat README 
#
# Wed Dec 30 15:35:07 CST 2015
#

1. Before you run this script, please edit the node.conf file properly.
2. A example for node.conf


[NodeInfo]

User = root            # the user for remote host
Passwd = 123456        # the passwd for user root
Port = 22              # the port for ssh service
Nodes = node[1-20]     # the nodes which you want to manage 

Typically, you only need to change the 'Passwd' and 'Nodes' fields

3. Examples for Nodes:

example_1 (Multi nodes):
            "Nodes = nb0[01-99]" ==>  nb001,nb002...nb009...nb099
            "Nodes = nb[01-52]-eth1" ==> nb01-eth1,nb02-eth1...nb52-eth1
            "Nodes = node[1-22]" ==> node1,node2...node22
example_2 (starting from serial number 2):
            "Nodes = nb0[02-99]" ==> nb002...nb099
            "Nodes = node[2-9]" ==> node2...node9
example_3 (only one node):
            "Nodes = node[1-1]" ==> node1
            "Nodes = compute[2-2]" ==> compute2


5. runcmd.py内容为:

#!/usr/bin/env pythonimport sysimport platformfrom re import compilefrom ConfigParser import ConfigParserfrom subprocess import PIPE, STDOUT, calldist, ver, arch = platform.dist()if dist not in ("redhat", "centos", "SuSE"):    print '''This script only support "redhat" and "SuSE"'''    sys.exit(1)try:    import pexpectexcept ImportError:    rhel5 = "rpm -ivh pexpect/pexpect-2.3-1.rhel5.rpm --force"    rhel6 = "rpm -ivh pexpect/pexpect-2.3-1.rhel6.rpm --force"    sles10 = "rpm -ivh pexpect/pexpect-2.3-1.sles10.rpm --force"    sles11 = "rpm -ivh pexpect/pexpect-2.3-1.sles11.rpm --force"    if dist in ('redhat', 'centos') and int(eval(ver)) == 5:        state = call(rhel5, shell=True, stdout=PIPE, stderr=STDOUT)    elif dist in ('redhat', 'centos') and int(eval(ver)) == 6:        state = call(rhel6, shell=True, stdout=PIPE, stderr=STDOUT)    elif dist == 'SuSE' and int(eval(ver)) == 10:        source_path = "/usr/local/lib64/python2.4/site-packages"        dest_path = "/usr/lib64/python2.4/site-packages"        state = call(sles10, shell=True, stdout=PIPE, stderr=STDOUT)    elif dist == 'SuSE' and int(eval(ver)) == 11:        source_path = "/usr/local/lib64/python2.6/site-packages"        dest_path = "/usr/lib64/python2.6/site-packages"        state = call(sles11, shell=True, stdout=PIPE, stderr=STDOUT)    if state == 0:        if dist in ('redhat', 'centos'):            import pexpect        else:            call("cp %s/* %s/" % (source_path, dest_path), shell=True, stdout=PIPE)            import pexpect    else:        print '''sorry, can't find the python module "pexpect"'''        sys.exit(1)user_admin = '''Password <%s> for %s@%s is incorrect. Please check the "node.conf" for Passwd !'''user_common = '''User <%s> does't exists or Password <%s> for %s@%s is incorrect.Please check the "node.conf" for User and Passwd !'''class BatchMan(object):    def __init__(self, user, passwd, command, port=22):        self.user = user        self.passwd = passwd        self.command = command        self.port = port        self.p3_obj = compile('continue connecting (yes/no)?')        self.p4_obj = compile('[Pp]assword:')        def __myExpect(self, child, time_out=30):        try:            try:                index = child.expect([self.p3_obj, self.p4_obj], timeout=time_out)                if index == 0:                    child.sendline('yes')                    child.expect(self.p4_obj)                    child.sendline(self.passwd)                    if child.expect(self.p4_obj) == 0:                        if self.user == "root":                            retval = user_admin % (self.passwd, self.user, host)                        else:                            retval = user_common % (self.user, self.passwd, self.user, host)                        return                    retval = child.read().strip()                elif index == 1:                    child.sendline(self.passwd)                    if child.expect(self.p4_obj) == 0:                        if self.user == "root":                            retval = user_admin % (self.passwd, self.user, host)                        else:                            retval = user_common % (self.user, self.passwd, self.user, host)                        return                    retval = child.read().strip()            except pexpect.EOF:                if 'scp: command not found' in child.before:                    retval = '===> command "scp" not found in %s' % host                else:                    retval = child.before.strip()            except pexpect.TIMEOUT:                retval = "Can't connect to host %s" % host        finally:            while child.isalive():                child.close()            print retval    def runCmd(self, host):        ssh = pexpect.spawn("ssh -p %s %s@%s %s" % (self.port,                                                    self.user,                                                    host,                                                    self.command))        self.__myExpect(ssh)    def runScp(self, host, source, dest):        scp = pexpect.spawn('scp -P %s %s %s@%s:%s' %(self.port,                                                      source,                                                      self.user,                                                      host,                                                      dest))        self.__myExpect(scp, 3600)if __name__ == "__main__":    ####### sys section ##########    args = sys.argv[1:]    if len(args) == 0:        print 'Usage: python %s <command>' % sys.argv[0]        sys.exit(1)    if args[0] == 'scp':        if len(args) != 3:            print 'Usage: python %s scp <local_source> <dest>' % sys.argv[0]            sys.exit(1)    command = ' '.join(args)    ####### ConfigParser #########    cf = ConfigParser()    cf.read('node.conf')    user = cf.get('NodeInfo', 'User')    passwd = cf.get('NodeInfo', 'Passwd')    port = cf.get('NodeInfo', 'Port')    exp = cf.get('NodeInfo', 'Nodes')        ######## get nodes ############    p1 = r'(^[a-zA-Z]+(\d+)?)\[(\d+)\-(\d+)\](.+)?'    p1_obj = compile(p1)    mo1 = p1_obj.search(exp)    if not mo1:        print '''"nodes" in "node.conf" should be writed as the following:example_1 (Multi nodes):            "Nodes = nb0[01-99]" ==>  nb001,nb002...nb009...nb099            "Nodes = nb[01-52]-eth1" ==> nb01-eth1,nb02-eth1...nb52-eth1            "Nodes = node[1-22]" ==> node1,node2...node22example_2 (starting from serial number 2):            "Nodes = nb0[02-99]" ==> nb002...nb099            "Nodes = node[2-9]" ==> node2...node9example_3 (only one node):            "Nodes = node[1-1]" ==> node1            "Nodes = compute[2-2]" ==> compute2'''        sys.exit(1)    prefix = mo1.group(1)    start = mo1.group(3)    stop = mo1.group(4)    if mo1.group(5):        suffix = mo1.group(5)    else:        suffix = ''    p2 = r'0*'    p2_obj = compile(p2)    mo2 = p2_obj.search(start)    if mo2:        zeronum = mo2.group()    else:        zeornum = ''    range_begin = int(start)    range_end = int(stop) + 1    hosts = []    for i in range(range_begin, range_end):        if i >= 10:            hosts.append(prefix + str(i) + suffix)        else:            hosts.append(prefix + zeronum + str(i) + suffix)     ###########################################################    batch = BatchMan(user, passwd, command)    if args[0] == 'scp':        source = args[1]        dest = args[2]        for host in hosts:            print '-' * 16 , '%s' % host, '-' * 16            print 'copying "%s" to "%s" ...' % (source, dest)            batch.runScp(host, source, dest)    else:        for host in hosts:            print '-' * 16 , '%s' % host, '-' * 16            batch.runCmd(host)
二. 使用示例

 1.统一执行系统命令,比如执行date和df -h命令

admin:~/BatchMan # python runcmd.py date
---------------- suse1 ----------------

Thu Oct 29 19:25:16 CST 2015

---------------- suse2 ----------------

Thu Oct 29 19:25:15 CST 2015

admin:~/BatchMan # python runcmd.py df -h |egrep "suse|sda2"
-------------------- suse1 --------------------
/dev/sda2       4.0G  1.5G  2.3G  40% /
-------------------- suse2 --------------------
/dev/sda2       4.0G  1.5G  2.3G  40% /

2.如果是要管理的机器已关机,或因网络问题、SSH服务问题连不上等原因,输出如下:

linux-xwc7:~/BatchMan # python runcmd.py df -h
---------------- suse1 ----------------
ssh: Could not resolve hostname suse1: Temporary failure in name resolution
---------------- suse2 ----------------
ssh: Could not resolve hostname suse2: Temporary failure in name resolution

3.往远程服务器复制文件,如复制/etc/hosts文件到各个节点的/etc目录下

linux-xwc7:~/BatchMan # python runcmd.py scp /etc/hosts /etc
---------------- suse1 ----------------
copying "/etc/hosts" to "/etc/" ...

---------------- suse2 ----------------
copying "/etc/hosts" to "/etc/" ...


0 0
原创粉丝点击