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

相关推荐
AOwhisky29 分钟前
Linux 文本处理三剑客:awk、grep、sed 完全指南
linux·运维·服务器·网络·云计算·运维开发
Gavin_9151 小时前
从零开始部署经典开源项目管理系统最新版redmine6-Linux Debian12
linux·ruby on rails·开源·debian·ruby·redmine
xuanerya1 小时前
使用 SSH 方式克隆 GitHub 仓库没有权限解决办法
运维·ssh·github
花小璇学linux1 小时前
imx6ull-驱动开发篇31——Linux异步通知
linux·驱动开发·嵌入式软件
shelutai1 小时前
ubuntu 编译ffmpeg6.1 增加drawtext,libx264,libx265等
linux·ubuntu·ffmpeg
runfarther2 小时前
搭建LLaMA-Factory环境
linux·运维·服务器·python·自然语言处理·ai编程·llama-factory
hello_ world.2 小时前
RHCA10NUMA
linux
神秘人X7073 小时前
Linux高效备份:rsync + inotify实时同步
linux·服务器·rsync
轻松Ai享生活3 小时前
一步步学习Linux initrd/initramfs
linux
轻松Ai享生活3 小时前
一步步深入学习Linux Process Scheduling
linux