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 命令时,会自动清除上次复制出来的文件。

相关推荐
0xDevNull7 小时前
Linux切换JDK版本详细教程
linux
进击的丸子7 小时前
虹软人脸服务器版SDK(Linux/ARM Pro)多线程调用及性能优化
linux·数据库·后端
Johny_Zhao2 天前
OpenClaw安装部署教程
linux·人工智能·ai·云计算·系统运维·openclaw
chlk1233 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑3 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件3 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号4 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash4 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI4 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行5 天前
Linux和window共享文件夹
linux