zoukankan      html  css  js  c++  java
  • 基于php+shell的发布系统

    一.发布系统要解决的问题

      一个比较完善的发布系统首先肯定是要能发布文件,其次当发布出现问题时要能支持撤销,避免长时间无法解决问题影响产品的正常运营。
    对于发布脚本语言如PHP,shell加入语法检查,有语法错误阻止本次发布。

    二.原理

      我们正在使用的发布系统基于PHP+shell开发,发布的时候填好文件列表,从当前机器A发布到目标机器B,发布之前A机器通过ssh协议认证登陆到B机器执行shell命令备份待发布的文件列表
    然后使用rsync从A机器同步文件列表到B机器,发布完成后写入当前发布记录到数据库,当需要回滚的时候将对应的备份文件覆盖到B机器即可。

    三.要解决的问题

    1.使用rsync以及备份目标机器文件需要免密登陆

      A机器到B机器实现免密登陆,需要使用ssh-keygen生成当前用户的登陆秘钥,把当前用户的公钥追加到目标机器用户的 .ssh/authorized_keys文件中
    以下shell是把当前机器的公钥追加到目标机器的authorized_keys文件

    USER=www
    IP=192.168.1.100 #B机器ip
    PORT=22 #B机器SSH协议端口
    cat /home/${USER}/.ssh/id_rsa.pub | ssh ${USER}@${IP} 'cat>>/home/${USER}/.ssh/authorized_keys'
    

    后续无需输入密码即可在A机器免密登陆B机器

    2.发布到多台机器
      如果目标机器有多台,可以循环发布到目标机器。如果每次更新的文件过大,可以发布到一台中心节点服务器,然后使用sersync同步到其它机器。https://code.google.com/archive/p/sersync/downloads
    修改config.xml rsync节点<ssh start="true"/>,并使用免密登陆的用户启动sersync服务

    #!/bin/bash
    #-------------------------------------------------------------------------------------------------------
    #从当前机器发布文件到远程机器,如果是分布式机器,以一台机器为主节点通过sersync同步到其它节点
    #
    #
    #参数说明
    #    发布
    #$1:执行动作send
    #$2:远程目标机器ip
    #$3:远程目标机器端口
    #$4:当前机器发布根目录
    #$5:远程目标机器发布根目录
    #$6:远程目标机器备份根目录
    #$7:发布版本号
    #$8:文件列表 多个文件或者目录使用","隔开
    
    #
    #
    #    回滚
    #$1:执行动作roll
    #$2:远程目标机器ip
    #$3:远程目标机器端口
    #$4:当前机器发布根目录
    #$5:远程目标机器发布根目录
    #$6:远程目标机器备份根目录
    #$7:回滚版本号
    #----------------------------------------------------------------------------------------------------
    
    source /etc/profile
    umask 022
    
    readonly TARGET_IP=$2                        #远程目标机器ip
    readonly TARGET_PORT=$3                        #远程目标机器ip
    readonly USER=www                            #执行远程shell命令用户
    readonly SOURCE_ROOT=$4                        #当前机器发布根目录
    readonly TARGET_ROOT=$5                        #远程目标机器发布目录
    readonly BACKUP_ROOT=$6                        #远程目标机器备份路径
    
    readonly execssh="/usr/bin/ssh -p ${TARGET_PORT} -o StrictHostKeyChecking=no ${USER}@${TARGET_IP}" #在远程目标机器执行shell命令
    
    #发布
    function send(){
        IFS=","
        error=0
        aFile=($1)
        for file in ${aFile[@]}
        do
            if [ ! -e "${SOURCE_ROOT}/${file}" ];then
                fileList+={$file}
                error=1
            fi
        done
    
        if [ "${error}" != 0 ];then
            echo "file list is not exists in ${SOURCE_ROOT}"
            echo $fileList
            exit 1
        fi
    
        eval "${execssh} ${TARGET_ROOT}/cron/sendfile.sh backup ${1} ${2} ${TARGET_ROOT} ${BACKUP_ROOT}"
        
        if [ "$?" == 0 ];then
            cd ${SOURCE_ROOT}
            fileList=$(echo "${1}" | tr "," " ")
            #/usr/bin/rsync -avzR -e ssh ${fileList} ${USER}@${TARGET_IP}:${TARGET_ROOT}
            eval "/usr/bin/rsync -avzR '-e ssh -p ${TARGET_PORT}' ${fileList} ${USER}@${TARGET_IP}:${TARGET_ROOT}"
        else
            echo "back up faild!!!"
            exit 2
        fi
        exit 0
    }
    
    #回滚
    function roll(){
        $execssh "tar zxf ${BACKUP_ROOT}/${1}.bak.tar.gz -C ${TARGET_ROOT}"
        echo 'ok'
    }
    
    #备份
    function backup(){
        target_root=$3
        back_root=$4
        cd ${target_root}
        IFS=","
        aFile=($1)
        fileList=""
        for file in ${aFile[@]}
        do
            if [ -e "${target_root}/${file}" ];then
                fileList+="$file "
            fi
        done
        if [ -n "${fileList}" ];then
            if [ ! -d ${back_root} ];then
                mkdir -p ${back_root}
                if [ "$?" != 0 ];then
                    echo "mkdir backup dir ${back_root} fail"
                    exit 1
                fi
            fi
            tar czf ${back_root}/${2}.bak.tar.gz $1
            if [ "$?" == 0 ];then
                echo "backup file ${back_root}/${2}.bak.tar.gz!"
            fi 
        fi
    }
    
    function argsCheck(){
        if [ -z $2 ] || [ -z $3 ] || [ -z $4 ] || [ -z $5 ] || [ -z $6 ] || [ -z $7 ];then
            echo "useage ${0} send|roll TARGET_IP TARGET_PORT SOURCE_ROOT TARGET_ROOT BACKUP_ROOT VER"
            exit 1
        fi
        if [ ! -d $4 ];then
            echo "SOURCE_ROOT ${SOURCE_ROOT} is not exsists!"
            exit 2
        fi
    }
    
    case $1 in
        "send")
            argsCheck "$@"
            send $8 $7 #文件列表版本号
        ;;
        
        "backup")
            backup $2 $3 $4 $5
        ;;
        
        "roll")
            argsCheck "$@"
            roll $7 #版本号
        ;;
        
        *)
        echo "useage ${0} send|roll TARGET_IP TARGET_PORT SOURCE_ROOT TARGET_ROOT BACKUP_ROOT VER"
        ;;
    esac
    #!/bin/bash
    #-------------------------------------------------------------------------------------------------------
    #从当前机器发布文件到远程机器,如果是分布式机器,以一台机器为主节点通过sersync同步到其它节点
    #
    #
    #参数说明
    #    发布
    #$1:执行动作send
    #$2:远程目标机器ip
    #$3:远程目标机器端口
    #$4:当前机器发布根目录
    #$5:远程目标机器发布根目录
    #$6:远程目标机器备份根目录
    #$7:发布版本号
    #$8:文件列表 多个文件或者目录使用","隔开
    
    #
    #
    #    回滚
    #$1:执行动作roll
    #$2:远程目标机器ip
    #$3:远程目标机器端口
    #$4:当前机器发布根目录
    #$5:远程目标机器发布根目录
    #$6:远程目标机器备份根目录
    #$7:回滚版本号
    #----------------------------------------------------------------------------------------------------
    
    source /etc/profile
    umask 022
    
    readonly TARGET_IP=$2                        #远程目标机器ip
    readonly TARGET_PORT=$3                        #远程目标机器ip
    readonly USER=www                            #执行远程shell命令用户
    readonly SOURCE_ROOT=$4                        #当前机器发布根目录
    readonly TARGET_ROOT=$5                        #远程目标机器发布目录
    readonly BACKUP_ROOT=$6                        #远程目标机器备份路径
    
    readonly execssh="/usr/bin/ssh -p ${TARGET_PORT} -o StrictHostKeyChecking=no ${USER}@${TARGET_IP}" #在远程目标机器执行shell命令
    
    #发布
    function send(){
        IFS=","
        error=0
        aFile=($1)
        for file in ${aFile[@]}
        do
            if [ ! -e "${SOURCE_ROOT}/${file}" ];then
                fileList+={$file}
                error=1
            fi
        done
    
        if [ "${error}" != 0 ];then
            echo "file list is not exists in ${SOURCE_ROOT}"
            echo $fileList
            exit 1
        fi
    
        eval "${execssh} ${TARGET_ROOT}/cron/sendfile.sh backup ${1} ${2} ${TARGET_ROOT} ${BACKUP_ROOT}"
        
        if [ "$?" == 0 ];then
            cd ${SOURCE_ROOT}
            fileList=$(echo "${1}" | tr "," " ")
            #/usr/bin/rsync -avzR -e ssh ${fileList} ${USER}@${TARGET_IP}:${TARGET_ROOT}
            eval "/usr/bin/rsync -avzR '-e ssh -p ${TARGET_PORT}' ${fileList} ${USER}@${TARGET_IP}:${TARGET_ROOT}"
        else
            echo "back up faild!!!"
            exit 2
        fi
        exit 0
    }
    
    #回滚
    function roll(){
        $execssh "tar zxf ${BACKUP_ROOT}/${1}.bak.tar.gz -C ${TARGET_ROOT}"
        echo 'ok'
    }
    
    #备份
    function backup(){
        target_root=$3
        back_root=$4
        cd ${target_root}
        IFS=","
        aFile=($1)
        fileList=""
        for file in ${aFile[@]}
        do
            if [ -e "${target_root}/${file}" ];then
                fileList+="$file "
            fi
        done
        if [ -n "${fileList}" ];then
            if [ ! -d ${back_root} ];then
                mkdir -p ${back_root}
                if [ "$?" != 0 ];then
                    echo "mkdir backup dir ${back_root} fail"
                    exit 1
                fi
            fi
            tar czf ${back_root}/${2}.bak.tar.gz $1
            if [ "$?" == 0 ];then
                echo "backup file ${back_root}/${2}.bak.tar.gz!"
            fi 
        fi
    }
    
    function argsCheck(){
        if [ -z $2 ] || [ -z $3 ] || [ -z $4 ] || [ -z $5 ] || [ -z $6 ] || [ -z $7 ];then
            echo "useage ${0} send|roll TARGET_IP TARGET_PORT SOURCE_ROOT TARGET_ROOT BACKUP_ROOT VER"
            exit 1
        fi
        if [ ! -d $4 ];then
            echo "SOURCE_ROOT ${SOURCE_ROOT} is not exsists!"
            exit 2
        fi
    }
    
    case $1 in
        "send")
            argsCheck "$@"
            send $8 $7 #文件列表版本号
        ;;
        
        "backup")
            backup $2 $3 $4 $5
        ;;
        
        "roll")
            argsCheck "$@"
            roll $7 #版本号
        ;;
        
        *)
        echo "useage ${0} send|roll TARGET_IP TARGET_PORT SOURCE_ROOT TARGET_ROOT BACKUP_ROOT 

      

  • 相关阅读:
    ufw防火墙设置
    [从0到1搭建ABP微服务]
    .Net Core CI/CD环境搭建(正式版)
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
    [Abp vNext微服务实践]
  • 原文地址:https://www.cnblogs.com/gaoqin31/p/9383083.html
Copyright © 2011-2022 走看看