跳转到内容
搜索 RunEntLinux 文档

仅搜索 RunEntLinux 通用文档,各发行版文档使用各自的搜索入口。

    浏览当前文档目录

    定时任务 (Timer)

    systemd timer 是 cron 的现代替代方案,提供了更精确的调度控制、完善的日志集成和依赖管理能力。在 CentOS/AlmaLinux/Rocky Linux 上,越来越多的系统任务已经从 cron 迁移到了 systemd timer。

    特性systemd TimerCron
    日志集成自动集成 journald,可用 journalctl 查看需要手动配置日志重定向
    依赖管理支持 After=、Requires= 等依赖声明无依赖管理
    错过执行支持 Persistent=true,错过的任务会在下次启动时补执行错过即丢失
    资源控制可设置 CPU、内存、IO 限制无资源控制
    精度支持微秒级精度最小粒度为 1 分钟
    开机延迟支持 OnBootSec= 等相对时间触发不支持
    随机延迟支持 RandomizedDelaySec= 分散负载不支持
    管理方式统一使用 systemctl 管理需要编辑 crontab 文件

    systemd timer 以成对的方式工作:每个 .timer 单元对应一个同名的 .service 单元。当定时器触发时,systemd 会自动启动对应的 service 单元。

    例如:

    • backup.timer — 定义触发时间
    • backup.service — 定义要执行的任务

    基于相对时间触发,适合”距离某个事件过了多久”的场景:

    指令说明
    OnBootSec=系统启动后多久触发
    OnActiveSec=定时器激活后多久触发
    OnStartupSec=systemd 启动后多久触发
    OnUnitActiveSec=对应服务上次激活后多久再次触发
    OnUnitInactiveSec=对应服务上次完成后多久再次触发

    日历定时器(Realtime/Calendar Timer)

    Section titled “日历定时器(Realtime/Calendar Timer)”

    基于绝对时间触发,类似 cron 的定时方式:

    指令说明
    OnCalendar=按日历时间表达式触发

    OnCalendar= 使用以下格式:

    星期 年-月-日 时:分:秒
    表达式说明等效 Cron
    *-*-* 00:00:00每天午夜0 0 * * *
    *-*-* *:00:00每小时整点0 * * * *
    *-*-* *:*:00每分钟* * * * *
    *-*-01 00:00:00每月 1 号午夜0 0 1 * *
    Mon *-*-* 08:00:00每周一早上 8 点0 8 * * 1
    Mon..Fri *-*-* 18:00:00工作日每天 18 点0 18 * * 1-5
    *-*-* 06,18:00:00每天 6 点和 18 点0 6,18 * * *
    *-*-* 09:00:00/2h9 点起每 2 小时—

    systemd 还提供了便捷的预设值:

    预设值等价表达式
    minutely*-*-* *:*:00
    hourly*-*-* *:00:00
    daily*-*-* 00:00:00
    weeklyMon *-*-* 00:00:00
    monthly*-*-01 00:00:00
    yearly*-01-01 00:00:00

    使用 systemd-analyze calendar 来验证表达式是否正确,并预览接下来的触发时间:

    验证时间表达式并查看下次触发时间
    systemd-analyze calendar "Mon..Fri *-*-* 09:00:00"
    验证每 15 分钟触发一次的表达式
    systemd-analyze calendar "*-*-* *:00/15:00"

    下面以一个数据库备份任务为例,演示如何创建 timer + service 对。

    创建备份脚本
    sudo vim /opt/scripts/db-backup.sh

    写入以下内容:

    /opt/scripts/db-backup.sh
    #!/bin/bash
    BACKUP_DIR="/backup/database"
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    mkdir -p "$BACKUP_DIR"
    mysqldump --all-databases | gzip > "$BACKUP_DIR/all-db-$TIMESTAMP.sql.gz"
    # 删除 7 天前的备份
    find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
    echo "Database backup completed: all-db-$TIMESTAMP.sql.gz"
    赋予脚本执行权限
    sudo chmod +x /opt/scripts/db-backup.sh
    创建备份服务单元文件
    sudo vim /etc/systemd/system/db-backup.service
    /etc/systemd/system/db-backup.service
    [Unit]
    Description=Database Backup Service
    After=mariadb.service
    Wants=mariadb.service
    [Service]
    Type=oneshot
    ExecStart=/opt/scripts/db-backup.sh
    User=root
    StandardOutput=journal
    StandardError=journal
    # 超时设置(备份大数据库可能需要较长时间)
    TimeoutStartSec=3600
    # 安全加固
    PrivateTmp=true
    ProtectHome=true

    注意:timer 触发的 service 通常不需要 [Install] 段,因为它由 timer 启动而非直接 enable。

    创建备份定时器单元文件
    sudo vim /etc/systemd/system/db-backup.timer
    /etc/systemd/system/db-backup.timer
    [Unit]
    Description=Run Database Backup Daily at 2:00 AM
    [Timer]
    OnCalendar=*-*-* 02:00:00
    RandomizedDelaySec=300
    Persistent=true
    [Install]
    WantedBy=timers.target

    配置说明:

    指令说明
    OnCalendar=*-*-* 02:00:00每天凌晨 2 点触发
    RandomizedDelaySec=300随机延迟 0-300 秒,避免多台服务器同时执行
    Persistent=true如果错过了执行时间(如服务器关机),下次启动时立即补执行
    重新加载 systemd 配置
    sudo systemctl daemon-reload
    启用并启动定时器
    sudo systemctl enable --now db-backup.timer
    查看定时器状态和下次触发时间
    sudo systemctl status db-backup.timer
    手动触发一次备份服务进行测试
    sudo systemctl start db-backup.service
    查看备份服务的执行日志
    sudo journalctl -u db-backup.service -n 20

    除了基于日历时间的定时器,单调定时器适合”每隔一段时间执行一次”的场景:

    /etc/systemd/system/health-check.timer - 开机 1 分钟后首次执行,之后每 5 分钟执行一次
    [Unit]
    Description=Run Health Check Every 5 Minutes
    [Timer]
    OnBootSec=1min
    OnUnitActiveSec=5min
    [Install]
    WantedBy=timers.target
    /etc/systemd/system/health-check.service
    [Unit]
    Description=System Health Check
    [Service]
    Type=oneshot
    ExecStart=/opt/scripts/health-check.sh
    列出所有活动定时器及其下次触发时间
    systemctl list-timers

    查看所有定时器(包括未激活的)

    Section titled “查看所有定时器(包括未激活的)”
    列出所有定时器(含已停用的)
    systemctl list-timers --all
    停止定时器(不会取消 enable)
    sudo systemctl stop db-backup.timer
    禁用并停止定时器
    sudo systemctl disable --now db-backup.timer

    如果你有一个现有的 crontab 任务:

    30 3 * * * /opt/scripts/cleanup.sh

    对应的 systemd timer 配置为:

    /etc/systemd/system/cleanup.service
    [Unit]
    Description=Daily Cleanup Task
    [Service]
    Type=oneshot
    ExecStart=/opt/scripts/cleanup.sh
    /etc/systemd/system/cleanup.timer
    [Unit]
    Description=Run Cleanup Daily at 3:30 AM
    [Timer]
    OnCalendar=*-*-* 03:30:00
    Persistent=true
    [Install]
    WantedBy=timers.target
    启用迁移后的定时器
    sudo systemctl daemon-reload && sudo systemctl enable --now cleanup.timer

    确认 timer 正常工作后,再删除对应的 crontab 条目:

    编辑 crontab 移除旧任务
    sudo crontab -e
    查看定时器详细状态
    sudo systemctl status db-backup.timer
    查看定时器关联的服务最近执行结果
    sudo systemctl status db-backup.service
    查看定时器的所有属性
    systemctl show db-backup.timer
    验证 OnCalendar 表达式语法
    systemd-analyze calendar "*-*-* 02:00:00"
    查看定时器和服务的完整日志
    sudo journalctl -u db-backup.timer -u db-backup.service --since today