使用systemd创建定时任务

温馨提醒

在 Linux 中,使用 systemd 创建定时任务(即替代传统的 crontab)主要是通过两个单元(unit)文件来实现:

  1. Service 单元(.service):定义要执行的任务内容
  2. Timer 单元(.timer):定义何时执行该任务

与 cron 相比,优点如下:

  1. 精确到秒

  2. 灵活的时间表达,同时支持多个表达式

    OnCalendar=支持复杂的时间表达式,如:

    1
    2
    
    # 表示每天凌晨 3 点和每周一中午 12 点都执行一次
    OnCalendar=*-*-* 03:00:00; Mon *-*-* 12:00:00
  3. 日志记录集成

    自动集成到 journalctl,方便追踪

  4. 失败重试机制

    可通过 Restart= 配置失败重试

  5. 错过进可以补跑

    Persistent=true可实现

  6. 启动/停止控制

    可随时通过 start/stop 启动/停止服务

.service 和 .timer 文件名是否必须要一致:

不必须完全一致,但强烈建议保持一致。

虽然 systemd 不强制 .timer.service文件名称相同,但如果名称一致,系统会自动知道.timer对应的是哪个.service

如果文件名不一致时,怎么办:

可以通过Unit=显式指定.service的名称,如:

[Unit] Description=Custom timer

[Timer] OnCalendar=*:0/5 Unit=backup.service # 指定目标任务为 backup.service

[Install] WantedBy=timers.target

  • 创建 service 文件

    路径通常为/etc/systemd/system/文件名格式为 xxx.service

    创建/etc/systemd/system/backup.service

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [Unit]
    Description=Run backup script
    
    [Service]
    # 表示任务执行一次后就退出
    Type=oneshot
    
    # 要运行的脚本路径
    ExecStart=/opt/scripts/backup.sh
  • 创建 timer 文件

    创建/etc/systemd/system/backup.timer

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    [Unit]
    Description=Run backup script every 5 minutes
    
    [Timer]
    OnCalendar=*:0/5
    
    # 如果系统在计划时间关机了,下次开机时自动补一次
    Persistent=true
    
    [Install]
    # 允许用 enable 启动定时器
    WantedBy=timers.target

    OnCalendar 时间格式

    格式:DayOfWeek Year-Month-Day Hour:Minute:Second

    字段解释:

    Year:年份 Month:月份 Day:日期

    Hour:小时

    Minute:分钟

    Second:秒,默认0秒,可以省略

    *:匹配任意

    */n:每 n 个单位触发

    1,2,3:多个具体的值

    ..:范围,如1..5

    还可以写成 Mon,Tue 这样指定星期几

    常用示例:

    每天 02:00 OnCalendar=--* 02:00:00

    每小时 OnCalendar=hourly

    每分钟 OnCalendar=minutely

    每5分钟 OnCalendar=*:0/5

    每周一 08:00 OnCalendar=Mon --* 08:00:00

    每月1日 00:00 OnCalendar=--01 00:00:00

    每年1月1日 00:00 OnCalendar=*-01-01 00:00:00

  • 启动和测试

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    # 重载 systemd 配置
    systemctl daemon-reexec
    systemctl daemon-reload
    
    # 启用并启动定时器
    systemctl enable --now backup.timer
    
    # 查看定时器状态
    systemctl list-timers --all
    
    # 可以手动触发执行一次
    systemctl start backup.service
  • 查看日志

    1
    
    journalctl -u backup.service