Bash编写服务检测脚本时运行时长判断失效问题求助
问题根因
你现有脚本跑不通是几个基础Bash语法和逻辑设计错误叠加导致的:
systemctl is-active --quiet本身通过退出码返回结果:退出码0代表服务处于active状态,非0代表异常,你后面追加的= active会被当成命令参数传入,直接导致命令执行逻辑错误。- Bash原生不支持直接写
$SERVICE_UP_TIME > 60s做数值比较:在(( ))算术判断结构外,>是文件重定向符号,你这么写不会做数值判断,反而会在当前目录创建一个名为60s的空文件;同时算术比较要求两边都是纯数字,不能带s这类单位后缀。 wait 60s用法完全错误:wait是Bash内置命令,作用是等待指定后台进程执行结束,没有延时功能,做时间等待要用sleep命令。- 逻辑设计有缺陷:你只在脚本开头取了一次服务启动时间,后续没有重新校验,服务如果在等待过程中重启、启动时间重置,脚本完全感知不到,满足不了“检测服务重启报错误”的要求。
- 启动时间解析方式鲁棒性差:直接解析
systemctl status的文本输出很容易受系统语言、systemd版本差异影响,取到的时间格式不对就会导致计算运行时长失败。
优化后可复用脚本
这个版本适配任意systemd管理的服务,修复了上述所有问题,完全匹配你要的检测逻辑:
#!/bin/bash # 可替换为任意需要检测的systemd服务名 SERVICE="logstash" # 要求的最小运行时长阈值,单位秒 UPTIME_THRESHOLD=60 # 统一C语言环境,避免时间解析受系统语言影响 export LANG=C LC_ALL=C # 记录首次检测到的服务启动时间,用于判断服务是否重启 last_start_time=0 while true; do # 第一步:检测服务当前状态 svc_state=$(systemctl is-active "$SERVICE") if [ "$svc_state" != "active" ]; then echo "ERROR: 服务$SERVICE当前状态为$svc_state,未正常运行" exit 1 fi # 第二步:通过systemctl原生接口取服务精确启动时间,不解析易变的status文本 current_start_raw=$(systemctl show -p ActiveEnterTimestamp --value "$SERVICE") current_start_ts=$(date -d "$current_start_raw" +%s) current_ts=$(date +%s) current_uptime=$((current_ts - current_start_ts)) # 第三步:检测服务是否发生重启(启动时间比上次记录的更晚) if [ $last_start_time -ne 0 ] && [ $current_start_ts -gt $last_start_time ]; then echo "ERROR: 服务$SERVICE发生重启,运行时长已重置" exit 1 fi last_start_time=$current_start_ts # 第四步:判断运行时长是否达标 if [ $current_uptime -ge $UPTIME_THRESHOLD ]; then echo "$SERVICE 运行正常,已稳定运行超过$UPTIME_THRESHOLD秒,开始执行后续检测项" break fi # 未达阈值则动态计算等待时间,避免无效等待 wait_sec=$((UPTIME_THRESHOLD - current_uptime)) echo "$SERVICE 当前已运行${current_uptime}秒,还差${wait_sec}秒达到阈值,等待中..." sleep $wait_sec done # 后续其他检测项写在这里
适配说明
- 只需要修改开头
SERVICE变量的值,就可以复用到任意systemd托管的服务检测场景,不需要调整其他逻辑 - 所有系统状态取值都通过
systemctl show拿结构化属性,不解析自由格式的systemctl status输出,跨版本、跨语言环境兼容性拉满 - 每次循环都会重新拉取服务状态和启动时间,一旦出现服务失败、意外重启的情况会立刻报错退出,不会漏检
- 等待时长是动态计算的,不会固定等待60秒,服务运行时长刚到阈值就会立刻进入后续检测流程,没有多余耗时
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

