自动化,批量化是作为管理员,或者运维人员必须面临的问题。自动化和批量化也有很多方式,可以用单一工具也可以自己写shell脚本,甚至可以开发出来一套完备的任务管理系统。其实我们大多时候可以在一台主机上面通过ssh来控制所有机器,来完成我们的任务工作。是否有这样的工具来支持我们呢?
fabric是对ssh的一个集成工具,对我们而言只需要使用相应的接口,来高效的完成工作,我们常用到的功能基本是 : 本地或者远端执行命令, 分发文件,收集文件,还有一些权限相关的操作。 这些fabric都给我们提供了对应的接口。
如下所示:
1 2 3 4 5 6 7 | run ( fabric . operations . run ) sudo ( fabric . operations . sudo ) local ( fabric . operations . local ) get ( fabric . operations . get ) put ( fabric . operations . put ) prompt ( fabric . operations . prompt ) reboot ( fabric . operations . reboot ) |
接口部分提供了命令运行的方式,不过都无法保持上下文关系,为了解决这个问题,fabric的context manager 就派上了用场:
1 2 3 4 5 | cd ( fabric . context_managers . cd ) lcd ( fabric . context_managers . lcd ) path ( fabric . context_managers . path ) settings ( fabric . context_managers . settings ) prefix ( fabric . context_managers . prefix ) |
1 | easy_install fabric |
由于fabric是基于python的,所以写fabric脚本就是写python脚本,你可以像写python脚本一样,可以依赖其他模块或者其他工具来完成工作。Fabric 脚本,通过fab工具运行fabric python脚本。fab工具默认执行fabfile.py ,也可以通过-f 参数指定 脚本文件名。fabric优势多多,简单,方便,日志输出清晰,命令
中可以使用AWK 命令 下面我们看一个 hello world 程序。
1 2 3 4 5 | from fabric . api import * def helloworld ( who = ‘world’ ) : print “Hello {0}!” . format ( who ) def helloworld1 ( you = ‘world’ , me = ‘ruiaylin’ ) : print “Hello {0}! i am {1} ! “ . format ( you , me ) |
执行命令(其中参数的传递直接跟在任务后跟变量名和参数):
1 2 3 4 5 6 | fabric fab – f helloword . py helloworld Hello world ! Done . fabric fab – f helloword . py helloworld1 : you = ‘ruichao’ , me = ‘ruiaylin’ Hello ruichao ! i am ruiaylin ! Done . |
我们已经看了一个简单例子下面我们来看一下fabric的主要接口。
Fabric 中使用最多的就是 run 方法了。run是用来在一台或者多台远程主机上面执行shell 命令。
使用方法:
1 2 3 4 5 6 | # creat a directory run ( ” mkdir /tmp/testdir/ -p “ ) # check process result = run ( “ps -ef |grep mysqld|grep -v safe |grep -v grep | wc -l “ #Check if command result . failed |
使用 sudo 命令执行对顶的命令。使用方法与run 类似。
local 命令是执行本机的命令或者脚本.使用方法和run 还有sudo类似,但是有一个区别
就是: 捕获结果的时候,是通过指定 capture=False 或者capture=True来确定。来看
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # example like this : def helloworld ( who = ‘world’ ) : print “Hello {0}!” . format ( who ) yy = local ( ” pwd “ , capture = False ) print ‘start : yy = ‘ , yy , ‘ : :: ‘ , yy . succeeded zz = local ( ” pwd “ , capture = True ) print ‘start : zz = ‘ , zz , ‘ : :: ‘ , zz . succeeded #result : fabric fab – f helloword . py helloworld – H 10.211.55.3 – u root [ 10.211.55.3 ] Executing task ‘helloworld’ Hello world ! [ trustauth.cn ] local : pwd / Users / ruiaylin / Documents / workpython / fabric start : yy = : :: True [ trustauth.cn ] local : pwd start : zz = / Users / ruiaylin / Documents / workpython / fabric : :: True |
get 方法是从远程主机 copy file 到本地,功能跟scp一样。可以从远程主机下载
备份,或者日志文件等等。
使用方法如下:
1 2 3 4 | # Download some logs get ( remote_path = “/tmp/xxx.log” , local_path = “/tmp/xxx.log” ) # Download a database back-up get ( “/backup/db.gz” , “./db.gz” ) |
某些需要上传和分发文件的时候,put命令就派上了用场,使用方式类似 get。也同样可以
通过.failed .succeeded进行命令是否执行成功的判断。
如下例子:
1 | upload = put ( “requirements.txt” , “requirements.txt” , mode = 0664 ) |
目前官方来看 1.X 版本的fabric 并行执行的时候不是thread safe的。如果需要并行执行task。需要在方法上面使用注解 @parallel 为了防止管控机器上面过多的并发任务可以通过 @parallel(pool_size=5)来设置. 并行的执行输出都会输出到一个终端上面,比较混乱。最好是写到日志,以task为维度。跟下面的代码类似。
安装步骤如下
基本脚本如下:
script 1 sub task :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | from fabric . api import * from fabric . colors import green , red , blue , cyan , yellow import os , sys import socket import datetime import logging import logging.handlers #get logger for logging def initLoggerWithRotate ( ) : logname = ” . join ( env . host_string . split ( ‘.’ ) ) + ‘.log’ logFileName = “logs/%s” % logname logger = logging . getLogger ( “fabric” ) formater = logging . Formatter ( “%(asctime)s %(name)s %(levelname)s %(message)s” , “%Y-%m-%d %H:%M:%S” ) file_handler = logging.handlers . RotatingFileHandler ( logFileName , maxBytes = 104857600 , backupCount = 5 ) file_handler . setFormatter ( formater ) stream_handler = logging . StreamHandler ( sys . stderr ) logger . addHandler ( file_handler ) logger . addHandler ( stream_handler ) logger . setLevel ( logging . INFO ) return logger #mkdir def runmkdir ( dir ) : run ( ”’ mkdir -p %s ”’ % dir ) #stp 1 check host def checkhost ( logger ) : host = env . host _string s = socket . socket ( socket . AF_INET , socket . SOCK_STREAM ) flag_c = 0 try : s . connect ( ( host , 22 ) ) flag_c = 1 logger . info ( green ( ‘ –> host %s can be reachable ‘ % host ) ) except socket . error as e : logger . warning ( yellow ( ‘ –> Error on connect %s’ % e ) ) s . close ( ) return flag_c #stp 2 check alive instance on target host def checkmysqlinstance ( logger ) : try : wc = run ( ”’ ps -ef |grep mysqld|grep -v safe | grep -v grep | wc -l ”’ ) if int ( wc ) > 0 : logger . warning ( yellow ( ‘ –> %sinstance exist on the target host ‘ % wc ) ) portraw = run ( ”’ ps -ef |grep mysqld|grep -v safe |grep -v grep |awk ‘ {for(i=1;i<=NF;i++){if($i ~/–port/ ){print $i}}}’ |awk -F ‘=’ ‘{print $2}’ ”’ ) ports = [ x . strip ( ) for x in portraw . split ( ) ] logger . warning ( yellow ( ‘ –> existing instance port : [ %s ] ‘ % ( ‘,’ . join ( ports ) ) ) ) if port in ports : logger . error ( red ( ‘ –> Install port %s exist , install failed ‘ % port ) ) logger . error ( red ( ‘ <<<exit>>>>> task on host %s stop & exit() ‘ % thost ) ) sys . exit ( ) except Exception , e : logger . warning ( yellow ( ‘ –> checkmysqlinstance() exception : %s ‘ % e ) ) raise e #stp 3 initdir for installation def createUser ( logger , user = ‘mysql’ , group = ‘dba’ ) : try : if int ( run ( ‘grep “^mysql” /etc/passwd|wc -l’ ) ) == 0 : run ( ‘groupadd dba ‘ ) run ( ‘useradd -c “mysql software owner” -g dba -G dba mysql’ ) run ( ‘mkdir -p /home/mysql ; chown -R mysql.dba /home/mysql ‘ ) logger . info ( cyan ( ‘ –> create user [ mysql ] in group [ dba ] success ‘ ) ) else : logger . info ( yellow ( ‘ –> user [ mysql ] in group [ dba ] exist & skip ‘ ) ) except Exception , e : logger . warning ( yellow ( ‘ –> createUser() exception : %s ‘ % e ) ) raise e #stp 4 initail directory for mysql def initdir ( logger , port = 3306 ) : try : logger . info ( green ( ‘ –> begin to create dirs for installation ‘ ) ) datadir = ‘/data/’ logdir = ‘/log/’ mandir = ‘mysql%s’ % port subddir = ‘/data/mysql%s/{data,log,run,tmp}’ % ( port ) subldir = ‘/log/mysql%s/{binlog,iblog}’ % ( port ) #data ck1 = run ( ‘ df -vh | grep /data | wc -l ‘ ) if ck1 == 0 : logger . error ( green ( ‘ –> no /data/ partition exist’ ) ) #sys.exit() if int ( run ( ‘ ls / | grep /data | wc -l ‘ ) ) == 0 or int ( run ( ‘ ls /data/ | grep -w %s | wc -l ‘ % mandir ) ) == 0 : runmkdir ( subddir ) logger . info ( green ( ‘ –> /data/*** create Ok ‘ ) ) else : logger . info ( green ( ‘ –> /data/mysql%s exsit ‘ % port ) ) logger . info ( green ( ‘ –> pls,handle it and restart this task ‘ ) ) sys . exit ( ) #log ck2 = run ( ‘ df -vh | grep /log/ | wc -l ‘ ) if int ( run ( ‘ df -vh | grep /log/ | wc -l ‘ ) ) == 0 and int ( run ( ‘ ls / | grep -w log | wc -l ‘ ) ) == 0 : logger . warning ( yellow ( ‘ –> no /log/ partition exist’ ) ) logger . warning ( yellow ( ‘ –> create link for /log/ –> /data/log/’ ) ) runmkdir ( ‘/data/log’ ) run ( ‘ln -s /data/log /log ‘ ) runmkdir ( subldir ) logger . info ( green ( ‘ –> /log/*** create Ok ‘ ) ) else : if int ( run ( ‘ ls /log/ | grep -w %s | wc -l ‘ % mandir ) ) == 0 : runmkdir ( subldir ) logger . info ( green ( ‘ –> /log/*** create Ok ‘ ) ) else : logger . info ( yellow ( ‘ –> /log/mysql%s exsit ‘ % port ) ) logger . error ( red ( ‘ –> pls,handle it and restart this task ‘ ) ) sys . exit ( ) #change runmkdir ( ‘/data/tmp’ ) logger . info ( green ( ‘ –> change dirs owner&privs start’ ) ) run ( ‘chown -R mysql:dba /data/*’ ) run ( ‘chown -R mysql:dba /log’ ) logger . info ( green ( ‘ –> change dirs owner&privs done’ ) ) except Exception , e : logger . warning ( yellow ( ‘ –> initdir() exception : %s ‘ % e ) ) raise e #stp 5 put mysql install package def copymysql ( logger , version = ‘5.7’ ) : try : dits = { ‘ubuntu’ : ‘mysql-server_5.6.21-1ubuntu12.04_amd64.deb-bundle.tar’ , ‘centos’ : ‘mysql-server.tar.gz’ } issue = run ( ‘cat /etc/issue’ ) ss = issue . lower ( ) logger . info ( green ( ‘ %s ‘ % ss ) ) if int ( run ( ‘ ls /usr/local/ | grep mysql | wc -l ‘ ) ) > 0 : logger . info ( yellow ( ‘ –> mysql software installed , skip ‘ ) ) return plats = dits . keys ( ) for x in plats : if ss . find ( x ) != – 1 : logger . info ( green ( ‘ –> the target host platform is %s’ % x ) ) put ( local_path = “configs/%s” % dits [ x ] , remote_path = “/tmp/%s” % dits [ x ] ) logger . info ( green ( ‘ –> tar the ball to prop dir ‘ ) ) run ( ‘tar zxvf /tmp/%s -C /usr/local/ ‘ % dits [ x ] ) run ( ‘ln -s /usr/local/%s /usr/local/mysql ‘ % dits [ x ] [ : – 7 ] ) break except Exception , e : logger . warning ( yellow ( ‘ –> copymysql() exception : %s ‘ % e ) ) raise e #gen my.cnf file def getnewServerId ( logger , port ) : host = env . host_string print ‘getnewServerId : ‘ , host pics = host . split ( ‘.’ ) a = int ( pics [ 0 ] ) b = int ( pics [ 1 ] ) c = int ( pics [ 2 ] ) d = int ( pics [ 3 ] ) suf = int ( port ) % 256 server_id = b * 256 * 256 * 256 + c * 256 * 256 + d * 256 + suf logger . info ( cyan ( ‘ –> gen server_id done , %s %s is %s ‘ % ( host , port , server_id ) ) ) return server_id def genmycnf ( logger , port = 3306 , itype = ‘h’ ) : host = env . host_string bps = { “a” : “48|32|3100|3000” , “b” : “62|40|4600|4500” , ‘c’ : ’94|64|7600|7500′ , ‘d’ : ’94|32|3100|3000′ , ‘e’ : ‘125|75|10100|10000’ , ‘f’ : ‘188|120|15100|15000’ , ‘g’ : ‘188|60|7600|7500’ , ‘h’ : ‘1|256M|800|750’ } try : myfile = ” . join ( host . split ( ‘.’ ) ) + ‘.cnf’ cpmycnf = “””cp configs/my.cnf tmp/%s “”” % myfile local ( ‘rm -f tmp/%s’ % myfile ) local ( “cp configs/my.cnf tmp/%s “ % myfile ) sid = getnewServerId ( logger , port ) keys = bps . keys ( ) bpxs = bps [ itype ] mem , bpsize , maxc , maxuc = bpxs . split ( ‘|’ ) if bpsize [ – 1 ] != “M” : bpsize = bpsize + ‘g’ chrgcmd = “”” sed -i -e “s/3306/%s/g” -e “s/server_id=10000/server_id=%s/g” -e “s/=32g/=%s/g” -e “s/max_connections=3100/max_connections=%s/g” -e “s/max_user_connections=3000/max_user_connections=%s/g” tmp/%s “”” local ( chrgcmd % ( port , sid , bpsize , maxc , maxuc , myfile ) ) logger . info ( green ( ‘ –> gen my.cnf success ‘ ) ) logger . info ( green ( ‘ –> copy my.cnf to dist host ‘ ) ) put ( local_path = “tmp/%s” % myfile , remote_path = “/data/mysql%s/my.cnf” % ( port ) ) except Exception , e : logger . warning ( yellow ( ‘ –> genmycnf() exception : %s ‘ % traceback . format_exc ( ) ) ) raise e |
script 2 whole task :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import inst_utils from inst_utils import * def install_mysql ( port ) : logger = initLoggerWithRotate ( ) thost = env . host_string try : logger . info ( green ( ‘stp 1 get the host %s ‘ % thost ) ) #check host reachable rs1 = checkhost ( logger ) if int ( rs1 ) == 0 : logger . info ( red ( ‘stp 2 check the host is reachable failed ‘ ) ) logger . info ( green ( ‘stp 2 check the host is reachable OK ‘ ) ) plat_type = run ( ”’ uname -o ”’ ) if plat_type != ‘GNU/Linux’ : logger . warning ( yellow ( ‘stp 3 target platform is not GNU/Linux & exit() ‘ ) ) sys . exit ( ) logger . info ( green ( ‘stp 3 target platform is GNU/Linux’ ) ) #check target host exsist mysql instance logger . info ( green ( ‘stp 4 checkmysqlinstance ‘ ) ) checkmysqlinstance ( logger ) #create MySQL user logger . info ( green ( ‘stp 5 createUser ‘ ) ) createUser ( logger ) put ( local_path = “configs/bash_profile” , remote_path = “/home/mysql/.bash_profile” ) #checking dir logger . info ( green ( ‘stp 6 initdir ‘ ) ) initdir ( logger , port ) #copy file logger . info ( green ( ‘stp 7 copymysql ‘ ) ) copymysql ( logger ) logger . info ( green ( ‘stp 8 genmycnf ‘ ) ) genmycnf ( logger , port , ‘h’ ) except Exception , e : print ‘main : exception : ‘ , e |
文章转载来自:trustauth.cn