golang linux快速启动 一键重启脚本

需求背景

  • 我使用本地编译,复制到 linux 上运行的方式部署 go 项目
  • 单体部署,如果是集群部署可以依赖 nginx 做无感切换

痛点

  1. 正在运行的 go 项目文件不能被覆盖,我需要先使用脚本停止项目,然后覆盖,然后再用脚本运行起来。 这会造成显著的服务中断。
  2. 单体运行多个 go项目时,需要明确区分项目名称,不然终止脚本可能会误杀

原脚本

启动

bash 复制代码
nohup /全路径/项目名称 >> nohup.out &
tail -f /全路径/nohup.out

终止

bash 复制代码
kill -15 `ps -ef | grep 项目名称 | grep -v grep | awk '{print $2}'`

新思路

  • 每次还是编译成相同名称的文件。
  • 脚本将新的可执行文件复制为一个新的名称,此名称确保和原来名称不重复。
  • 如果需要更新项目包,脚本先复制新项目,然后终止原项目,然后运行新项目,可以最大程度缩小服务中断时间。
  • 需要有个文件存储上一次运行的项目被改成了什么名字,以方便需要终止他的时候能找到他。

新脚本

代码如下

bash 复制代码
#!/bin/bash
#项目路径
PROJECT_PATH="/opt/my_project/"
# 配置文件名称
CONFIG_FILE="shell_info.ini"
# 目标文件路径
TARGET_FILE="my_golang_app"
# 日志文件路径
LOG_FILE="nohup.log"

# 生成随机字符串
generate_random_string() {
    cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1
}

# 根据日期和随机数生成新文件名
generate_new_filename() {
    local date_str=$(date +"%Y%m%d")
    local random_str=$(generate_random_string)
    echo "${date_str}_${random_str}"
}

# 启动服务
start_service() {
    local new_filename=$(generate_new_filename)
    cp $PROJECT_PATH$TARGET_FILE "$PROJECT_PATH$new_filename"
    echo "Starting service with filename: $PROJECT_PATH$new_filename"
    nohup "$PROJECT_PATH$new_filename" >> $PROJECT_PATH$LOG_FILE 2>&1 &
    echo "current=$PROJECT_PATH$new_filename" > $PROJECT_PATH$CONFIG_FILE
    tail -f $PROJECT_PATH$LOG_FILE
}

# 重新加载服务
reload_service() {
    local current=$(grep '^current=' $PROJECT_PATH$CONFIG_FILE | cut -d'=' -f2)
    if [ -z "$current" ]; then
        echo "No current service to reload."
        return
    fi
    local new_filename=$(generate_new_filename)
    cp $PROJECT_PATH$TARGET_FILE "$PROJECT_PATH$new_filename"
    echo "Reloading service from $current to $PROJECT_PATH$new_filename"
    local pid=$(ps -ef | grep "$current" | grep -v grep | awk '{print $2}')
    if [ -n "$pid" ]; then
        kill -9 $pid
        echo "Service $current stopped."
    fi
    nohup "$PROJECT_PATH$new_filename" >> $PROJECT_PATH$LOG_FILE 2>&1 &
    rm "$current"
    echo "current=$PROJECT_PATH$new_filename" > $PROJECT_PATH$CONFIG_FILE
    tail -f $PROJECT_PATH$LOG_FILE
}

# 停止服务
stop_service() {
    local current=$(grep '^current=' $PROJECT_PATH$CONFIG_FILE | cut -d'=' -f2)
    if [ -z "$current" ]; then
        echo "No current service to stop."
        return
    fi
    local pid=$(ps -ef | grep "$current" | grep -v grep | awk '{print $2}')
    if [ -n "$pid" ]; then
        kill -9 $pid
        echo "Service $current stopped."
    fi
}

case $1 in
    start)
        start_service
        ;;
    reload)
        reload_service
        ;;
    stop)
        stop_service
        ;;
    *)
        echo "Usage: $0 {start|reload|stop}"
        exit 1
        ;;
esac

exit 0

使用方法:

bash 复制代码
#运行项目
sh runner.sh start
#使用新包覆盖原运行项目
sh runner.sh reload
#终止运行
sh runner.sh stop

使用说明:

如果你第一次查阅相关内容,就看到了我的文章,那么你在复制 linux 可执行文件后,可能需要修改其权限。建议将脚本和 linux 可执行文件放在同一文件夹下。

bash 复制代码
#赋予当前路径下所有文件执行权限
chmod 777 ./*

修改脚本头部配置,其中项目路径填你存放脚本和 linux 可执行文件的路径,配置文件不用管,不要手欠误删了就没事。删了也没事,只是你得自己终止进程了。

目标文件路径填 linux 可执行文件的名称即可。.

脚本会复制原可执行文件,生成的新文件名称是:原名称+时间日期+乱码

在使用 reload 命令时,会自动清除上次复制出来的文件。

相关推荐
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
开发者联盟league3 天前
安装pnpm
ssh
载数而行5203 天前
Linux 11 动态监控指令top
linux