Systemd timer 单元适合在基于 systemd 的 Linux 发行版中替代 crontab,提供更精确的触发控制和统一的日志管理。迁移时需注意语法差异,建议在测试环境验证后再上线。
先说结论:Systemd timer 是 cron 的现代化替代方案,适合需要依赖管理、精确秒级触发或统一日志审计的场景。
- 适合:基于 systemd 的 Linux 系统(如 Ubuntu 16.04+、CentOS 7+、Debian 8+)。
- 重点看:.timer 单元配置文件中的 OnCalendar 语法与 cron 表达式的区别。
- 别忽略:环境变量和 working directory 需要在 .service 单元中显式声明,不像 cron 那样隐式加载。
命令速用版
以下命令用于查看和管理 timer 状态,替代 cron 的 crontab -l 和 service restart 操作。
systemctl list-timers `--all` # 列出所有 timer 及下次触发时间
systemctl enable `--now` foo.timer # 启用并立即启动定时任务
systemctl status foo.timer # 查看 timer 状态
journalctl -u foo.service # 查看对应服务的日志为什么会这样
Systemd timer 通过集成到 init 系统中解决了 cron 守护进程独立运行导致的日志分散和问题隔离性差。
cron 守护进程独立于系统服务管理器,日志通常写入 /var/log/cron 或 syslog,排查时需要切换上下文。Systemd timer 作为 systemd 的一部分,触发的是 .service 单元,日志统一进入 journal,支持按单元过滤。此外,cron 最小精度为分钟,Systemd timer 支持秒级精度和单调计时器(如开机后延迟触发)。
分步处理
迁移 cron 任务到 systemd timer 需要创建对应的 service 单元和 timer 单元。
1. 创建 service 单元:在 /etc/systemd/system/ 下创建 foo.service,定义执行命令。
[Unit]
Description=Run foo script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/foo.sh
User=root2. 创建 timer 单元:创建 foo.timer,定义触发时间。
[Unit]
Description=Run foo script daily
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target3. 启用任务:使用 systemctl 启用 timer,无需重启守护进程。
systemctl daemon-reload
systemctl enable `--now` foo.timer4. 移除旧 cron:确认新任务生效后,编辑 crontab 注释掉旧任务。
crontab -e怎么验证是否生效
通过 list-timers 查看下次触发时间,通过 journalctl 查看历史执行记录。
执行 systemctl list-timers foo.timer 确认 LAST 和 NEXT 列有具体时间。执行 journalctl -u foo.service 查看是否有最近的任务执行日志。如果任务未触发,检查 systemctl status foo.timer 是否处于 active (waiting) 状态。
常见坑
环境变量缺失和时区设置是迁移过程中最容易出错的地方。
cron 默认加载部分环境变量,而 systemd service 默认环境变量极少,需要在 [Service] 段使用 Environment 或 EnvironmentFile 显式配置。OnCalendar 默认使用系统本地时间,若服务器时区变更可能导致触发时间偏移,建议确认 timedatectl 设置。
常见问题
Systemd timer 精度比 cron 高吗
是的,Systemd timer 支持秒级精度,而 cron 最小单位是分钟。
可以同时运行 cron 和 systemd timer 吗
可以,两者互不冲突,但建议避免同一任务被双重调度。
迁移后任务不执行怎么办
检查 timer 是否 enable,service 类型是否为 oneshot,以及 ExecStart 路径是否可执行。
参考来源
systemd.timer - systemd 官方文档,freedesktop.org,https://www.freedesktop.org/software/systemd/man/systemd.timer.html