Shell脚本如何实现热加载

wen 实用脚本 1

本文目录导读:

Shell脚本如何实现热加载

  1. 信号机制(最常用)
  2. 文件监控方式
  3. 使用inotify(Linux专用)
  4. 动态函数重载
  5. 完整示例:配置热加载服务
  6. 管理脚本
  7. 使用示例
  8. 关键点

Shell脚本实现热加载(即在不重启进程的情况下重新加载配置或代码)主要有以下几种方法:

信号机制(最常用)

#!/bin/bash
# 配置文件
CONFIG_FILE="/etc/myapp/config.conf"
PID_FILE="/var/run/myapp.pid"
# 信号处理函数
reload_config() {
    echo "重新加载配置: $(date)"
    source "$CONFIG_FILE"
    # 这里执行配置生效的逻辑
}
# 注册信号处理器
trap reload_config SIGHUP
# 主循环
while true; do
    # 业务逻辑
    echo "运行中..."
    sleep 5
done

使用方法:

# 启动
./script.sh &
# 热加载
kill -HUP <PID>
# 或者
pkill -HUP script.sh

文件监控方式

#!/bin/bash
# 监控配置文件变化
CONFIG_FILE="/etc/myapp/config.conf"
LAST_MODIFIED=$(stat -c %Y "$CONFIG_FILE")
reload_config() {
    echo "检测到配置文件变化,重新加载..."
    source "$CONFIG_FILE"
    # 执行配置生效逻辑
}
while true; do
    CURRENT_MODIFIED=$(stat -c %Y "$CONFIG_FILE")
    if [ "$CURRENT_MODIFIED" != "$LAST_MODIFIED" ]; then
        LAST_MODIFIED=$CURRENT_MODIFIED
        reload_config
    fi
    sleep 2
done

使用inotify(Linux专用)

#!/bin/bash
# 需要安装 inotify-tools
# apt-get install inotify-tools
CONFIG_FILE="/etc/myapp/config.conf"
reload_config() {
    echo "配置文件变更,重新加载..."
    source "$CONFIG_FILE"
}
# 监控文件变化
inotifywait -m -e modify "$CONFIG_FILE" |
    while read -r directory events filename; do
        reload_config
    done

动态函数重载

#!/bin/bash
# 函数库文件
FUNCTIONS_FILE="./functions.sh"
# 热加载函数
hot_reload_function() {
    local func_name=$1
    local func_file=$2
    # 重新加载特定函数
    eval "$(sed -n "/^${func_name}()/,/^}/p" "$func_file")"
}
# 主程序逻辑
while true; do
    # 业务逻辑
    if [ -f "$FUNCTIONS_FILE" ]; then
        hot_reload_function "my_function" "$FUNCTIONS_FILE"
    fi
    sleep 10
done

完整示例:配置热加载服务

#!/bin/bash
# 配置热加载服务
CONFIG_FILE="/tmp/app.conf"
PID_FILE="/tmp/app.pid"
LOG_FILE="/tmp/app.log"
# 默认配置
PORT=8080
MODE="production"
TIMEOUT=30
# 初始化配置
init_config() {
    if [ -f "$CONFIG_FILE" ]; then
        source "$CONFIG_FILE"
    fi
    log "配置初始化完成: PORT=$PORT, MODE=$MODE"
}
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# 重新加载配置
reload_config() {
    log "收到重载信号,重新加载配置..."
    OLD_PORT=$PORT
    OLD_MODE=$MODE
    OLD_TIMEOUT=$TIMEOUT
    init_config
    if [ "$PORT" != "$OLD_PORT" ] || [ "$MODE" != "$OLD_MODE" ]; then
        log "配置变更: PORT=$OLD_PORT->$PORT, MODE=$OLD_MODE->$MODE"
    fi
    apply_config
}
# 应用配置
apply_config() {
    # 模拟配置生效
    log "应用新配置: PORT=$PORT, MODE=$MODE, TIMEOUT=$TIMEOUT"
}
# 服务主循环
service_loop() {
    log "服务启动,PID=$$"
    echo $$ > "$PID_FILE"
    while true; do
        # 模拟服务运行
        sleep 5
        log "服务运行中: PORT=$PORT, MODE=$MODE"
    done
}
# 信号处理
trap reload_config SIGHUP
trap 'log "服务停止"; rm -f "$PID_FILE"; exit 0' SIGTERM SIGINT
# 启动服务
init_config
apply_config
service_loop

管理脚本

#!/bin/bash
SERVICE_SCRIPT="./hot_reload_service.sh"
PID_FILE="/tmp/app.pid"
start() {
    if [ -f "$PID_FILE" ]; then
        echo "服务已在运行"
        return 1
    fi
    nohup bash "$SERVICE_SCRIPT" > /dev/null 2>&1 &
    echo "服务已启动"
}
stop() {
    if [ -f "$PID_FILE" ]; then
        kill -TERM $(cat "$PID_FILE") 2>/dev/null
        rm -f "$PID_FILE"
        echo "服务已停止"
    else
        echo "服务未运行"
    fi
}
reload() {
    if [ -f "$PID_FILE" ]; then
        kill -HUP $(cat "$PID_FILE") 2>/dev/null
        echo "已发送重载信号"
    else
        echo "服务未运行"
    fi
}
status() {
    if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
        echo "服务运行中,PID: $(cat $PID_FILE)"
    else
        echo "服务未运行"
    fi
}
case "$1" in
    start)   start ;;
    stop)    stop ;;
    reload)  reload ;;
    status)  status ;;
    *)
        echo "用法: $0 {start|stop|reload|status}"
        exit 1
        ;;
esac

使用示例

# 启动服务
./manage.sh start
# 修改配置文件
echo "PORT=9090" > /tmp/app.conf
# 热加载
./manage.sh reload
# 查看状态
./manage.sh status
# 停止服务
./manage.sh stop

关键点

  1. 信号处理:使用 trap 捕获 SIGUP 信号
  2. 日志记录:记录重载事件和配置变更
  3. 优雅处理:确保重载过程中服务不中断
  4. 配置验证:在应用配置前进行验证
  5. 回滚机制:配置错误时可以回滚到上一版本

这种热加载方式适用于配置变更、函数更新等场景,无需重启进程即可生效。

抱歉,评论功能暂时关闭!