再看编译构建和部署脚本(一)

332 阅读3分钟

以前端项目为例,编译构建的目的主要是将代码变成一些静态资源,部署的目的是可以使用域名访问到这些静态资源。本次实验的前端项目同时使用node起了一个简单的服务端,目的是做请求转发。

编译构建阶段

  1. 先上脚本
#!/bin/bash
set -o errexit
NPM_RUN_COMMAND="npm run build:${ENV} --prefix"

function clean
{
    echo "Clean up..."
    # 部署用的全套代码以及node层的依赖
    rm -rf /output
    # 前端编译代码
    rm -rf dist
    # 代码检查结果
    rm -f eslint-output.xml
    echo "Clean up successfully!"
}

function output
{
    mkdir -p /output
    # 复制server代码(不包含node_modules)、bin至output
    cp server.js /output/pigeon.js
    cp api_route.js /output/api_route.js
    cp package.json /output
    # 复制bin至output
    cp -r bin /output
    # 复制静态资源
    cp -r dist/static/css /output/css
    cp -r dist/static/img /output/img
    cp -r dist/static/js /output/js
    cp -r dist/static/fonts /output/fonts

    # 复制静态html
    cp dist/index.html /output
    echo "Downloading server node_modules"
    npm i --production --prefix /output
    # 执行权限
    chmod +x /output/bin/control
}

function build
{

    echo "Downloading basic & client node_modules"
    # url里的xx是我司简称hhhh
    npm config set registry http://registry.m.xx.com
    npm i && npm i --prefix client

    #echo "code quality check"
    #npm run lint-report

    echo "client production build"
    $NPM_RUN_COMMAND
}

function main
{
    clean
    build $@
    output
}

main $@
  1. 简要解释脚本 从main()中可以看出这段简单的脚本由三部分构成,clean(),清除上一次编译构建产生的内容,build(),执行构建,output(),将build阶段产生的内容放置到指定位置。

(1).clean(),rm -rf disk移除项目路径下编译构建之后的内容,通常情况下在项目路径下执行npm build,静态资源都会放到/disk中,这个默认路径可以在webpack中设置。rm -rf /output,实验中把build之后的内容放到了根目录下的output文件夹中,所以每次build之前都要清除这个目录下的内容, echo为了看一下build过程,方便调错。

(2).build(),build过程对于前端项目来说主要就是npm build,如果你的前端项目有服务端,那么将服务端和客户端的依赖分开放置是个不错的方式,--prefix的作用就是将node依赖安装到指定目录。

(3).output(),output的作用就是将编译构建的内容放置到指定位置。执行权限那一步完全可以省略,我司预发环境部署的时候容器启动会自动去寻找/bin/control作为启动进程,所以要给control增加执行权限。

  1. 执行后结果

部署阶段

  1. 先上脚本
#!/bin/bash
cd "$(dirname $0)"/.. || exit 1
PROC_NAME='pigeon'

help(){
    echo "${0} <start|stop|restart|status>"
    exit 1
}

status(){
    ps -eo 'pid,command' | grep "$PROC_NAME" | grep -v grep > /dev/null 2>&1
    ret=$?
    if [ 0 -eq $ret ]; then
        echo "running"
        return 0
    else
        echo "not running"
        return 1
    fi
}

stop_server() {
    echo ${DATE} "stop " ${PROC_NAME} " server"
    SERVER_PIDS=`ps aux | grep "$PROC_NAME" | grep -v "grep"| awk '{print $2}'`
    for id in $SERVER_PIDS;do
       kill -TERM ${id}
       echo "kill process,pid:${id}"
    done

    for i in 1 2 3 4 5; do
        sleep 1
        status
        if [ $? -eq 1 ]; then
            ok "stop server"
            return 0
        fi
    done

    die "stop server"
}

start(){
  npm start
}

stop(){
    stop_server
}

restart(){
    stop
    start
}

case "${1}" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    status|health|checkhealth|st)
        status
        ;;
    *)
        help
        ;;
esac
  1. 简要解释脚本 部署脚本主要有start(),restart(),stop(),status()组成

(1). start()启动服务,我司容器启动时会默认调用start函数,对于前端项目来说,start()一般是封装的了npm的script,比如我的scripts

"scripts": {
   "dev": "vue-cli-service serve",
   "build:prod": "vue-cli-service build",
   "build:pre": "vue-cli-service build",
   "build:stage": "vue-cli-service build --mode staging",
   "preview": "node build/index.js --preview",
   "lint": "eslint --ext .js,.vue src",
   "test:unit": "jest --clearCache && vue-cli-service test:unit",
   "test:ci": "npm run lint && npm run test:unit",
   "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
   "start": "nohup node pigeon.js &"
 },

所以start()实际上执行的是nohup node pigeon.js,nohup可以使node像后台服务一样执行。

(2). stop(),停止服务,主要是通过ps aux | grep "$PROC_NAME"找到关于当前项目启动的全部pid,然后循环调用kill pid

(3). restart(),重新启动服务,先调用stop()停止服务,然后调用start()启动服务。

(4). status(),可以通过 bash /bin/control status查看服务状态。

(5). help(), 通过bash /bin/control help查看该脚本中支持的命令。

  1. 启动服务后简单的验证 对于带有服务端的前端项目,启动后我习惯执行两步简单的验证

(1).判断是否可以准发请求,执行curl -d "username=xxx&password=xxx" -H "Accept: application/json" -X POST "http://localhost:8088/dev-api/xx/xx/user/login" -v ,如果服务转发没问题,通常情况下可以获得服务端的返回值,比如{request-id: 'xxxxx'}等等。

(2).判断是否可以访问静态资源,执行curl http://localhost:8088/static/index.html 通常情况下会返回一个<html>阿巴阿巴...</html>

如果以上两步都得到了预期内的返回值,那么就可以去做申请域名,域名解析等等后续步骤了

附属说明

对于一个合格的部署脚本来说,直接启动的应该是守护进程,用于检测服务进程的状态并对于不同的状态自动执行不同的动作,下一篇简单写一下关于守护进程的事。文中如有问题,请多多指教,感恩。