zoukankan      html  css  js  c++  java
  • 通过shell脚本实现代码自动化部署

    通过shell脚本实现代码自动化部署

    一、传统部署方式及优缺点

    1.传统部署方式

    1)纯手工scp

    2)纯手工登录git pullsvn update

    3)纯手工xftp往上拉

    4)开发给打一个压缩包,rz上去;解压

    2.缺点

    1)全程运维参与,占用大量时间

    2)上线速度慢

    3)人为失误多,管理混乱

    4)回滚慢,不及时

    二、环境规划

    1、开发环境--开发者本地有自己的环境。

    运维需要设置的开发环境,大家共用的服务。

    2、测试环境:功能测试环境和性能测试环境。

    3、预生产环境:生产环境集群中的某一个节点。

    4、生产环境:直接对用户提供服务的环境。

    测试环境与生产环境的数据库不一致时,可能会导致测试的功能不全面,在测试环境测无问题,放在线上可能出现问题

    三、需求分析

    一、功能需求需求

    一个集群有十个节点

    1.实现 一键部署10个节点

    2.一键回滚到任意版本

    3.一键回滚到上个版本

    二、部署需求

    部署:

    1.代码在哪里:svngit

    2.获取什么版本代码?

    svn/git:直接拉去某个分支

    svn:指定版本号

    git:指定tag

    3.差异解决:

    1)各个节点直接差异:配置文件未必一致(crontab.xml)。预生产节点。

    2)代码仓库和实际的差异。配置文件是否放在代码仓库中。

    4.如何更新

    更新时需要考虑是否重启。例如java代码,需要考虑重启tomcat。重启过程中,用户就不能访问了。

    5.测试

    部署多个节点,某个节点由于配置问题导致部署不成功。如何测试。

    6.串行和并行

    部署多个节点,串行部署还是并行部署,视具体业务需求决定。

    7.如何执行

    1.shell脚本,直接执行

    2.web界面

    三、部署流程

    1.获取代码(直接拉取)---- 2.编译(可选)---- 3.配置文件放进去---- 4.打包 ---- 

     

    5.SCP到目标服务器---- 6.将目标服务器移除集群---- 7.解压 ---- 8.放置到webroot ----

     

    9.SCP差异文件 ---- 10.重启(可选) ---- 11.测试 ---- 12.加入集群

    四、代码实现

    1、设置无交互访问

    通过ssh-keygen将部署机的公钥发送给应用服务器。

    注意,这里通常是用普通用户登陆部署机,生成公钥后,再把公钥发给应用服务器

     

    ssh-keygen -t rsa

     

    切换到.ssh目录下

    [www@linux-node1 ~/.ssh]$ ll

    total 16

    -rwx------ 1 www www  397 Jul 31 22:45 authorized_keys

    -rwx------ 1 www www 1679 Jul 31 22:44 id_rsa

    -rwx------ 1 www www  397 Jul 31 22:44 id_rsa.pub

     

    id_rsa.pub中的内容复制粘贴到应用服务器的www用户的.ssh目录下,

    文件名称为authorized_keys

     

    [www@linux-node2 .ssh]$ cat authorized_keys 

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqT3VwY9Wo7tKsXa4Ce1zXGLT/Iygy30tDBKnV4HW4g5BdUS48urTvYljL9cwJ/HWvoqbtJ5mc7PMmhDMOAjIh1CRZtGxKEkQFB/Xp5cLeAsE7iH+WfkNqavFHD75+YuM2mbNBvisDXO+/pJ/QfbmYwWJ6CW6uLpQKpitdJwrLpQDJGQv5H3aV0kHKZdoA+twdXm0LmQcWWJt7zruPq19CAXG5b93KTdgyt/1x4BfcT5/+PCaEd9suYwEneI2Io8CX9oTAe3MRyRPtlN0szT89qP/q+Q4sktVjc1nkxHhdP2mahqeiBLUGULfkgUBtEjaGAFSWb+ejFV0fRDHk6bSJ www@linux-node1

     

    注意,修改authorized_keys的权限

    chmod 600 authorized_keys

     

    另外,将.ssh目录的权限设置成700

    chmod 700 .ssh

    2、详细代码

      1 #!/bin/bash
      2 
      3 #Node List
      4 
      5 PRE_LIST="192.168.56.11"
      6 
      7 GROUP1_LIST="192.168.56.12"
      8 
      9 ROLLBACK_LIST="192.168.56.11 192.168.56.12"
     10 
     11 #Date/Time Variable
     12 
     13 LOG_DATE='date "+%Y-%m-%d"'
     14 
     15 LOG_TIME='date "+%H-%M-%S"'
     16 
     17 CDATE=$(date "+%Y-%m-%d")
     18 
     19 CTIME=$(date "+%H-%M-%S")
     20 
     21 #Shell env
     22 
     23 SHELL_NAME="/deploy1.sh"
     24 
     25 SHELL_DIR="/home/www/"
     26 
     27 SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
     28 
     29 #Code ENV
     30 
     31 PRO_NAME="web-demo"
     32 
     33 CODE_DIR="/deploy/code/web-demo"
     34 
     35 CONFIG_DIR="/deploy/config/web-demo"
     36 
     37 TMP_DIR="/deploy/tmp"
     38 
     39 TAR_DIR="/deploy/tar"
     40 
     41 LOCK_FILE="/tmp/deploy.lock"
     42 
     43  
     44 
     45 usage(){
     46 
     47          echo $"Usage: $0 {deploy | rollback [ list | version ]} "
     48 
     49 }
     50 
     51  
     52 
     53 writelog(){
     54 
     55          LOGINFO=$1
     56 
     57          echo "${CDATE}${CTIME}: ${SHELL_NAME}: ${LOGINFO} " >> ${SHELL_LOG}
     58 
     59 }
     60 
     61  
     62 
     63  
     64 
     65 shell_lock(){
     66 
     67          touch ${LOCK_FILE}
     68 
     69 }
     70 
     71  
     72 
     73 shell_unlock(){
     74 
     75          rm -f ${LOCK_FILE} 
     76 
     77 }
     78 
     79  
     80 
     81 code_get(){
     82 
     83          writelog "code_get";
     84 
     85          cd $CODE_DIR && echo "git pull";
     86 
     87         cp -r ${CODE_DIR} ${TMP_DIR}/
     88 
     89          API_VER="456"       
     90 
     91 }
     92 
     93  
     94 
     95 code_build(){
     96 
     97          echo code_build
     98 
     99 }
    100 
    101  
    102 
    103 code_config(){
    104 
    105          writelog "code_config"
    106 
    107          /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}"
    108 
    109          PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}"
    110 
    111          cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME}       
    112 
    113 }
    114 
    115  
    116 
    117 code_tar(){
    118 
    119          writelog "code_tar"
    120 
    121          cd ${TMP_DIR} && tar czf ${PKG_NAME}.tar.gz $PKG_NAME
    122 
    123          writelog "${PKG_NAME}.tar.gz"
    124 
    125 }
    126 
    127  
    128 
    129 code_scp(){
    130 
    131          writelog "code_scp"
    132 
    133          for node in $PRE_LIST;do
    134 
    135                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
    136 
    137          done
    138 
    139          for node in $GROUP1_LIST;do
    140 
    141                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
    142 
    143          done
    144 
    145 }
    146 
    147  
    148 
    149 cluster_node_remove(){
    150 
    151          writelog  "cluster_node_remove"
    152 
    153 }
    154 
    155  
    156 
    157 pre_deploy(){
    158 
    159          writelog "remove from cluster"  
    160 
    161         ssh $PRE_LIST "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
    162 
    163         ssh $PRE_LIST "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
    164 
    165 }
    166 
    167 url_test(){
    168 
    169          URL=$1
    170 
    171          curl -s --head $URL|grep "200 OK"
    172 
    173          if [ $? -ne 0 ];then
    174 
    175                  shell_unlock;
    176 
    177                  writelog "test error" && exit;
    178 
    179          fi
    180 
    181 }
    182 
    183 pre_test(){
    184 
    185          url_test "http://${PRE_LIST}/index.html"
    186 
    187          echo "add to cluster"
    188 
    189 }
    190 
    191  
    192 
    193 group1_deploy(){
    194 
    195          writelog "remove from cluster"
    196 
    197         
    198 
    199          for node in $GROUP1_LIST;do
    200 
    201                 ssh $node "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
    202 
    203                  ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
    204 
    205         done    
    206 
    207          scp ${CONFIG_DIR}/other/192.168.56.12.crontab.xml 192.168.56.12:/webroot/web-demo/crontab.xml
    208 
    209 }
    210 
    211  
    212 
    213 group1_test(){
    214 
    215          url_test "http://192.168.56.12/index.html"
    216 
    217          echo "add to cluster"
    218 
    219 }
    220 
    221 rollback_fun(){
    222 
    223          for node in $ROLLBACK_LIST;do
    224 
    225                 ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo"
    226 
    227         done 
    228 
    229 }
    230 
    231 rollback(){
    232 
    233 if [ -z $1 ];then
    234 
    235          shell_unlock; 
    236 
    237          echo "please input rollback version" && exit;
    238 
    239 fi
    240 
    241          case $1 in
    242 
    243              list)
    244 
    245                  ls -l /opt/webroot/*.tar.gz
    246 
    247                  ;;
    248 
    249              *)
    250 
    251                  rollback_fun $1
    252 
    253          esac        
    254 
    255 }
    256 
    257  
    258 
    259 main(){
    260 
    261     if [ -f $LOCK_FILE ];then
    262 
    263          echo "Deploy is running" && exit;
    264 
    265     fi
    266 
    267     DEPLOY_METHON=$1
    268 
    269     ROLLBACK_VER=$2
    270 
    271     case $DEPLOY_METHON in
    272 
    273         deploy)
    274 
    275              shell_lock;
    276 
    277              code_get;
    278 
    279              code_build;
    280 
    281              code_config;
    282 
    283              code_tar;
    284 
    285              code_scp;
    286 
    287              pre_deploy;
    288 
    289              pre_test;
    290 
    291              group1_deploy;
    292 
    293              group1_test;
    294 
    295              shell_unlock;
    296 
    297              ;;
    298 
    299          rollback)
    300 
    301              shell_lock;
    302 
    303              rollback $ROLLBACK_VER;
    304 
    305              shell_unlock;
    306 
    307              ;;
    308 
    309          *)
    310 
    311              usage;
    312 
    313          esac 
    314 
    315 }
    316 
    317 main $1 $2
    View Code

    测试方式

    [www@linux-node1 ~]$ curl --head http://192.168.56.11/index.html

    HTTP/1.1 200 OK

    Date: Mon, 01 Aug 2016 09:42:23 GMT

    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5

    Last-Modified: Mon, 01 Aug 2016 09:39:52 GMT

    ETag: "17-538ff61ca0a00"

    Accept-Ranges: bytes

    Content-Length: 23

    Content-Type: text/html; charset=UTF-8

     

    [www@linux-node1 ~]$ curl -s --head http://192.168.56.11/index.html|grep "200 OK"

    HTTP/1.1 200 OK

    上面脚本远程执行命令或者拷贝 是使用ssh/scp完成的。当服务器稍多的时候,效率并不高。

    我在生产环境中是使用 ansible 替代的,个人感觉对于这个脚本来说,就是个并行、串行的区别。

    进一步的发展,还可以开发一些WEB界面去结合这个脚本,做到WEB化自动部署,当然也可以使用开源的jenkis。

    3、回滚

    1.列出回滚版本

    2.目标服务器移除集群

    3.执行回滚

    4.重启和测试

    5.加入集群

    ===========

    如果是遇到重大bug

    1.列出回滚版本

    2.执行回滚(重启)

    ==========

    非常紧急

    1.直接回滚到上个版本(重启)

    自动化部署的核心是创建软链接,同样在回滚的时候也能实现秒级回滚。

    但是在生产环境中,使用软连接可能会造成WEB打开页面空白,这点需要注意。

     





  • 相关阅读:
    Codeforces Round #555 (Div. 3) A B C1(很水的题目)
    蓝桥杯国赛之阶乘位数
    POJ-1258 Agri-Net(最小生成树)
    昂贵的聘礼(枚举区间+最短路)
    地斗主(矩阵快速幂)
    救救兔子(二分)
    shell编程之sed编辑器&gawk程序
    typedef struct与struct的区别
    iOS内存管理编程指南
    Object c 基础知识
  • 原文地址:https://www.cnblogs.com/yangliheng/p/5783852.html
Copyright © 2011-2022 走看看