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

相关推荐
2301_8090511421 小时前
Linux 网络编程 学习笔记
linux·网络·学习
坤昱1 天前
cfs调度类深入解刨——最新内核细节分析2
linux·服务器·cfs·cfs调度·eevdf调度·eevdf·kernel 7.1
艾莉丝努力练剑1 天前
【Linux:文件】Ext系列文件系统进阶
linux·运维·服务器·c++·文件系统·文件io·ext
海市公约1 天前
Linux核心基础命令与权限管理实战指南
linux·运维·服务器·vim·权限管理·系统监控·命令行
eggcode1 天前
【Qt学习】Linux(ARM架构)在线安装Qt6.x
linux·qt·学习·arm
wkd_0071 天前
Ubuntu 22.04 Samba 连接故障排查记:从“用户名或密码错误”到 NTLM 版本不兼容
linux·运维·ubuntu
mixboot1 天前
Linux 进程工作目录查看利器:pwdx 命令详解
linux·运维·服务器
鹏北海-RemHusband1 天前
Go 语言进阶笔记 — 面向 JS/TS 前端开发者
笔记·golang
旺仔来了1 天前
不联网的Linux下部署python环境
linux·开发语言·python
Irene19911 天前
WSL 切换磁盘后验证完整性(MobaXterm、Powershell、WSL 的区别)
linux·wsl·mobaxterm