版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/netdxy/article/details/79431415
一直认为不懂部署的开发工程师不是好的开发工程师,以下以一些实例讲解自己在项目中的 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"
有疑问加站长微信联系(非本文作者)