写点什么

关于 Linux 中作业调度 crond 和 systemd.timer 使用场景

作者:山河已无恙
  • 2022-12-03
    内蒙古
  • 本文字数:14224 字

    阅读完需:约 47 分钟

写在前面



  • 分享一些 systemd.timer 相关的笔记

  • 博文内容涉及:

  • systemd.timer 的一些介绍

  • cron VS systemd.timer 区别

  • 如何创建 systemd.timer 作业调度

  • 理解不足小伙伴帮忙指正


我们承受所有的不幸,皆因我们无法独处 ------叔本华



关于 systemd.timer 的一些介绍

crond 这里不多介绍,小伙伴们应该都接触过。所以直接来看 systemd.timer


systemd 的 timer 单元。 用于封装一个基于时间触发的动作。它取代了传统的 atd, crond 等任务计划服务。参见 systemd.timer(5) 手册。, 换句话讲,就是对crond的任务进行了细粒度的处理,以前我们通过 bash 脚本处理的一些调度策略,现在可以通过 systemd.timer 来实现。


systemctl list-unit-files -t timer 命令可以查看当前系统的 timer 单元


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$systemctl list-unit-files  -t timerUNIT FILE                    STATEchrony-dnssrv@.timer         disabledfstrim.timer                 disabledpmie_check.timer             disabledpmie_daily.timer             disabledpmlogger_check.timer         disabledpmlogger_daily-poll.timer    disabledpmlogger_daily.timer         disabledsystemd-readahead-done.timer indirectsystemd-tmpfiles-clean.timer static
9 unit files listed.
复制代码


systemctl status systemd-tmpfiles-clean.timer 可以查看具体的状态信息


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$systemctl status systemd-tmpfiles-clean.timer● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories   Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static; vendor preset: disabled)   Active: active (waiting) since 日 2022-10-23 01:07:13 CST; 4 days ago     Docs: man:tmpfiles.d(5)           man:systemd-tmpfiles(8)
10月 23 01:07:13 liruilongs.github.io systemd[1]: Started Daily Cleanup of Temporary Directories.
复制代码


systemctl cat systemd-tmpfiles-clean.timer 命令可以查看相关配置信息


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$systemctl cat systemd-tmpfiles-clean.timer# /usr/lib/systemd/system/systemd-tmpfiles-clean.timer#  This file is part of systemd.##  systemd is free software; you can redistribute it and/or modify it#  under the terms of the GNU Lesser General Public License as published by#  the Free Software Foundation; either version 2.1 of the License, or#  (at your option) any later version.
[Unit]Description=Daily Cleanup of Temporary DirectoriesDocumentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
[Timer]OnBootSec=15minOnUnitActiveSec=1d┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$
复制代码


上面的配置中,OnBootSec=15min 表示系统启动后 15 分钟执行,OnUnitActiveSec=1d 表示间隔多长时间执行下一次。


那么这里执行什么,如果没有显示的定义 unit 字段,默认是和 timer 同名 service 单元。


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$systemctl status systemd-tmpfiles-clean.service● systemd-tmpfiles-clean.service - Cleanup of Temporary Directories   Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.service; static; vendor preset: disabled)   Active: inactive (dead) since 四 2022-10-27 15:36:56 CST; 5h 58min ago     Docs: man:tmpfiles.d(5)           man:systemd-tmpfiles(8)  Process: 9783 ExecStart=/usr/bin/systemd-tmpfiles --clean (code=exited, status=0/SUCCESS) Main PID: 9783 (code=exited, status=0/SUCCESS)
10月 27 15:36:56 liruilongs.github.io systemd[1]: Starting Cleanup of Temporary Directories...10月 27 15:36:56 liruilongs.github.io systemd[1]: Started Cleanup of Temporary Directories.
复制代码


需要注意的是,如果当前Service unitactive 状态,那么定时任务是不会执行的,所以这里和 crond有一定的区别,如果是crond只能通过 bash 任务内部判断.


对应timerservice 的单元文件


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$systemctl cat systemd-tmpfiles-clean.service# /usr/lib/systemd/system/systemd-tmpfiles-clean.service#  This file is part of systemd.##  systemd is free software; you can redistribute it and/or modify it#  under the terms of the GNU Lesser General Public License as published by#  the Free Software Foundation; either version 2.1 of the License, or#  (at your option) any later version.
[Unit]Description=Cleanup of Temporary DirectoriesDocumentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)DefaultDependencies=noConflicts=shutdown.targetAfter=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target time-sync.targBefore=shutdown.target
[Service]Type=oneshotExecStart=/usr/bin/systemd-tmpfiles --cleanIOSchedulingClass=idle┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$
复制代码


可以通过 journalctl 来看看单元对应的日志信息


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$journalctl -u systemd-tmpfiles-clean.service-- Logs begin at 日 2022-10-23 01:07:09 CST, end at 四 2022-10-27 21:55:39 CST. --10月 23 01:22:25 liruilongs.github.io systemd[1]: Starting Cleanup of Temporary Directories...10月 23 01:22:25 liruilongs.github.io systemd[1]: Started Cleanup of Temporary Directories.10月 24 01:22:45 liruilongs.github.io systemd[1]: Starting Cleanup of Temporary Directories...10月 24 01:22:45 liruilongs.github.io systemd[1]: Started Cleanup of Temporary Directories.10月 27 15:36:56 liruilongs.github.io systemd[1]: Starting Cleanup of Temporary Directories...10月 27 15:36:56 liruilongs.github.io systemd[1]: Started Cleanup of Temporary Directories.┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$journalctl -u systemd-tmpfiles-clean.timer-- Logs begin at 日 2022-10-23 01:07:09 CST, end at 四 2022-10-27 21:55:39 CST. --10月 23 01:07:13 liruilongs.github.io systemd[1]: Started Daily Cleanup of Temporary Directories.┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$
复制代码


systemctl list-timers --no-pager 可以列出当前已经生效的定时器


┌──[root@liruilongs.github.io]-[~]└─$systemctl list-timers --no-pagerNEXT                         LEFT       LAST                         PASSED    UNIT     ACTIVATES五 2022-10-28 00:55:00 CST  24min left 五 2022-10-28 00:25:08 CST  5min ago  pmlogger_check.timer         pmlogger_check.service五 2022-10-28 01:30:00 CST  59min left 五 2022-10-28 00:30:01 CST  47s ago   pmlogger_daily-poll.timer    pmlogger_daily-poll.service五 2022-10-28 15:36:56 CST  15h left   四 2022-10-27 15:36:56 CST  8h ago    systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service六 2022-10-29 00:10:00 CST  23h left   五 2022-10-28 00:10:01 CST  20min ago pmlogger_daily.timer         pmlogger_daily.service
4 timers listed.Pass --all to see loaded but inactive timers, too.┌──[root@liruilongs.github.io]-[~]└─$
复制代码


查看单个定时器的 详细信息


┌──[root@liruilongs.github.io]-[~]└─$systemctl list-timers systemd-tmpfiles-clean.timerNEXT                         LEFT     LAST                         PASSED UNIT                         ACTIVATES六 2022-10-29 15:37:00 CST  15h left 五 2022-10-28 15:37:00 CST  8h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.se1 timers listed.Pass --all to see loaded but inactive timers, too.
复制代码


关于 timer 单位文件具体的参数我们可以通过帮助文档查看 帮助手册查看 man systemd.timer


┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$man systemd.timer | catSYSTEMD.TIMER(5)                            systemd.timer                           SYSTEMD.TIMER(5)


NAME systemd.timer - Timer unit configuration
SYNOPSIS timer.timer
DESCRIPTION # 以 ".timer" 为后缀的单元文件, 封装了一个由 systemd 管理的定时器, 以支持基于定时器的启动。 A unit configuration file whose name ends in ".timer" encodes information about a timer controlled and supervised by systemd, for timer-based activation.
# 本手册列出了 所有专用于此类单元的配置选项(亦称"配置指令"或"单元属性")。 # systemd.unit(5) 中描述了通用于所有单元类型的配置选项, 它们位于 [Unit] 与 [Install] 小节。 # 此类单元专用的配置选项位于 [Timer] 小节。 This man page lists the configuration options specific to this unit type. See systemd.unit(5) for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The timer specific configuration options are configured in the [Timer] section.
# 每个定时器单元都必须有一个与其匹配的单元, 用于在特定的时间启动。 # 匹配的单元可以通过 Unit= 选项(见下文)明确指定。 # 若未指定,则默认是与该单元名称相同的 .service 单元(不算后缀)。例如 foo.timer 默认匹配 foo.service 单元。 For each timer file, a matching unit file must exist, describing the unit to activate when the timer elapses. By default, a service by the same name as the timer (except for the suffix) is activated. Example: a timer file foo.timer activates a matching service foo.service. The unit to activate may be controlled by Unit= (see below).
# 注意,如果在启动时间点到来的时候,匹配的单元已经被启动, 那么将不执行任何动作,也不会启动任何新的服务实例。 # 因此,那些设置了 RemainAfterExit=yes(当该服务的所有进程全部退出之后,依然将此服务视为处于活动状态) 的服务单元一般不适合使用基于定时器的启动。 # 因为这样的单元仅会被启动一次,然后就永远处于活动(active)状态了。
# 下列依赖关系是自动隐含的:: 定时器单元自动获得对匹配单元的 Before= 依赖。 # 除非明确设置了 DefaultDependencies=no ,否则 timer 单元将会自动添加下列依赖关系: # Requires=sysinit.target, After=sysinit.target, Before=timers.target 依赖; 以及 Conflicts=shutdown.target, Before=shutdown.target 依赖(确保在关机前干净的停止)。 只有那些在系统启动的早期就必须启动的定时器,以及那些必须在关机动作的结尾才能停止的定时器才需要设置 DefaultDependencies=no Unless DefaultDependencies= is set to false, all timer units will implicitly have dependencies of type Conflicts= and Before= on shutdown.target to ensure that they are stopped cleanly prior to system shutdown. Timer units with at least one OnCalendar= directive will have an additional After= dependency on timer-sync.target to avoid being started before the system clock has been correctly set. Only timer units involved with early boot or late system shutdown should disable the DefaultDependencies= option.
OPTIONS # 定时器单元文件中必须包含一个 [Timer] 小节, 其中包含了该单元所定义的定时器的相关信息。 这里只列出仅能用于 [Timer] 小节的选项(亦称"指令"或"属性"): Timer files must include a [Timer] section, which carries information about the timer it defines. The options specific to the [Timer] section of timer units are the following: # 定义相对于特定时间点之后一段时间的 单调定时器: # OnActiveSec= 相对于该单元自身被启动的时间点; # OnBootSec= 相对于机器被启动的时间点, 也就是内核开始运行的时间点; # OnStartupSec= 相对于 systemd 被首次启动的时间点,也就是内核启动init进程的时间点; # OnUnitActiveSec= 相对于匹配单元最后一次被启动的时间点; # OnUnitInactiveSec= 相对于匹配单元 最后一次被停止的时间点; OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec= Defines monotonic timers relative to different starting points: OnActiveSec= defines a timer relative to the moment the timer itself is activated. OnBootSec= defines a timer relative to when the machine was booted up. OnStartupSec= defines a timer relative to when systemd was first started. OnUnitActiveSec= defines a timer relative to when the unit the timer is activating was last activated. OnUnitInactiveSec= defines a timer relative to when the unit the timer is activating was last deactivated.
# 可以组合使用这些指令(既可以将某个指令使用多次,也可以将多个指令一起使用), # 例如,通过同时使用 OnBootSec= 与 OnUnitActiveSec= 指令, 就可以实现在系统启动后的某个时间点启动匹配单元, 并且之后每隔一段时间周期性的反复启动匹配单元。 Multiple directives may be combined of the same and of different types. For example, by combining OnBootSec= and OnUnitActiveSec=, it is possible to define a timer that elapses in regular intervals and activates a specific service each time.
# 指令的值是一个时间长度, 可以使用下面的时间单位后缀:us(微秒), ms(毫秒), s(秒), m(分), h(时), d(天), w(周) 。 # 如果省略了时间单位,那么表示使用默认单位"秒"。 可以同时使用多个时间单位, # 例如 "OnBootSec=5h 30min" 表示系统启动之后的5小时30分钟。 更多有关表示时间长度的语法,参见 systemd.time(7) 手册。 The arguments to the directives are time spans configured in seconds. Example: "OnBootSec=50" means 50s after boot-up. The argument may also include time units. Example: "OnBootSec=5h 30min" means 5 hours and 30 minutes after boot-up. For details about the syntax of time spans, see systemd.unit(5).
# 如果定时器单元在启动时已经超过了 OnBootSec= 或 OnStartupSec= 指定的时间, 那么将会立即启动匹配的单元。 # 但是对于使用其他指令定义的定时器, 超过了就等于错过了,不会尝试去补救。 If a timer configured with OnBootSec= or OnStartupSec= is already in the past when the timer unit is activated, it will immediately elapse and the configured unit is started. This is not the case for timers defined in the other directives.
# 这几个指令定义的定时器都是基于单调时间的单调定时器(monotonic timer),所谓"单调时间"的意思是从开机那一刻(零点)起, 只要系统正在运行,该时间就不断的单调均匀递增(但在系统休眠时此时间保持不变),永远不会往后退,并且与时区也没有关系。 即使在系统运行的过程中,用户向前/向后修改系统时间,也不会对"单调时间"产生任何影响。 These are monotonic timers, independent of wall-clock time and timezones. If the computer is temporarily suspended, the monotonic clock stops too. # 如果给某个指令赋予一个空字符串, 则表示 撤销该指令之前已设置的所有定时器 If the empty string is assigned to any of these options, the list of timers is reset, and all prior assignments will have no effect. # 注意, 这些指令设置的定时器并不必然在所设置的精准时间点上启动匹配单元, 因为它们还受到下文 AccuracySec= 选项的影响。 Note that timers do not necessarily expire at the precise time configured with these settings, as they are subject to the AccuracySec= setting below.
OnCalendar= # 定义基于挂钟时间(wallclock)的日历定时器,是与传统cron任务类似的定时器。详见 systemd.time(7) 手册以了解日历事件表达式的语法 Defines realtime (i.e. wallclock) timers with calendar event expressions. See systemd.time(7) for more information on the syntax of calendar event expressions. Otherwise, the semantics are similar to OnActiveSec= and related settings. # 注意,该指令设置的定时器 并不必然在所设置的精准时间点上启动匹配单元, 因为它们还受到下文 AccuracySec= 选项的影响 Note that timers do not necessarily expire at the precise time configured with this setting, as it is subject to the AccuracySec= setting below.
AccuracySec= # 设置定时器的触发精度。默认值是一分钟。定时器并不必然在所设置的精准时间点上启动匹配单元, 而是在所设置的精准时 # 间点为起点的一小段时间窗口范围内的某个时间点上启动匹配单元, 这个时间窗口的起点由 OnCalendar=, # OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec= 决定, 而这个时间窗口的长 # 度则由该指令决定。 在这个时间窗口内,触发点的具体位置虽然无法在系统开机之前预知, 也就是说触发点的具体位置在每 # 次启动之间是随机的, 但是一旦开机之后,对于正在运行中的系统而言又是固定的, 并且对全系统范围内所有的定时器而言 # 都是固定的。 这么做的目的在于避免过多不必要的CPU唤醒,以节约电力。 若想获得最高精度,可以将此选项设为"1us"(一 # 微秒),但是耗电量就可能明显增加。 注意,定时器的精度还受到 systemd-system.conf(5) 中的 TimerSlackNSec= 选 # 项的影响(不过一般可以忽略不计,参见 prctl(2) 手册)。 为了优化耗电量, 应该将此指令设为可接收的最大值。 Specify the accuracy the timer shall elapse with. Defaults to 1min. The timer is scheduled to elapse within a time window starting with the time specified in OnCalendar=, OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec= or OnUnitInactiveSec= and ending the time configured with AccuracySec= later. Within this time window, the expiry time will be placed at a host-specific, randomized, but stable position that is synchronized between all local timer units. This is done in order to optimize power consumption to suppress unnecessary CPU wake-ups. To get best accuracy, set this option to 1us. Note that the timer is still subject to the timer slack configured via systemd- system.conf(5)'s TimerSlackNSec= setting. See prctl(2) for details. To optimize power consumption, make sure to set this value as high as possible and as low as necessary.'

RandomizedDelaySec= # 将此单元的定时器随机延迟一小段时间, 这一小段时间的长度 介于零到该指令设置的时间长度之间, 以均匀概率分布。 默 # 认值是零,表示不延迟。 定时器单元在每次迭代前确定这个随机值的大小, 并简单的把它加到下一次启动匹配单元的时间点 # 上, 此选项可以将大量在同一时间点触发的定时器 均匀的分摊到一小段时间范围内触发, 以避免造成资源争抢。 # AccuracySec= 允许将一段时间内分散的定时器事件集中到一点,以减少CPU唤醒。 而本指令正好相反, 允许将集中在一点 # 的定时器事件分散到一小段时间范围内, 以避免造成资源争抢。如果同时使用 RandomizedDelaySec= 与 AccuracySec= # 选项, 那么首先添加一个随机的时间, 然后结果可能进一步被平移, 以和系统上其他定时器事件合并。 因为默认设置 # AccuracySec=1min, RandomizedDelaySec=0 鼓励将多个定时器事件聚合在一起。 所以如果希望尽可能均匀分散定时器事 # 件,那么应该将 RandomizedDelaySec= 设为一个较大的值,同时设置 AccuracySec=1us
Delay the timer by a randomly selected, evenly distributed amount of time between 0 and the specified time value. Defaults to 0, indicating that no randomized delay shall be applied. Each timer unit will determine this delay randomly each time it is started, and the delay will simply be added on top of the next determined elapsing time. This is useful to stretch dispatching of similarly configured timer events over a certain amount time, to avoid that they all fire at the same time, possibly resulting in resource congestion. Note the relation to AccuracySec= above: the latter allows the service manager to coalesce timer events within a specified time range in order to minimize wakeups, the former does the opposite: it stretches timer events over a time range, to make it unlikely that they fire simultaneously. If RandomizedDelaySec= and AccuracySec= are used in conjunction, first the a randomized time is added, and the result is then possibly shifted further to coalesce it with other timer events possibly happening on the system. As mentioned above AccuracySec= defaults to 1min and RandomizedDelaySec= to 0, thus encouraging coalescing of timer events. In order to optimally stretch timer events over a certain range of time, make sure to set RandomizedDelaySec= to a higher value, and AccuracySec=1us.
Unit= # 该定时器单元的匹配单元, 也就是要被该定时器启动的单元。参数是一个不以 ".timer" 结尾的单元名。 # 默认值是 与此定时器单元同名的服务单元(见上文)。 # 建议将定时器单元的名字 与被该定时器启动的匹配单元的名字保持一致 (也就是仅单元后缀名不同)。 The unit to activate when this timer elapses. The argument is a unit name, whose suffix is not ".timer". If not specified, this value defaults to a service that has the same name as the timer unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the timer unit are named identically, except for the suffix.
Persistent= # 此选项仅对 OnCalendar= 指令定义的日历定时器有意义。 若设为"yes",则表示将匹配单元的上次触发时间永久保存在磁盘 # 上。 这样,当定时器单元再次被启动时, 如果匹配单元本应该在定时器单元停止期间至少被启动一次, 那么将立即启动匹配 # 单元。 这样就不会因为关机而错过必须执行的任务。 默认值为 no Takes a boolean argument. If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. This is useful to catch up on missed runs of the service when the machine was off. Note that this setting only has an effect on timers configured with OnCalendar=.
WakeSystem= # 若设为"yes", 则表示当某个定时器到达触发时间点时, 唤醒正在休眠的系统并阻止系统进入休眠状态。 # 注意, 此选项仅确保唤醒系统, 而不关心任务执行完成之后是否需要再次休眠系统。 默认值为 no Takes a boolean argument. If true, an elapsing timer will cause the system to resume from suspend, should it be suspended and if the system supports this. Note that this option will only make sure the system resumes on the appropriate times, it will not take care of suspending it again after any work that is to be done is finished. Defaults to false.
SEE ALSO systemd(1), systemctl(1), systemd.unit(5), systemd.service(5), systemd.time(7), systemd.directives(7), systemd-system.conf(5), prctl(2)


systemd 219 SYSTEMD.TIMER(5)┌──[root@liruilongs.github.io]-[/etc/tmpfiles.d]└─$
复制代码

crond 于 systemd.timer 的区别

虽然 systemd 定时器单元可以用来安排类似 cron 的工作,但两者之间有明显的优缺点。systemd.timer 更独立,但是配置略麻烦,crond配置简单,所以相对功能简单,当前用户的所有任务在一起配置


Systemd 计时器单元基本上是 systemd 服务,随之而来的是所有功能和优势,包括但不限于:


  • 作业可以有依赖项(可以依赖于其他 systemd 服务),可以设置前置后置依赖,可以运用于一些调度场景,这一点事

  • 定时器单元被记录到 systemd 日志中,可以通过 journalctl -u 来查看日志信息

  • 可以轻松地运行一个独立的定时器的作业。可以作为一个工具存在,crond,at 的所有作业是依赖于crond等服务的

  • 计时器单元可以有一个很好的值,也可以使用cgroups来管理资源。

  • Systemd 计时器单元可以由启动和硬件更改等事件触发。

  • 可以使用 systemctl 轻松管理,禁用或启用。

  • 定时器单元可以使用实时单调时间


systemd 计时器相比,Cron 有几个明显的好处。


  • 配置 cron 作业是一个简单的过程。

  • Cron 能够使用 MAILTO 功能发送电子邮件。

创建 sustemd.timer unit

来看一个小 Demo,我们希望在指定时间周期重启服务,创建 systemd.timer unit 我们需要下面两个单元:


  • 作业运行的定时器单元

  • 重启任务的服务单元


以 httpd 服务为例,当前到的服务状态为 inactive


┌──[root@liruilongs.github.io]-[~]└─$systemctl status httpd● httpd.service - The Apache HTTP Server   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)  Drop-In: /etc/systemd/system/httpd.service.d           └─50-BlockIOAccounting.conf, 50-CPUShares.conf, 50-MemoryLimit.conf   Active: inactive (dead)     Docs: man:httpd(8)           man:apachectl(8)
复制代码


创建重启服务的 Service unit


┌──[root@liruilongs.github.io]-[~]└─$vim /etc/systemd/system/restart-httpd.service┌──[root@liruilongs.github.io]-[~]└─$cat /etc/systemd/system/restart-httpd.service[Unit]Description= update httpd config , restart httpd serviceAfter=network-online.target
[Service]Type=oneshotExecStart=/usr/bin/systemctl restart httpd.service
[Install]WantedBy=multi-user.target┌──[root@liruilongs.github.io]-[~]└─$systemd-analyze verify /etc/systemd/system/restart-httpd.service
复制代码


创建定时器的 timer units


这里我么使用 OnCalendar=*:*:10 设置每分钟 10 秒的时候 z 周期执行 Service。OnwBootSec=3s 在系统开机多久执行 ,当然也可以尝试其他的字段,具体可以看下文档


┌──[root@liruilongs.github.io]-[~]└─$systemctl cat restart-httpd.timer# /etc/systemd/system/restart-httpd.timer[Unit]Description="每分钟10秒 后重启 httpd"
[Timer]OnBootSec=3sOnCalendar=*:*:10Unit=restart-httpd.service
[Install]WantedBy=multi-user.target
复制代码


写完之后要做文件校验


┌──[root@liruilongs.github.io]-[~]└─$vim  /etc/systemd/system/restart-httpd.timer┌──[root@liruilongs.github.io]-[~]└─$systemd-analyze verify /etc/systemd/system/restart-httpd.timer
复制代码


简单的介绍下 onCalendar字段表达式的写法:


* *-*-* *:*:*


  • * - 表示一周中的某一天,例如:- Sat,Thu,Mon

  • *-*-* - 表示日历日期。这意味着它分解为 year-month-date

  • 2021-10-15 是 10 月 15 日

  • *-10-15 表示每年的 10 月 15 日

  • *-01-01意味着每个新年。

  • *:*:* 是表示日历事件的时间分量 - hour:minute:second


常见的表达式:


  • 每一分钟 *-*-* *:*:00

  • 每 5 分钟 *-*-* *:*/5:00

  • 每 60 分钟 *-*-* */1:00:00

  • 每 1 小时 *-*-* *:00:00

  • 每 3 小时 *-*-* */3:00:00

  • 每隔一小时 *-*-* */2:00:00

  • 每 12 小时 *-*-* */12:00:00

  • 在特定时间之间 *-*-* 9-17:00:00

  • 每天 *-*-* 00:00:00

  • 每天凌晨 1 点 *-*-* 01:00:00

  • 每晚午夜 *-*-* 00:00:00

  • 每周六 Sat *-*-* 00:00:00

  • 星期一到星期五 Mon...Fri *-*-* 00:00:00

  • 每周末 Sat,Sun *-*-* 00:00:00

  • 每 7 天 * *-*-* 00:00:00

  • 每个月 * *-*-01 00:00:00

  • 每个季度 * *-01,04,07,10-01 00:00:00

  • 每 6 个月 * *-01,07-01 00:00:00

  • 每年 * *-01-01 00:00:00


执行定时器


┌──[root@liruilongs.github.io]-[~]└─$systemctl start restart-httpd.timer
复制代码


通过 systemctl list-timers restart-httpd.timer 我们可以查看定时计划的详细信息,next 表示下一秒执行的时间


┌──[root@liruilongs.github.io]-[~]└─$systemctl list-timers  restart-httpd.timerNEXT                         LEFT     LAST                         PASSED UNIT                ACTIVATES五 2022-10-28 22:49:10 CST  58s left 五 2022-10-28 22:48:10 CST  1s ago restart-httpd.timer restart-httpd.service
1 timers listed.Pass --all to see loaded but inactive timers, too.┌──[root@liruilongs.github.io]-[~]└─$date2022年 10月 28日 星期五 22:48:30 CST
复制代码


配置指定在未来的某个时间执行


┌──[root@liruilongs.github.io]-[~]└─$systemctl cat restart-httpd.timer# /etc/systemd/system/restart-httpd.timer[Unit]Description="2022-10-28 23:20:00 后重启 httpd"
[Timer]OnBootSec=3sOnCalendar=2022-10-28 23:20:00Unit=restart-httpd.service
[Install]WantedBy=multi-user.target
复制代码


查看执行日志


┌──[root@liruilongs.github.io]-[~]└─$journalctl -u restart-httpd.service | tail -n 510月 28 23:19:15 liruilongs.github.io systemd[1]: Started update httpd config , restart httpd service.10月 28 23:19:44 liruilongs.github.io systemd[1]: Starting update httpd config , restart httpd service...10月 28 23:19:45 liruilongs.github.io systemd[1]: Started update httpd config , restart httpd service.10月 28 23:20:01 liruilongs.github.io systemd[1]: Starting update httpd config , restart httpd service...10月 28 23:20:02 liruilongs.github.io systemd[1]: Started update httpd config , restart httpd service.
复制代码


在次查看状态,就没有下一次执行的时间了


┌──[root@liruilongs.github.io]-[~]└─$systemctl list-timers restart-httpd.timerNEXT LEFT LAST                         PASSED    UNIT                ACTIVATESn/a  n/a  五 2022-10-28 23:20:01 CST  40min ago restart-httpd.timer restart-httpd.service
1 timers listed.Pass --all to see loaded but inactive timers, too.┌──[root@liruilongs.github.io]-[~]└─$
复制代码


当然如果是一次性的,我们可以使用 systemc-run 命令来处理, systemc-run 命令可以创建一些临时的 systemd units ,比如常见的临时命令利用 Cgroup 限制资源,


┌──[root@liruilongs.github.io]-[~]└─$systemd-run --on-active=30 systemctl start restart-httpd.serviceRunning timer as unit run-23043.timer.Will run service as unit run-23043.service.
复制代码


使用 systemc-run 可以创建一个在一段时间后执行的 Service unit,这里的命令行会自动包装成 对应的 timer,service 单元


┌──[root@liruilongs.github.io]-[~]└─$journalctl -u restart-httpd.service | tail -n 310月 28 23:20:02 liruilongs.github.io systemd[1]: Started update httpd config , restart httpd service.10月 29 00:21:37 liruilongs.github.io systemd[1]: Starting update httpd config , restart httpd service...10月 29 00:21:38 liruilongs.github.io systemd[1]: Started update httpd config , restart httpd service.┌──[root@liruilongs.github.io]-[~]└─$
复制代码

博文引用资源

http://www.jinbuguo.com/systemd/systemd.html#


https://www.putorius.net/using-systemd-timers.html#


https://blog.csdn.net/weixin_42347739/article/details/112406369


https://silentlad.com/systemd-timers-oncalendar-(cron)-format-explained


用户头像

InfoQ写作平台签约作者,RHCE、CKA认证 2022-01-04 加入

Java 后端一枚,技术不高,前端、Shell、Python 也可以写一点.纯种屌丝,不热爱生活,热爱学习,热爱工作,喜欢一直忙,不闲着。喜欢篆刻,喜欢吃好吃的,喜欢吃饱了晒太阳。

评论

发布
暂无评论
关于Linux中作业调度 crond 和 systemd.timer 使用场景_Linux Kenel_山河已无恙_InfoQ写作社区