systemd 定时器

相关文章

定时器是名称以 .timer 结尾的 systemd 单元文件,用来控制 .service 文件或事件。它们可以作为 cron 的替代品(参见 cron 的替代方案),内置日历时间与单调时间事件支持,并可异步运行。

定时器单元

定时器单元的名称以 .timer 结尾,存放在与其他 单元配置文件 相同的路径中。[Timer] 节定义何时、如何激活定时器。定时器分为两种:

  • 实时定时器(也称为壁钟定时器)使用日历事件激活,与 cron 作业类似。OnCalendar= 选项用于定义这类定时器。
  • 单调时间定时器依据相对于某个起点的时间间隔激活。在系统关机或挂起时,它们会停止计时。定时器存在多个通用的 OnTypeSec= 选项;常用的有 OnBootSec= 和 OnUnitActiveSec=。

有关全部选项及参数语法的详细说明,请参阅 systemd.timer(5) 和 systemd.time(7)。

Note systemd offers the target timers.target which sets up all timers that should be active after boot (see systemd.special(7) for details). To use it, add WantedBy=timers.target to the [Install] section of your timer and enable the timer unit.

服务单元

每个定时器都必须有一个对应的服务单元,用来描述需要激活的单元。默认情况下,foo.timer 会激活并控制 foo.service。由于服务由定时器激活,因此其文件不需要包含 [Install] 节。也可以在定时器的 [Timer] 节中通过 Unit= 指定其他名称的服务。

管理

要使用定时器,启用并启动 .timer 单元即可。可用以下命令显示已经启动的定时器:

$ systemctl list-timers
NEXT                          LEFT        LAST                          PASSED     UNIT                         ACTIVATES
Thu 2014-07-10 19:37:03 CEST  11h left    Wed 2014-07-09 19:37:03 CEST  12h ago    systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Fri 2014-07-11 00:00:00 CEST  15h left    Thu 2014-07-10 00:00:13 CEST  8h ago     logrotate.timer              logrotate.service

Note

  • 要列出所有定时器(包括未活动的定时器),使用 systemctl list-timers --all。
  • 除非当前正由定时器触发,否则服务单元通常处于未活动状态。
  • 如果定时器与实际状态不同步,可删除 /var/lib/systemd/timers/ 中相应的 stamp-* 文件;用户定时器则位于 ~/.local/share/systemd/ 下。它们是记录上次运行时间的空文件。下一次启动定时器时会重新创建。

示例

服务单元文件可以直接使用定时器调度。以下示例使用名为 foo.timer 的对应定时器调度 foo.service。

单调时间定时器

下面的定时器在开机 15 分钟后运行,并在系统持续运行期间每周运行一次。

/etc/systemd/system/foo.timer
[Unit]
Description=Run foo weekly and on boot

[Timer]
OnBootSec=15min
OnUnitActiveSec=1w

[Install]
WantedBy=timers.target

实时定时器

下面的定时器每周运行一次,即星期一 00:00。Persistent=true 表示:如果系统关机期间错过了执行时间,在下次激活定时器时立即执行。

/etc/systemd/system/foo.timer
[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target

OnCalendar= 事件的具体语法如下:

DayOfWeek Year-Month-Day Hour:Minute:Second

星号 * 可匹配任意值,逗号用于列举值,.. 用于指定范围。

下面的定时器在每月前四天的中午运行,但只有当天是星期一或星期二才会触发:

OnCalendar=Mon,Tue *-*-01..04 12:00:00

每月的第一个星期六:

OnCalendar=Sat *-*-1..7 18:00:00

DayOfWeek 必须包含至少一个星期值。要每天 04:00 执行,可以省略该字段:

OnCalendar=*-*-* 4:00:00

可以指定多个 OnCalendar= 事件。例如,工作日 22:30、周末 20:00:

OnCalendar=Mon..Fri 22:30
OnCalendar=Sat,Sun 20:00

可以在时间表达式末尾指定时区;使用 timedatectl list-timezones 查看可用时区。

OnCalendar=*-*-* 02:00:00 Europe/Paris

更多信息参见 systemd.time(7)。

Tip

  • 可以使用 systemd-analyze 工具的 calendar 选项验证 OnCalendar 时间表达式,并计算定时器下一次满足条件的时间。例如,运行 systemd-analyze calendar weekly,或 systemd-analyze calendar "Mon,Tue *-*-01..04 12:00:00"。添加 --iterations=N 可以显示更多次触发时间。
  • libfaketime 软件包中的 faketime 也可用于测试定时器。
  • daily、weekly 等事件会在相同的固定时间触发,因此多个任务可能争用资源。在 [Timer] 节设置 RandomizedDelaySec=,可将任务分散到不同时间。参阅 systemd.timer(5)。
  • 如果需要精确时间,可以在 [Timer] 节设置 AccuracySec=1us,避免默认的 1 分钟精度范围;参见 systemd.timer(5)。
  • 某些选项(如 WakeSystem)需要特定的系统能力,否则可能导致定时器无法启动,并报告 “Failed to enter waiting state: Operation not supported” 和 “Failed with result ‘resources’.”。

临时定时器单元

systemd-run 可以创建临时定时器,而无需预先编写服务文件。以下示例在 30 秒后执行 touch 命令:

# systemd-run --on-active=30 /bin/touch /tmp/foo

也可以指定一个已有、但没有对应定时器文件的服务。例如,以下命令在 12.5 小时后启动名为 someunit.service 的 systemd 单元:

# systemd-run --on-active="12h 30m" --unit someunit.service

更多信息参见 systemd-run(1)。

作为 cron 的替代方案

cron 是广为人知的定时任务工具。systemd 定时器可替代它。 (cron)

优点

每个定时器任务都有独立的 systemd 服务,因此可以获得以下能力:

  • 可以独立启动任务,便于调试。
  • 可以按 systemd.exec(5) 的规定设置特定运行环境。
  • 可使用 cgroups 管理资源。 (cgroups)
  • 可定义对其他 systemd 单元的依赖。
  • 任务记录在 journal 中,便于排查问题。

注意事项

cron 中很简单的操作,换成定时器可能更复杂:

  • 创建任务:systemd 需要创建两个文件并运行 systemctl 命令,而 crontab 只需要增加一行。
  • 没有内置的 MAILTO 功能来发送失败邮件。可使用 OnFailure=,参见 systemd 中的邮件通知。

默认情况下,用户定时器只有在用户登录会话活动时才运行。启用 lingering 后,即使用户没有活动会话,服务也可以在开机时运行。

使用 crontab

systemd-cron-next-git(AUR)和 systemd-cron(AUR)可以解析传统的 crontab,并为 MAILTO 等功能提供解决方法。

这样既可以保留 crontab,又可以通过 systemctl 统一查看任务;参见 管理。

手动处理

除迁移既有 cron 任务之外,还可以为 cron 风格的执行周期编写模板,从而避免给每个任务单独创建定时器。 (template unit)

/etc/systemd/system/monthly@.timer
[Unit]
Description=Monthly Timer for %i service

[Timer]
OnCalendar=*-*-1 02:00:00
AccuracySec=6h
RandomizedDelaySec=1h
Persistent=true
Unit=%i.service

[Install]
WantedBy=default.target

Note See systemd.timer(5) § OPTIONS for the importance of using RandomizedDelaySec and not only AccuracySec to avoid all units started by the timer firing at once.

随后只需启用并启动 monthly@unit_name.timer。

Tip The template units can be nested, e.g. one could enable/start monthly@btrfs-scrub@mnt-$(systemd-escape bbb76c63-e4ac-4e39-8897-a120c5d30686).timer.

提示与技巧

有效期(time-to-live)

某些程序会记录距离上次下载或更新过去了多久;如果还不到 24 小时,就禁止再次更新数据库。

默认情况下,定时器不跟踪任务完成时间。可以使用 OnUnitInactiveSeconds,在被触发的服务停用之后再开始计时。

/etc/systemd/system/daily-inactive@.timer
[Unit]
Description=Launch %i service 24hours after it deactivated

[Timer]
OnUnitInactiveSec=1day1sec
Unit=%i.service
Persistent=true

[Install]
WantedBy=default.target

Tip With Restart=on-failure along with RestartSec, it is possible to have a unit rerun after failure and success according to different schedules, see systemd.service(5) § OPTIONS.

桌面通知

systemd-timer-notify(AUR)可以在定时器触发时自动显示桌面通知;对应服务运行期间通知保持显示,服务结束后关闭。

这有助于解释 CPU 使用率突然升高的原因,也能避免在备份尚未完成时关机。

详情与配置参见 项目页面。

参阅

项目源码 || systemd-cron(AUR)
  • systemd-cron-next:通过生成器转换 crontab 和 anacrontab。
项目源码 || systemd-cron-next-git(AUR)

来源:ArchWiki · systemd/Timers。

原文来自 ArchWiki。除另有说明外,内容以 GNU Free Documentation License 1.3 或更高版本提供。许可:https://www.gnu.org/copyleft/fdl.html。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容