Shell脚本故障排查:日志检测与ABC.jar进程重启逻辑修复
问题分析与修复方案
嘿,我帮你拆解下脚本里的问题,然后给你修复后的版本和更靠谱的优化方案:
先说说你脚本里的几个关键错误
- Shebang写错了:开头的
#!/bin是无效的,得改成#!/bin/bash指定bash解释器,不然系统不知道用什么来跑脚本 - 变量赋值不能有空格:比如
PERVIOUS_TIME = cat ...这种写法,Shell会把PERVIOUS_TIME当成命令,=当成参数,这就是你第7、9行报错的根源——变量赋值时=前后必须紧挨着,不能有空格 - 时间获取逻辑完全错了:你想用
cat test.log | date "%D %T"拿日志时间,这根本不是date的用法啊!date要么输出当前时间,要么解析你给的时间字符串,不是读文件内容。你实际要的是日志文件的最后修改时间,得用stat命令来获取 - 时间比较用错了运算符:
-eq是用来比数字的,不能比时间字符串,这会导致你的if判断完全失效,不管日志有没有更新都走同一个分支 - 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




