高可用自动化重启脚本需具备容错、状态感知、防误操作和可追溯能力:通过业务健康检查判断宕机,用flock加锁防并发,kill -0预检进程,设冷却时间与最大重试次数,重启前校验磁盘、端口、配置,并详尽记录日志。

在 Linux 环境中,用 Shell 编写一个“高可用”的自动化重启脚本,核心不是让脚本本身永不失败,而是让它具备容错、状态感知、防误操作和可追溯能力。真正的高可用体现在:服务挂了能拉起、重复触发不雪崩、异常时有记录、重启前做必要检查。
判断服务是否真正宕机,而非仅进程存在
只靠 ps | grep 容易误判——进程还在但已无响应(如卡死、假死)。应结合业务健康检查:
- 对 Web 服务:用
curl -sfL --max-time 5 http://127.0.0.1:8080/health | grep -q "status.*up" - 对数据库连接类服务:尝试建立轻量连接(如
mysql -h127.0.0.1 -uuser -ppass -e"SELECT 1" &>/dev/null) - 避免无脑杀进程:先
kill -0 $PID检查进程是否可响应信号,再决定是否kill -9
防止重启风暴:加锁 + 冷却时间 + 最大重试限制
网络抖动或瞬时超时可能触发多次检测,若脚本并发执行会反复重启服务,加剧故障。需强制串行化:
- 使用
flock文件锁:在脚本开头加exec 200>/var/lock/restart_script.lock && flock -n 200 || exit 1 - 每次重启后 sleep 至少 30 秒(避免秒级循环),并记录上一次成功重启时间戳
- 连续失败超过 3 次则停止自动重启,写入告警日志并退出(例如:
echo "$(date): failed 3 times, aborting" >> /var/log/restart_alert.log)
重启前检查依赖与资源,避免无效操作
盲目重启常因前置条件缺失而失败(如磁盘满、端口被占、配置文件损坏)。脚本应主动验证:
- 磁盘空间:
df /opt/myapp | awk 'NR==2 {print $5}' | sed 's/%//' | awk '$1 > 90 {exit 1}' - 端口空闲:
lsof -ti:8080 >/dev/null && exit 1 || true(若端口被占,说明旧进程未退出干净) - 配置文件语法:
if ! myapp --config-test /etc/myapp/conf.yaml; then echo "Config invalid"; exit 1; fi
记录完整上下文,便于事后归因
日志不能只写“重启了”,要包含为什么重启、依据什么判断、环境状态快照:
- 每次运行记录到独立日志:
logger -t "auto-restart" "Health check failed: $(curl -s http://localhost/health 2>/dev/null || echo 'timeout')" - 保存重启前的内存/CPU/连接数:
echo "$(date), $(free -m | awk '/Mem:/ {print $3}'), $(ss -s | head -1)" >> /var/log/restart_env.log - 将本次 PID、启动参数、配置哈希(
sha256sum /etc/myapp/conf.yaml)一并写入日志
不复杂但容易忽略:高可用脚本的关键不在“重启多快”,而在“何时不该重启”和“重启后能否稳住”。把检查做实、把并发控住、把日志留全,比一行 systemctl restart xxx 可靠得多。











