systemd 定时器是一种替代传统 cron 的方法,用于安排定时任务。
systemd 定时器由两部分组成:一个 .service
文件和一个 .timer
文件。.service
文件定义了要执行的任务,而 .timer
文件设定了何时执行这个任务。
通常位于 /etc/systemd/system/
或 /usr/lib/systemd/system/
目录下。
1)创建服务文件
创建一个 .service 文件来定义要执行的任务,该文件定义了任务的执行方式。
例如:创建 /etc/systemd/system/backup.service
文件,内容如下,
[Unit]
Description=Run backup script
[Service]
ExecStart=/path/to/backup-script.sh
在这个文件中:
- [Unit] 部分:定义单元的基本信息,包括描述和依赖关系。
Description
字段提供了该服务的简短描述。 - [Service] 部分:定义服务的执行方式。
ExecStart
字段指定了服务启动时要执行的命令或脚本。
2)创建 .timer 文件
.service
文件创建完成后,还需要创建一个定时器文件(.timer
),例如,
创建 /etc/systemd/system/backup
.timer 文件,内容如下,
[Unit]
Description=Run backup script every hour
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
在这个文件中:
- [Unit] 部分:定义单元的基本信息,包括描述和依赖关系。
常见的字段有Description
和After
等。Description
字段提供了该定时器的简短描述。After
:指定该单元需要在另一个单元之后启动 - [Timer] 部分:定义定时器的属性和触发条件。
常见的字段有OnCalendar
、OnBootSec
、OnUnitActiveSec、Persistent
等。OnCalendar
字段指定了定时器的触发时间,这里表示每小时触发一次。OnActiveSec
、OnBootSec
、OnStartupSec
、OnUnitActiveSec
、OnUnitInactiveSec
:定义定时器在特定事件后的触发时间。Persistent
字段表示如果系统在预定时间未启动,定时器将在系统启动时立即触发。AccuracySec
:设置定时器触发的精确度。RandomizedDelaySec
:添加随机延迟,避免多个定时器同时触发。 - [Install] 部分:指定定时器的安装和启用方式。
常见的字段有WantedBy
和RequiredBy
等。WantedBy
字段指定该定时器属于timers.target
,确保定时器在系统启动时被激活。
常见的定时器类型
systemd 定时器支持多种触发条件,下面介绍一些常见的定时器类型及其用法:
OnActiveSec:在定时器激活后经过指定时间触发。适用于需要在特定时间间隔后执行的任务。
示例:
1 |
|
表示在定时器激活后 1 小时触发。
OnBootSec:在系统启动后经过指定时间触发。适用于需要在系统启动后执行的任务。
示例:
1 |
|
表示在系统启动后 30 分钟触发。
OnStartupSec:在 systemd 启动后经过指定时间触发。适用于需要在 systemd 启动后执行的任务。
示例:
1 |
|
表示在 systemd 启动后 15 分钟触发。
OnUnitActiveSec:在关联的服务单元最后一次激活后经过指定时间触发。适用于需要在服务激活后执行的任务。
示例:
1 |
|
表示在关联的服务单元最后一次激活后 1 小时触发。
OnUnitInactiveSec:在关联的服务单元最后一次非活跃后经过指定时间触发。适用于需要在服务停止后执行的任务。
示例:
1 |
|
表示在关联的服务单元最后一次非活跃后 2 小时触发。
OnCalendar:按照指定的时间表触发,类似于 cron 表达式。适用于需要按照特定时间表执行的任务。
示例:
1 |
|
表示每小时触发一次。
定时器单元的工作原理
systemd 定时器单元通过定义触发条件来调度关联的服务单元。当定时器触发时,systemd 会自动启动关联的服务单元。定时器和服务单元通常成对出现,例如 backup.timer
和 backup.service
。
定时器单元的工作流程如下:
- 创建一个服务单元文件,定义任务的执行方式。
- 创建一个定时器单元文件,定义任务的触发条件。
- 启动和启用定时器单元。
- 定时器触发时,systemd 自动执行关联的服务单元。
通过这种方式,systemd 提供了一种灵活且强大的方法来管理和调度定期任务
3)定时器使用相关命令
4)高级定时器配置
复杂的时间表达式
systemd 定时器单元支持使用 OnCalendar
属性定义复杂的时间表达式。OnCalendar
属性类似于 cron 表达式,但更加灵活和强大。它支持多种格式的时间表达式,允许用户精确地定义定时器的触发时间。
常见的时间表达式
基础格式:YYYY-MM-DD HH:MM:SS
例子:2024-06-05 02:30:00
表示在 2024 年 6 月 5 日凌晨 2:30 触发。
通配符格式:*
代表任意值
例子:*-*-01 00:00:00
表示每月的第一天凌晨 0 点触发。
列表格式:使用逗号分隔多个值
例子:Mon,Fri *-*-* 09:00:00
表示每周一和周五早上 9 点触发。
范围格式:使用 ..
定义一个范围
例子:*-*-01..07 00:00:00
表示每月的前七天的凌晨 0 点触发。
重复格式:使用 /
定义重复间隔
例子:*-*-* *:00/15:00
表示每小时的 0 分和 15 分触发。
示例:复杂的时间表达式
每月的第一个星期一:
1 |
|
这表示每月的第一个星期一凌晨 0 点触发。
每周的星期一和星期三:
1 |
|
这表示每周的星期一和星期三凌晨 0 点触发。
每天下午 3 点和晚上 9 点:
1 |
|
这表示每天的下午 3 点和晚上 9 点触发。
使用 OnCalendar 和其他定时器属性
除了 OnCalendar
属性外,systemd 定时器单元还支持其他定时器属性,允许用户定义在特定事件后的触发时间。这些属性可以与 OnCalendar
一起使用,提供更灵活的时间调度。
OnActiveSec
OnActiveSec
属性定义在定时器激活后经过指定时间触发。适用于需要在特定时间间隔后执行的任务。
示例:
1 |
|
表示在定时器激活后 1 小时触发。
OnBootSec
OnBootSec
属性定义在系统启动后经过指定时间触发。适用于需要在系统启动后执行的任务。
示例:
1 |
|
表示在系统启动后 30 分钟触发。
OnStartupSec
OnStartupSec
属性定义在 systemd 启动后经过指定时间触发。适用于需要在 systemd 启动后执行的任务。
示例:
1 |
|
表示在 systemd 启动后 15 分钟触发。
OnUnitActiveSec
OnUnitActiveSec
属性定义在关联的服务单元最后一次激活后经过指定时间触发。适用于需要在服务激活后执行的任务。
示例:
1 |
|
表示在关联的服务单元最后一次激活后 1 小时触发。
OnUnitInactiveSec
OnUnitInactiveSec
属性定义在关联的服务单元最后一次非活跃后经过指定时间触发。适用于需要在服务停止后执行的任务。
示例:
1 |
|
表示在关联的服务单元最后一次非活跃后 2 小时触发。
配置定时器的精确度和随机延迟
为了优化系统性能并避免多个定时器同时触发,systemd 提供了 AccuracySec
和 RandomizedDelaySec
属性,用于配置定时器的精确度和随机延迟。
AccuracySec
AccuracySec
属性设置定时器触发的精确度。较大的精确度值可以减少系统负载,因为定时器触发时间可以稍微偏离设定值。
示例:
1 |
|
表示定时器触发的精确度为 1 分钟,即触发时间可以在预定时间的前后 1 分钟内波动。
RandomizedDelaySec
RandomizedDelaySec
属性添加随机延迟,避免多个定时器同时触发,从而减少系统负载。
示例:
1 |
|
表示在预定触发时间基础上添加最多 30 分钟的随机延迟。
在特定条件下触发定时器
systemd 还支持在特定条件下触发定时器,例如系统空闲时或网络连接时。通过使用 Condition
和 Assert
属性,可以实现更灵活的任务调度。
示例:在系统空闲时触发定时器
创建一个定时器单元文件,在系统空闲时触发任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
在这个示例中,Type=idle
表示在系统空闲时执行任务。
示例:在网络连接时触发定时器
创建一个定时器单元文件,在网络连接时触发任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
在这个示例中,After=network-online.target
表示在网络连接后执行任务。
管理和调试 systemd 定时器
管理 systemd 定时器
管理 systemd 定时器涉及定时器单元的启动、停止、启用、禁用和查看状态等操作。
要启动定时器单元,可以使用以下命令:
1 |
|
这将立即启动定时器并按照配置的时间计划执行关联的服务单元。
要停止定时器单元,可以使用以下命令:
1 |
|
这将停止定时器,关联的服务单元将不再按计划触发。
要启用定时器单元,使其在系统启动时自动启动,可以使用以下命令:
1 |
|
要禁用定时器单元,使其不再在系统启动时自动启动,可以使用以下命令:
1 |
|
要查看定时器单元的状态,可以使用以下命令:
1 |
|
这个命令会显示定时器的当前状态、下次触发时间、最近一次触发时间以及相关日志。
要列出系统中所有已激活的定时器及其下次触发时间,可以使用以下命令:
1 |
|
这个命令会列出所有定时器单元,包括激活时间和下次触发时间,便于用户全面了解系统中的定时任务。
查看定时器日志
systemd 使用 journald 记录日志信息,用户可以通过查看日志来调试和监控定时器的执行情况。
要查看定时器关联的服务单元的日志,可以使用以下命令:
1 |
|
这个命令会显示服务单元的所有日志信息,包括启动、停止和执行过程中产生的日志。
要查看定时器单元本身的日志,可以使用以下命令:
1 |
|
这个命令会显示定时器单元的所有日志信息,包括触发时间和相关事件。
要实时查看定时器或服务单元的日志,可以使用 -f
选项,例如:
1 |
|
这个命令会实时显示服务单元的日志信息,便于用户监控任务的执行情况。
调试定时器问题
在使用 systemd 定时器时,可能会遇到一些问题。通过以下方法,可以有效地排查和解决定时器相关的问题。
首先,检查定时器和服务单元文件的配置是否正确。确保 OnCalendar
等属性设置合理,并且文件路径和命令正确无误。
使用 systemctl status
命令检查定时器和服务单元的状态,查看是否有错误信息或异常情况:
1 2 |
|
使用 journalctl
命令查看定时器和服务单元的日志,查找错误信息和警告:
1 2 |
|
日志中可能包含错误信息、失败原因和调试信息,有助于快速定位和解决问题。
手动启动关联的服务单元,确保其能够正常执行:
sudo systemctl start backup.service
如果服务单元无法正常执行,检查脚本或命令是否存在问题,确保其在独立运行时能够正常完成任务。
在服务单元文件中设置 Environment=SYSTEMD_LOG_LEVEL=debug
,以启用详细的 debug 日志级别,有助于深入分析和调试问题。
编辑服务单元文件 backup.service
,添加 Environment
行:
1 2 3 4 5 6 |
|
保存文件后,重新加载 systemd 配置:
1 2 |
|
查看 debug 日志:
1 |
|