linux中可通过systemd的onfailure机制实现服务失败自动邮件告警:先配置mail命令支持smtp发信,再编写带服务名、退出码等上下文的告警脚本,最后在unit文件中启用onfailure并关联模板服务,全程无需外部轮询。

Linux 中配置 systemd 服务失败后自动发送邮件告警,关键不是等服务挂了再“查日志+手动通知”,而是让 systemd 在检测到异常退出时,直接触发一个带上下文的邮件脚本。整个过程不依赖外部轮询或监控平台,响应快、可靠性高。
确保系统具备可用的邮件发送能力
systemd 本身不发邮件,它只负责调用外部命令。所以第一步必须验证 mail 命令能在 root 环境下稳定投递:
- 安装 mailx(CentOS/RHEL):yum install -y mailx;Ubuntu/Debian:apt update && apt install -y mailutils
- 配置 /etc/mail.rc,以 QQ 邮箱为例(务必用 SMTP 授权码,不是登录密码):
set from=yourname@qq.com
set smtp=smtps://smtp.qq.com:465
set smtp-auth-user=yourname@qq.com
set smtp-auth-password=你的授权码
set smtp-auth=login
set ssl-verify=ignore - 测试是否通:echo "test" | mail -s "systemd test" admin@example.com,收到即成功
编写失败触发的告警脚本
这个脚本会被 systemd 调用,需能获取服务名、退出状态、错误时间等关键信息。保存为 /usr/local/bin/systemd-fail-alert.sh:
- 添加可执行权限:chmod +x /usr/local/bin/systemd-fail-alert.sh
- 脚本内容示例(适配大多数场景):
#!/bin/bash
service_name="$1"
exit_code="$2"
timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
host="$(hostname)"
subject="❌ systemd service failed: ${service_name}"
body="Service: ${service_name}\nExit Code: ${exit_code}\nTime: ${timestamp}\nHost: ${host}\n\nCheck with: systemctl status ${service_name}"
echo "$body" | mail -s "$subject" admin@example.com - 建议同时记录到本地日志:echo "[$timestamp] $service_name failed (code $exit_code)" >> /var/log/systemd-alert.log
在服务单元中启用 OnFailure
编辑目标服务的 unit 文件(如 /etc/systemd/system/nginx.service),在 [Unit] 或 [Service] 段下方添加:
-
OnFailure=systemd-fail-alert@%n.service(推荐,支持参数化)
或
OnFailure=systemd-fail-alert.service(简单直连,需在脚本里用 $SERVICE 等变量取名) - 若使用 @ 符号方式,还需创建对应的模板服务:
/etc/systemd/system/systemd-fail-alert@.service,内容含:
[Service]
Type=oneshot
ExecStart=/usr/local/bin/systemd-fail-alert.sh %i $EXIT_CODE - 重载配置:systemctl daemon-reload
验证与调试要点
systemd 的 OnFailure 是在服务进程退出且状态为 failed 时触发,不是每次 restart 都调用。调试时注意:
- 手动模拟失败:systemctl kill --signal=SIGKILL nginx,然后检查邮件和日志
- 查看触发记录:journalctl -u nginx -n 20 和 journalctl -u systemd-fail-alert@nginx.service
- 确保脚本中所有路径用绝对路径(如 /bin/date 而非 date),避免 cron 类环境缺失 PATH
- 收件人建议设为运维邮箱,并抄送企业微信/钉钉机器人 Webhook(可扩展为 curl 推送)











