相关文章
定时器是名称以 .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可以显示更多次触发时间。 - lib
faketime软件包中的 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.timer(5) 手册
- Fedora:Features/SystemdCalendarTimers
- Gentoo:Systemd 的定时器服务
- systemd-cron:提供 systemd 单元以运行 cron 脚本,并使用 systemd-crontab-generator 将 crontab 转换为定时器。
- 项目源码 || systemd-cron(AUR)
- systemd-cron-next:通过生成器转换 crontab 和 anacrontab。
- 项目源码 || systemd-cron-next-git(AUR)
原文来自 ArchWiki。除另有说明外,内容以 GNU Free Documentation License 1.3 或更高版本提供。许可:https://www.gnu.org/copyleft/fdl.html。











暂无评论内容