timer 定时器

发布时间: 更新时间: 总字数:1469 阅读时间:3m 作者: IP上海 分享 网址

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

AccuracySecRandomizedDelaySec 的目的互补,一般情况下,若要控制任务精确的执行时间点,可使用如下方式:

# 立刻触发定时任务
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

参考

  1. https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数