用于调度任务的 systemd 定时器

运维 系统运维
systemd 提供定时器有一段时间了,定时器替代了 cron 功能,这一特性值得看看。本文将向你介绍在系统启动后如何使用 systemd 中的定时器来运行任务,并在此后重复运行。这不是对 systemd 的全面讨论,只是对此特性的一个介绍。

[[407576]]

systemd 提供定时器有一段时间了,定时器替代了 cron 功能,这一特性值得看看。本文将向你介绍在系统启动后如何使用 systemd 中的定时器来运行任务,并在此后重复运行。这不是对 systemd 的全面讨论,只是对此特性的一个介绍。

快速回顾:cron、anacron 与 systemd

cron 可以以几分钟到几个月或更长时间的粒度调度运行一个任务。设置起来相对简单,它只需要一个配置文件。虽然配置过程有些深奥,但一般用户也可以使用。

然而,如果你的系统在需要执行的时间没有运行,那么 cron 会失败。

anacron 克服了“系统没有运行”的问题。它确保任务将在你的系统再次启动时执行。虽然它旨在给管理员使用,但有些系统允许普通用户访问 anacron。

但是,anacron 的执行频率不能低于每天一次。

cron 和 anacron 都存在执行上下文一致性的问题。必须注意任务运行时有效的环境与测试时使用的环境完全相同。必须提供相同的 shell、环境变量和路径。这意味着测试和调试有时会很困难。

systemd 定时器提供了 cron 和 anacron 二者的优点,允许调度到分钟粒度。确保在系统再次运行时执行任务,即使在预期的执行时间内系统处于关闭状态。它对所有用户都可用。你可以在它将要运行的环境中测试和调试执行。

但是,它的配置更加复杂,至少需要两个配置文件。

如果你的 cron 和 anacron 配置可以很好地为你服务,那么可能没有理由改变。但是 systemd 至少值得研究,因为它可以简化任何当前的 cron/anacron 工作方式。

配置

systemd 定时器执行功能至少需要两个文件。这两个是“定时器单元timer unit”和“服务单元service unit”。(其执行的)“动作”不仅仅是简单的命令,你还需要一个“作业”文件或脚本来执行必要的功能。

定时器单元文件定义调度表,而服务单元文件定义执行的任务。有关的更多详细信息请参考 man systemd.timer 中提供的 .timer 单元。服务单元的详细信息可在 man systemd.service 中找到。

单元文件存放在几个位置(在手册页中有列出)。然而,对于普通用户来说,最容易找到的位置可能是 ~/.config/systemd/user。请注意,这里的 user 是字符串 user

示例

此示例是一个创建用户调度作业而不是(以 root 用户身份运行的)系统调度作业的简单示例。它将消息、日期和时间打印到文件中。

1、首先创建一个执行任务的 shell 脚本。在你的本地 bin 目录中创建它,例如在 ~/bin/schedule-test.sh 中。

创建文件:

  1. touch ~/bin/schedule-test.sh

然后将以下内容添加到你刚刚创建的文件中:

  1. #!/bin/sh
  2. echo "This is only a test: $(date)" >> "$HOME/schedule-test-output.txt"

记住赋予你的 shell 脚本执行权限。

2、创建 .service 单元调用上面的脚本。在以下位置创建目录与文件:~/.config/systemd/user/schedule-test.service

  1. [Unit]
  2. Description=A job to test the systemd scheduler
  3.  
  4. [Service]
  5. Type=simple
  6. ExecStart=/home/<user>/bin/schedule-test.sh
  7.  
  8. [Install]
  9. WantedBy=default.target

请注意 <user> 应该是你的家目录地址,但是单元文件路径名中的 user 实际上是字符串 user

ExecStart 应该提供一个没有变量的绝对地址。例外情况是,对于用户单元文件,你可以用 %h 替换 $HOME。换句话说,你可以使用:

  1. ExecStart=%h/bin/schedule-test.sh

这仅用于用户单元文件,而不适用于系统服务,因为在系统环境中运行时 %h 总是返回 /root。其他特殊符号可在 man systemd.unit 的 SPECIFIERS 中找到。因为它超出了本文的范围,所以这就是我们目前需要了解的关于特殊符号的全部内容。

3、创建一个 .timer 单元文件,该文件实际上调度你创建的 .service 单元文件。在 .service 单元文件相同位置创建它:~/.config/systemd/user/schedule-test.timer。请注意,文件名仅在扩展名上有所不同,例如一个是 .service,一个是 .timer

  1. [Unit]
  2. Description=Schedule a message every 1 minute
  3. RefuseManualStart=no # Allow manual starts
  4. RefuseManualStop=no # Allow manual stops
  5.  
  6. [Timer]
  7. #Execute job if it missed a run due to machine being off
  8. Persistent=true
  9. #Run 120 seconds after boot for the first time
  10. OnBootSec=120
  11. #Run every 1 minute thereafter
  12. OnUnitActiveSec=60
  13. #File describing job to execute
  14. Unit=schedule-test.service
  15.  
  16. [Install]
  17. WantedBy=timers.target

请注意,这个 .timer 单元文件使用了 OnUnitActiveSec 来指定调度表。OnCalendar 选项更加灵活。例如:

  1. # run on the minute of every minute every hour of every day
  2. OnCalendar=*-*-* *:*:00
  3. # run on the hour of every hour of every day
  4. OnCalendar=*-*-* *:00:00
  5. # run every day
  6. OnCalendar=*-*-* 00:00:00
  7. # run 11:12:13 of the first or fifth day of any month of the year
  8. # 2012, but only if that day is a Thursday or Friday
  9. OnCalendar=Thu,Fri 2012-*-1,5 11:12:13

有关 OnCalendar 的更多信息参见 这里

4、所有的部件都已就位,但你应该进行测试,以确保一切正常。首先,启用该用户服务:

  1. $ systemctl --user enable schedule-test.service

这将导致类似如下的输出:

  1. Created symlink /home/<user>/.config/systemd/user/default.target.wants/schedule-test.service /home/<user>/.config/systemd/user/schedule-test.service.

现在执行测试工作:

  1. $ systemctl --user start schedule-test.service

检查你的输出文件($HOME/schedule-test-output.txt),确保你的脚本运行正常。应该只有一个条目,因为我们还没有启动定时器。必要时进行调试。如果你需要更改 .service 单元文件,而不是更改它调用的 shell 脚本,请不要忘记再次启用该服务。

5、一旦作业正常运行,通过为服务启用、启动用户定时器来实时调度作业:

  1. $ systemctl --user enable schedule-test.timer
  2. $ systemctl --user start schedule-test.timer

请注意,你已经在上面的步骤 4 中启动、启用了服务,因此只需要为它启用、启动定时器。

enable 命令会产生如下输出:

  1. Created symlink /home/<user>/.config/systemd/user/timers.target.wants/schedule-test.timer /home/<user>/.config/systemd/user/schedule-test.timer.

start 命令将只是返回命令行界面提示符。

其他操作

你可以检查和监控服务。如果你从系统服务收到错误,下面的第一个命令特别有用:

  1. $ systemctl --user status schedule-test
  2. $ systemctl --user list-unit-files

手动停止服务:

  1. $ systemctl --user stop schedule-test.service

永久停止并禁用定时器和服务,重新加载守护程序配置并重置任何失败通知:

  1. $ systemctl --user stop schedule-test.timer
  2. $ systemctl --user disable schedule-test.timer
  3. $ systemctl --user stop schedule-test.service
  4. $ systemctl --user disable schedule-test.service
  5. $ systemctl --user daemon-reload
  6. $ systemctl --user reset-failed

总结

本文以 systemd 定时器为出发点,但是 systemd 的内容远不止于此。这篇文章应该为你提供一个基础。你可以从 Fedora Magazine systemd 系列 开始探索更多。 

 

责任编辑:庞桂玉 来源: Linux中国
相关推荐

2021-04-18 12:12:29

systemd定时器系统运维

2018-11-02 08:10:58

Linuxsystemd定时器

2018-12-03 12:20:52

Systemd定时器Linux

2023-12-11 09:50:35

Linux定时器

2010-07-28 15:56:22

FlexTimer定时

2009-11-11 10:14:10

linux定时器操作系统

2023-12-26 07:44:00

Spring定时调度

2022-11-02 11:40:16

Flowable定时器流程

2023-11-16 09:30:27

系统任务

2023-01-10 13:53:21

Linux定时器

2011-02-23 10:20:45

2009-04-12 08:51:50

Symbian诺基亚移动OS

2021-03-31 08:33:17

SysTick定时器SysTick定时器

2013-07-29 10:10:40

TCP协议TCP定时器TCP

2021-08-26 06:29:47

STM32DWT数据观察点触发

2021-07-27 16:01:29

高并发定时器高性能

2023-08-02 09:26:03

软件定时器鸿蒙

2009-06-18 11:07:17

Spring fram

2017-03-06 14:08:38

JavaScript单线程setTimeout

2023-02-28 18:09:53

Javascript定时器
点赞
收藏

51CTO技术栈公众号