用 systemd timer 替代 crontab:Linux 定时任务的更可靠写法

举报
yd_215738027 发表于 2026/10/31 13:14:28 2026/10/31
【摘要】 前言很多人习惯用 crontab 管理 Linux 定时任务:一行配置、简单直接。但任务一多,问题就来了:环境变量和交互式 shell 不一致、任务失败没有日志、无法限制资源、服务器重启期间错过的任务不会补跑。systemd timer 是 systemd 自带的定时机制,用 .timer 单元触发 .service 单元,能很好地解决这些痛点。本文介绍它的基本用法,并与 crontab ...

前言

很多人习惯用 crontab 管理 Linux 定时任务:一行配置、简单直接。但任务一多,问题就来了:环境变量和交互式 shell 不一致、任务失败没有日志、无法限制资源、服务器重启期间错过的任务不会补跑。systemd timer 是 systemd 自带的定时机制,用 .timer 单元触发 .service 单元,能很好地解决这些痛点。本文介绍它的基本用法,并与 crontab 做对比。

一、基本结构:.service + .timer

systemd timer 由两个文件组成:一个 .service 描述"做什么",一个 .timer 描述"什么时候做"。两者同名即可自动关联。

1. 创建服务单元 /etc/systemd/system/backup.service

[Unit]
Description=Daily backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backup
Nice=10

2. 创建定时器单元 /etc/systemd/system/backup.timer

[Unit]
Description=Run backup every day at 02:30

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target

其中 Persistent=true 表示如果机器在计划时间处于关机状态,开机后会立即

补跑一次;RandomizedDelaySec 可以在多台机器上错开执行时间,避免同时压垮后端。

3. 启用并启动

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

注意要启用的是 .timer,而不是 .service。

二、OnCalendar 常见写法

OnCalendar 的格式为 “星期 年-月-日 时:分:秒”,常用例子如下:

  • OnCalendar=hourly:每小时整点
  • OnCalendar=daily:每天 00:00
  • OnCalendar=Mon *-*-* 09:00:00:每周一 09:00
  • OnCalendar=*-*-01 00:00:00:每月 1 号零点
  • OnCalendar=*:0/15:每 15 分钟一次

写完后可以用下面的命令校验表达式,并查看下一次触发时间:

systemd-analyze calendar "Mon *-*-* 09:00:00"

除了日历定时,还有相对定时:OnBootSec=5min 表示开机 5 分钟后执行,OnUnitActiveSec=1h 表示上次执行完成 1 小时后再执行。

三、查看定时器与日志

查看所有定时器、下次与上次触发时间:

systemctl list-timers --all

输出包含 NEXT、LEFT、LAST、PASSED、UNIT、ACTIVATES 等列,一眼就能看出任务是否按预期排期。

手动触发一次任务做测试:

sudo systemctl start backup.service

查看任务执行日志,这是相比 crontab 最大的优势之一:

journalctl -u backup.service -n 50 --no-pager
journalctl -u backup.service --since "today"
journalctl -u backup.timer -f

任务的标准输出和标准错误都会自动进入 journal,无需再手工重定向到日志文件。

四、与 crontab 对比

对比项 crontab systemd timer
配置方式 一行文本,简单 两个单元文件,稍繁琐
日志 默认发邮件或需自行重定向 自动写入 journald
错过的任务 关机期间错过则不补跑 Persistent=true 可补跑
环境 环境变量极简,常踩坑 可用 Environment、EnvironmentFile 明确指定
资源限制 无 可使用 cgroup、Nice、MemoryMax 等
依赖管理 无 可用 After、Requires 声明依赖
随机延迟 需自己写 sleep RandomizedDelaySec 原生支持

五、使用建议

  1. 简单的一次性小任务,crontab 依然够用;需要可观测、可补跑、有依赖关系的任务,优先选 systemd timer。
  2. 服务单元使用 Type=oneshot,并写明 User,避免以 root 运行不必要的任务。
  3. 修改单元文件后一定要 daemon-reload,再 restart 对应的 timer。
  4. 失败排查先看 systemctl status xxx.service,再看 journalctl 详细日志。

总结

systemd timer 把"定时"与"执行"拆开,配合 journald 与 cgroup,让定时任务更可靠、更易排查。迁移成本也不高:把原来 crontab 里的命令放进 ExecStart,把时间表达式改写成 OnCalendar 即可。建议从一个不重要的任务开始尝试,熟悉之后再逐步迁移。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。