一直认为不懂部署的开发工程师不是好的开发工程师,以下以一些实例讲解自己在项目中的 Golang 后端部署的情况。
一般部署脚本应该具有构建、启动、停止、回滚已经查看记录日志等功能,以下分别将这些功能以单个脚本的形式给出,当然也可以写成Makefile 的形式。
单个部署脚本的形式,在一个目录下建立如下文件:
- bin # 目录,用于存放每次 build 之后存放的二进制文件
- app.log # 用来记录的日志文件
- log.sh # 实时查看日志
- build.sh # 构建
- run.sh # 启动某一次编译版本
- start.sh # 启动最新版本,并且备份之前前一次运行的版本
- shutdown.sh # 停止
- rollback.sh # 回滚到上一版本
本例中的 GOPATH=”/go”
log.sh 具体内容:
tail -f -n 200 app.log # 实时查看最后 200 条日志的情况
build.sh 具体内容:
- #!/bin/bash
- # 项目地址,/go 在 GOPATH 里面
- baseProjectDir="/go/src/monitor"
- # targetDir 编译后的二进制文件目录
- targetDir="bin"
- # branch 编译的分支
- branch="master"
- pwd=`pwd`
- # targetFile 编译后的输出文件名称
- targetFile=`basename $pwd`
- # buildPkg 编译的包名,main.go 所在的包
- buildPkg="monitor"
- # buildResult 编译结果
- buildResult=""
- if [ -n "$1" ]; then
- branch="$1"
- echo "Switch branch to ${branch}"
- else
- echo "Building Branch: ${branch}"
- fi
- gitPull() {
- pushd .
- cd "$baseProjectDir"
- git checkout "$branch"
- git pull
- popd
- }
- goBuild() {
- buildResult=`go build -o "${targetDir}/${targetFile}" "$buildPkg" 2>&1`
- if [ -z "$buildResult" ]; then
- buildResult="success"
- fi
- }
- gitPull
- goBuild
- if [ "$buildResult" = "success" ]; then
- cp ${targetDir}/${targetFile} ${targetFile}-new
- chmod +x ${targetFile}-new
- else
- echo "build error $buildResult"
- exit
- fi
- echo "All Complete"
run.sh 具体内容:
- #!/bin/bash
- # 以后台方式启动程序,并且将日志记录到 app.log
- nohup ./$1 >> app.log &
start.sh 具体内容:
- #!/bin/bash
- pwd=`pwd`
- target=`basename $pwd`
- # kill
- pid=`ps -C ${target} -o pid=`
- if [ -n "$pid" ]; then
- echo "Stopping old version, PID: ${pid}"
- if [ "$1" = "-f" ]; then
- # force shutdown
- echo "Force shutdown..."
- kill -9 $(ps -C ${target} -o pid=)
- else
- kill -s 2 $(ps -C ${target} -o pid=)
- fi
- # wait for program to stop
- pid=`ps -C ${target} -o pid=`
- while [ -n "$pid" ]; do
- sleep 1
- done
- fi
- # upgrade
- if [ -f "${target}-new" ]; then
- echo "Upgrading..."
- if [ -f "${target}-backup" ]; then
- backupdt=`date +%Y%m%d-%H`
- mv "${target}-backup" "${target}-backup-${backupdt}"
- fi
- mv ${target} ${target}-backup
- mv ${target}-new ${target}
- echo "Upgrade Complete"
- fi
- # run
- echo "Starting..."
- ./run.sh ${target}
- echo "Done"
shutdown.sh 具体内容:
- #!/bin/bash
- pwd=`pwd`
- target=`basename $pwd`
- # kill
- pid=`ps -C ${target} -o pid=`
- if [ -n "$pid" ]; then
- echo "Stopping old version, PID: ${pid}"
- if [ "$1" = "-f" ]; then
- # force shutdown
- echo "Force shutdown..."
- kill -9 $(ps -C ${target} -o pid=)
- else
- kill -s 2 $(ps -C ${target} -o pid=)
- fi
- # wait for program to stop
- pid=`ps -C ${target} -o pid=`
- while [ -n "$pid" ]; do
- sleep 1
- done
- fi
- echo "Done"
需要注意的是 kill -s 2 发送的是 Interrupt 中断信号,在项目中要有监听该信号的处理程序,eg:
- package main
- import (
- "log"
- "os"
- "os/signal"
- "github.com/robfig/cron"
- )
- func main() {
- i := 0
- c := cron.New()
- spec := "*/3 * * * * ?"
- c.AddFunc(spec, func() {
- i++
- log.Println("cron running:", i)
- })
- c.Start()
- go signalListen()
- select {}
- }
- func signalListen() {
- c := make(chan os.Signal)
- // 监听 os.Interrupt 并且退出程序
- signal.Notify(c, os.Interrupt, os.Kill)
- for {
- <-c
- os.Exit(0)
- }
- }
rollback.sh 具体内容:
- #!/bin/bash
- pwd=`pwd`
- target=`basename $pwd`
- # Kill running program
- pid=`ps -C ${target} -o pid=`
- if [ -n "$pid" ]; then
- echo "Stopping old version, PID: ${pid}"
- if [ "$1" = "-f" ]; then
- # force shutdown
- echo "Force shutdown..."
- kill $(ps -C ${target} -o pid=)
- else
- kill -s 2 $(ps -C ${target} -o pid=)
- fi
- # wait for program to stop
- pid=`ps -C ${target} -o pid=`
- while [ -n "$pid" ]; do
- sleep 1
- done
- fi
- # Rollback
- if [ -f "${target}-backup" ]; then
- echo "Rolling back..."
- if [ -f "${target}" ]; then
- rm "${target}"
- fi
- mv ${target}-backup ${target}
- echo "Rollback Complete"
- fi
- # run
- echo "Starting..."
- ./run.sh ${target}
- echo "Done"
---------------------
作者:极客Geek
来源:CSDN
原文:https://blog.csdn.net/netdxy/article/details/79431415
版权声明:本文为博主原创文章,转载请附上博文链接!