You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何配置可永久运行的systemd服务,并在达到指定重试次数后上报错误

如何配置可永久运行的systemd服务,并在达到指定重试次数后上报错误

嗨,我来帮你梳理清楚这个systemd服务的配置方案!你要的是一个能自动自我修复、持续运行的服务,同时要避免它变成“僵尸服务”——也就是不断重启却没人知晓的情况,所以需要在短时间内达到指定失败次数时触发错误上报,对吧?下面就一步步来实现这个需求。

一、主服务配置(my_infinite.service)

先把你的主服务配置调整完善,关键参数我会逐一说明:

# /etc/systemd/system/my_infinite.service
[Unit]
Description=自修复常驻服务,持续运行并在达到失败阈值时触发错误上报
After=network.target
# 当服务达到启动限制失败时,触发错误处理服务
OnFailure=failure-handler@%N.service
# 失败次数统计的时间窗口:20秒
StartLimitIntervalSec=20s
# 这个时间窗口内允许的最大失败次数:2次
StartLimitBurst=2

[Service]
# 这里用你的模拟命令,实际替换成你的业务进程即可
ExecStart=/bin/zsh -c "echo 'started' && sleep 2 && echo 'finished' && exit 1"
# 无论进程因何种原因退出(除了被systemd主动停止),都自动重启
Restart=always
# 重启间隔时间:5秒
RestartSec=5s
# 重要:让systemd把这个服务当成常驻进程管理,避免误判
Type=simple
# 可选:设置服务运行的用户,提升安全性
# User=your-service-user

关键参数解释:

  • StartLimitIntervalSec + StartLimitBurst:这俩是黄金组合,用来定义“20秒内失败2次”的触发条件,当达到这个阈值时,systemd会停止自动重启,并触发OnFailure指定的处理服务。
  • Restart=always:确保服务意外退出后自动重启,实现自修复能力。
  • OnFailure=failure-handler@%N.service%N是systemd的内置变量,代表当前服务的名称,这样错误处理服务可以动态识别是哪个服务触发的告警。

二、错误处理服务配置(failure-handler@.service)

接下来是错误处理服务,它需要完成两个核心动作:1)重置主服务的启动失败计数器;2)调用自定义的错误上报逻辑(比如发告警通知、写入专门日志等)。创建这个模板服务:

# /etc/systemd/system/failure-handler@.service
[Unit]
Description=处理%s服务的失败告警
# 确保主服务已经处于失败状态再执行
BindsTo=%i.service
After=%i.service

[Service]
Type=oneshot
# 执行命令:先重置失败计数器,再执行你的自定义上报逻辑
ExecStart=/bin/bash -c "
  # 重置主服务的启动限制计数器,这样后续如果恢复正常还能继续重启
  systemctl reset-failed %i.service;
  # 这里替换成你的错误上报命令,比如调用API、发邮件、写告警日志等
  echo '服务%i在20秒内失败了2次,已触发告警' >> /var/log/service-alerts.log;
  # 例子:如果有自定义脚本,就改成 /path/to/your-alert-script.sh %i
"
# 只执行一次,执行完就退出
RemainAfterExit=no

关键逻辑说明:

  • systemctl reset-failed %i.service:这一步非常重要,重置主服务的失败计数器后,后续如果服务恢复正常,systemd还能继续自动重启它,不会一直卡在“达到失败阈值”的状态。
  • 自定义上报逻辑:你可以替换成任何你需要的操作,比如调用企业微信/钉钉的告警API、发送邮件给运维团队,或者写入专门的告警日志文件。

三、配置生效步骤

完成配置后,执行以下命令让systemd加载新配置并启动服务:

  1. 重新加载systemd配置:
systemctl daemon-reload
  1. 启动主服务并设置开机自启:
systemctl enable --now my_infinite.service
  1. 查看服务状态,验证是否正常工作:
systemctl status my_infinite.service
  1. 查看告警日志(如果用了上面的日志示例):
tail -f /var/log/service-alerts.log

四、验证效果

按照你的模拟命令,服务会每2秒退出一次,5秒后重启:

  • 第一次失败:systemd会在5秒后自动重启服务
  • 第二次失败(20秒内):达到StartLimitBurst=2的阈值,systemd停止自动重启,触发failure-handler@my_infinite.service
  • 错误处理服务执行:重置计数器,同时写入告警日志
  • 之后如果服务再次启动(比如手动启动或者后续有触发),计数器已经重置,会重新开始统计

这样就完美实现了“自修复+达到失败阈值上报错误”的需求,既保证服务能尽量持续运行,又不会在不断失败时没人知晓。

备注:内容来源于stack exchange,提问作者antonio

火山引擎 最新活动