Systemd的Timer units
支持设置定时任务,可以用来取代Linux的cron
,但比cron
更强大。
介绍
- Linux 定时任务功能 crontab
- Timer 的优点如下
- 时间支持:us (微秒)、ms (毫秒)、s (秒)、m (分)、h (时)、d (日)、w (周);
cron
支持分、时、日、月、周 - 支持对定时任务做资源限制
- 支持重复不执行,若发现任务再执行,则不在此执行
- 支持使用 journal 查看日志
- 缺点:使用复杂
- 帮助文档:
man systemd.timer
使用
# 启动定时器
sudo systemctl start xxx.timer
# 查看定时器的状态
systemctl status xxx.timer
# 关闭定时器
sudo systemctl stop xxx.timer
# 开机自动启动定时器
sudo systemctl enable xxx.timer
# 关闭开机自动启动定时器
sudo systemctl disable xxx.timer
# 查看所有正在运行的定时器
systemctl list-timers
查看定时任务的执行情况
$ systemctl list-timers --no-pager
NEXT LEFT LAST PASSED UNIT ACTIVATES
...
Mon 2023-10-30 06:10:… 9h left Sun 2023-10-29 09:39:… 11h ago apt-daily.timer apt-daily.service
参数说明:
NEXT
下次自动触发的时间点LEFT
现在距离下次自动触发剩余的时间LAST
上次自动触发的时间点PASSED
距离上次自动触发任务已经过去的时间UNIT
当前是定时器的名字ACTIVATES
该定时器所触发的任务,使用 systemctl list-timers
查看时不显示
查看 timer 对应的 service
$ systemctl status apt-daily.timer
● apt-daily.timer - Daily apt download activities
Loaded: loaded (/lib/systemd/system/apt-daily.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Sun 2023-10-29 20:45:59 CST; 2min 14s ago
Trigger: Mon 2023-10-30 06:10:53 CST; 9h left
Triggers: ● apt-daily.service
$ systemctl cat apt-daily.timer
# /lib/systemd/system/apt-daily.timer
[Unit]
Description=Daily apt download activities
[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
Persistent=true
[Install]
WantedBy=timers.target
说明
Trigger
查看触发的时间Triggers
查看触发的 service
- 不指定
参数配置
配置文件的 [Timer]
section 指定
通用参数
# 配置 timer 触发的 service,默认是同名的 .service 单元
Unit=xxx.service
# 定时器启动后,10分钟后才可以第一次触发该定时任务
OnActiveSec=10m
# 每次执行完任务后,15分钟后才可以再次触发该定时任务
OnUnitInactiveSec=15m
# 定时器触发事件后,允许推迟0-10分钟触发该定时任务;用来避免不同的定时任务频繁唤醒CPU,将靠近的定时任务合并在一起执行
# 默认值 1min
AccuracySec=10m
# 定义触发任务后的可以延迟的时间;用来避免不同定时任务在同一时间点被触发,造成 CPU 等资源的竞争
# 注意:触发任务的时间点并不一定时任务的执行时间
# 默认值 0,即立即执行
RandomizedDelaySec=1m
# 仅对 OnCalendar 时有效,默认值 no
# 当设置 yes 时,会将上次执行任务的时间保存在磁盘上,若定时器再次被启动时,则可立即判断是否要执行丢失的任务,保存的文件:/var/lib/systemd/timers
Persistent=yes/no
# 若系统休眠,则自动唤醒系统
WakeSystem
AccuracySec
和 RandomizedDelaySec
的目的互补,一般情况下,若要控制任务精确的执行时间点,可使用如下方式:
# 立刻触发定时任务
AccuracySec = 1ms
# 触发时刻立刻执行该任务
RandomizedDelaySec = 0
单调定时规则
基于指定时间单调增加的定时规则
OnBootSec
内核启动多久后触发- 若
OnBootSec
配置的时间比较短时,可能出现超期现象,若任务超期时,检测到时会立即执行;同 OnStartupSec
OnStartupSec
systemd 启动(pid 为 1 的进程)多久后触发OnActiveSec
该定时器启动多久后触发任务OnUnitActiveSec
从上次任务触发的时间开始算起多久后触发- 若该任务仍有处于运行中的状态,此时不会再次触发任务
Service
文件中 Type=oneshot
的任务不显示 Active 状态,若需要可配置 RemainAfterExit
实现
OnCalendar 定时规则
OnCalendar
是基于日历(Calendar)
的定时规则,比 cron 的 时分日月周
更加灵活
systemd timer 支持的时间,更多时间参考
OnUnitActiveSec=1h
表示一小时执行一次任务OnUnitActiveSec=*-*-* 02:00:00
表示每天凌晨两点执行OnUnitActiveSec=Mon *-*-* 02:00:00
表示每周一凌晨两点执行
多个时间可以结合,且顺序无关,支持使用如下名称查看:
$ systemd-analyze calendar Sat,Mon..Wed
Original form: Sat,Mon..Wed
Normalized form: Mon..Wed,Sat *-*-* 00:00:00
Next elapse: Mon 2023-10-30 00:00:00 CST
(in UTC): Sun 2023-10-29 16:00:00 UTC
From now: 2h 38min left
$ systemd-analyze calendar "Mon *-05~07/1"
限制定时任务的资源
通过 service
配置文件配置资源控制指令或直接使用 Slice
定义的 CGroup
,示例
[Service]
MemoryLimit=20M
# 或
[Service]
Slice=xxx.slice
/usr/lib/systemd/system/xxx.slice
的示例
[Unit]
Description=Limited resources Slice
DefaultDependencies=no
Before=slices.target
[Slice]
CPUQuota=10%
MemoryLimit=200M
扩展
- 用户级定时任务
- 同系统级别,配置文件目录
~/.config/systemd/user/
- 使用
systemctl --user xx
操作
systemd-run
一次性定时任务
示例
$ cat <<EOF > /usr/local/bin/who-login
#!/bin/bash
echo "$(who)" >> /tmp/who-login.log
EOF
$ chmod 755 /usr/local/bin/who-login
- 创建
/usr/lib/systemd/system/who-login.service
cat <<EOF > /usr/lib/systemd/system/who-login.service
[Unit]
Description=who login service
[Service]
ExecStart=/usr/local/bin/who-login
[Install]
WantedBy=multi-user.target
EOF
- 创建
/usr/lib/systemd/system/who-login.timer
cat <<EOF > /usr/lib/systemd/system/who-login.timer
[Unit]
Description=Run who login every 1min
[Timer]
OnUnitActiveSec=1m
# option, default is who-login
Unit=who-login
[Install]
WantedBy=timers.target
EOF
$ systemctl daemon-reload
$ systemctl start who-login.service
$ systemctl enable who-login.timer
Created symlink /etc/systemd/system/timers.target.wants/who-login.timer → /lib/systemd/system/who-login.timer.
$ systemctl status who-login.timer
● who-login.timer - Run who login every 1min
Loaded: loaded (/lib/systemd/system/who-login.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Sun 2023-10-29 21:17:24 CST; 2min 28s ago
Trigger: Sun 2023-10-29 21:20:50 CST; 57s left
Triggers: ● who-login.service