You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现systemd定时任务多次失败仅发送一次通知邮件?

实现单次失败通知的优雅方案

不用手动清理标记文件,我们可以通过拆分systemd服务职责,配合systemd的失败触发机制来解决这个问题:

方案思路

  • 主服务仅负责执行SQL刷新脚本,不处理通知逻辑,确保失败状态能被systemd正确捕获
  • 创建独立的失败通知服务,仅在主服务首次失败时发送邮件,并记录通知状态
  • 主服务成功执行时自动重置通知状态,以便下次失败时能再次触发通知

Ansible配置修改

1. 刷新物化视图的主服务

- name: 添加刷新物化视图的systemd主服务
  copy:
    content: |
      [Unit]
      Description=刷新物化视图
      Wants=refresh_matviews.timer
      # 失败时触发通知服务
      OnFailure=refresh_matviews-notify.service

      [Service]
      User=galaxy
      Type=oneshot
      # 仅执行SQL脚本,失败时让systemd捕获退出码
      ExecStart=/usr/bin/psql ... -f /path/to/refresh_matviews.sql
      # 执行成功时,清除通知标记,重置状态
      ExecStartPost=/bin/rm -f /var/tmp/refresh_matviews_failed.seen
      [Install]
      WantedBy=multi-user.target
    dest: /etc/systemd/system/refresh_matviews.service
    owner: root
    group: root
    mode: 0644

2. 失败通知服务

- name: 添加失败通知的systemd服务
  copy:
    content: |
      [Unit]
      Description=物化视图刷新失败通知
      # 仅在主服务失败时触发,且自身为一次性服务
      BindsTo=refresh_matviews.service
      After=refresh_matviews.service

      [Service]
      User=galaxy
      Type=oneshot
      # 仅当标记文件不存在时,发送邮件并创建标记
      ExecStart=/bin/bash -c 'if [ ! -f /var/tmp/refresh_matviews_failed.seen ]; then echo "物化视图刷新失败!" | /usr/bin/mail -s "告警:物化视图刷新失败" admin@foo.com; touch /var/tmp/refresh_matviews_failed.seen; fi'
      # 禁止自动重启
      Restart=no
    dest: /etc/systemd/system/refresh_matviews-notify.service
    owner: root
    group: root
    mode: 0644

3. 定时服务保持不变

原有的refresh_matviews.timer配置无需修改,依然每5分钟触发主服务。

方案优势

  • 无需手动清理标记:主服务成功时自动删除标记文件,下次失败会重新发送通知
  • 依赖systemd原生机制:通过OnFailure触发通知,状态管理更可靠
  • 职责分离:主服务专注业务逻辑,通知服务专注告警,架构更清晰

内容的提问来源于stack exchange,提问作者Timur Shtatland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:50:17