You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Shell脚本故障排查:日志检测与ABC.jar进程重启逻辑修复

问题分析与修复方案

嘿,我帮你拆解下脚本里的问题,然后给你修复后的版本和更靠谱的优化方案:

先说说你脚本里的几个关键错误

  1. Shebang写错了:开头的#!/bin是无效的,得改成#!/bin/bash指定bash解释器,不然系统不知道用什么来跑脚本
  2. 变量赋值不能有空格:比如PERVIOUS_TIME = cat ...这种写法,Shell会把PERVIOUS_TIME当成命令,=当成参数,这就是你第7、9行报错的根源——变量赋值时=前后必须紧挨着,不能有空格
  3. 时间获取逻辑完全错了:你想用cat test.log | date "%D %T"拿日志时间,这根本不是date的用法啊!date要么输出当前时间,要么解析你给的时间字符串,不是读文件内容。你实际要的是日志文件的最后修改时间,得用stat命令来获取
  4. 时间比较用错了运算符-eq是用来比数字的,不能比时间字符串,这会导致你的if判断完全失效,不管日志有没有更新都走同一个分支
  5. PID处理不严谨:原脚本拿PID的方式可能返回空值,直接跑kill -9会报错,得先判断有没有PID再执行kill

修复后的可用脚本

#!/bin/bash
NOTIFYJARFILE='ABC.jar'
LOG_FILE='/test/script/test.log'
WORK_DIR='/test/script'

# 切换目录失败直接退出,避免后续命令在错误路径执行
cd "$WORK_DIR" || exit 1
echo "Inside the directory: $WORK_DIR"
ls -ltrh | tail -1
echo "Files are listed"

# 获取日志文件的最后修改时间(格式和当前时间一致)
PREVIOUS_TIME=$(stat -c "%y" "$LOG_FILE" | cut -d' ' -f1,2)
# 获取当前时间
CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S")

echo "PREVIOUS_TIME: $PREVIOUS_TIME"
echo "CURRENT_TIME: $CURRENT_TIME"

# 更实用的判断:检查日志是否在最近1分钟内有更新(比精确时间戳匹配更灵活)
LOG_MODIFIED_SECONDS=$(echo "$(date +%s) - $(stat -c "%Y" "$LOG_FILE")" | bc)
LOG_MODIFIED_MINUTES=$((LOG_MODIFIED_SECONDS / 60))

if [ "$LOG_MODIFIED_MINUTES" -le 1 ]; then
    echo "Logs are generating for the current timestamp | $(date)"
else
    echo "Logs are NOT generating for the current timestamp | $(date)"
    # 精准查找ABC.jar的进程PID
    PID=$(pgrep -f "$NOTIFYJARFILE")
    if [ -n "$PID" ]; then
        echo "Killing existing ABC.jar process (PID: $PID)"
        kill -9 "$PID"
        sleep 2  # 给进程留点终止的缓冲时间
    else
        echo "No running ABC.jar process found"
    fi
    # 用nohup启动,确保脚本退出后进程能继续后台运行
    echo "Starting the ABC jar | $(date)"
    nohup java -jar "$WORK_DIR/$NOTIFYJARFILE" > /dev/null 2>&1 &
fi

更优的实现建议

上面的脚本已经能正常工作,但我再给你几个优化点,让它更可靠:

1. 用时间戳代替字符串比较

直接拿Unix时间戳(秒数)来计算差值,比字符串匹配准确多了,不会因为时间格式不一致出问题。比如用stat -c "%Y"获取日志修改的时间戳,date +%s获取当前时间戳,算差值就能知道多久没更新了。

2. 进程管理更严谨

  • pgrep -f精准匹配进程,避免误杀其他名字里带ABC.jar的进程
  • 杀进程前先检查PID是否存在,不然kill会报错
  • nohup启动Jar进程,比单纯加&更靠谱,能避免终端关闭时进程跟着挂掉

3. 增加错误处理和日志

  • 切换目录时加|| exit 1,防止后续命令在错误路径执行
  • 可以把脚本的执行日志写入一个单独的文件,比如echo "[$(date)] 脚本执行日志" >> /var/log/abc_jar_monitor.log,方便以后排查问题

4. 做成可配置的

把检查间隔、日志路径、Jar路径这些参数放在脚本开头,以后改起来方便:

# 可配置参数
CHECK_INTERVAL=1  # 检查日志是否在N分钟内更新
LOG_FILE='/test/script/test.log'
JAR_PATH='/test/script/ABC.jar'
WORK_DIR='/test/script'

内容的提问来源于stack exchange,提问作者Naveen

火山引擎 最新活动