Skip to Content
文档运维系统管理定时任务

定时任务

定时任务允许你在指定的时间自动执行命令或脚本。Ubuntu 26.04 支持传统的 cron 和更现代的 systemd timers 两种方式。

crontab 基本用法

管理 crontab

# 编辑当前用户的 crontab crontab -e # 查看当前用户的 crontab crontab -l # 删除当前用户的 crontab crontab -r # 编辑其他用户的 crontab(需要 root 权限) sudo crontab -u username -e # 查看其他用户的 crontab sudo crontab -u username -l

cron 时间语法

cron 表达式由 5 个时间字段组成:

┌──────── 分钟 (0-59) │ ┌────── 小时 (0-23) │ │ ┌──── 日 (1-31) │ │ │ ┌── 月 (1-12) │ │ │ │ ┌ 星期 (0-7, 0和7都表示周日) │ │ │ │ │ * * * * * command

特殊字符

字符说明示例
*任意值* * * * * 每分钟
,多个值1,15,30 * * * * 第1、15、30分钟
-范围1-5 * * * * 第1到5分钟
/步长*/10 * * * * 每10分钟

常见示例

# 每分钟执行 * * * * * /path/to/script.sh # 每小时执行(整点) 0 * * * * /path/to/script.sh # 每天凌晨 3 点执行 0 3 * * * /path/to/script.sh # 每天凌晨 3 点 30 分执行 30 3 * * * /path/to/script.sh # 每周一凌晨 2 点执行 0 2 * * 1 /path/to/script.sh # 每月 1 号凌晨执行 0 0 1 * * /path/to/script.sh # 每 5 分钟执行 */5 * * * * /path/to/script.sh # 每小时的第 15 和 45 分钟执行 15,45 * * * * /path/to/script.sh # 工作日(周一到周五)每天 9 点执行 0 9 * * 1-5 /path/to/script.sh # 每天 8 点到 18 点,每小时执行 0 8-18 * * * /path/to/script.sh # 每半年执行(1月和7月的1号) 0 0 1 1,7 * /path/to/script.sh

特殊关键字

# 等价写法 @reboot # 系统启动时执行 @yearly # 每年执行 = 0 0 1 1 * @monthly # 每月执行 = 0 0 1 * * @weekly # 每周执行 = 0 0 * * 0 @daily # 每天执行 = 0 0 * * * @hourly # 每小时执行 = 0 * * * * # 使用示例 @reboot /opt/myapp/start.sh @daily /usr/local/bin/daily-backup.sh

cron 实用技巧

环境变量

cron 运行环境与用户 Shell 环境不同,PATH 等变量可能不完整:

# 在 crontab 顶部设置环境变量 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO=admin@example.com # 或在命令中使用完整路径 0 3 * * * /usr/bin/rsync -av /source/ /backup/

日志记录

# 将输出重定向到日志文件 0 3 * * * /path/to/script.sh >> /var/log/myscript.log 2>&1 # 丢弃所有输出 0 3 * * * /path/to/script.sh > /dev/null 2>&1 # 只记录错误 0 3 * * * /path/to/script.sh > /dev/null 2>> /var/log/myscript-error.log

邮件通知

# 在 crontab 中设置邮件接收者 MAILTO=admin@example.com # 禁用邮件通知 MAILTO=""

查看 cron 日志

# 通过 journalctl 查看 journalctl -u cron.service # 或查看 syslog grep CRON /var/log/syslog

系统级 cron 目录

Ubuntu 提供了几个预定义的 cron 目录:

# 将脚本放入相应目录即可自动执行 ls /etc/cron.hourly/ # 每小时 ls /etc/cron.daily/ # 每天 ls /etc/cron.weekly/ # 每周 ls /etc/cron.monthly/ # 每月
# 放入脚本并确保有执行权限 sudo cp myscript.sh /etc/cron.daily/ sudo chmod +x /etc/cron.daily/myscript.sh

系统级 cron 配置文件 /etc/crontab:

cat /etc/crontab
SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

systemd timers

systemd timers 是 cron 的现代替代方案,提供了更精确的时间控制和更好的日志支持。

查看现有 timers

# 列出所有活动的 timers systemctl list-timers --all # 输出示例: # NEXT LEFT LAST PASSED UNIT ACTIVATES # Tue 2026-03-24 06:00:00 CST 2h left Mon 2026-03-23 06:00:00 CST 22h ago apt-daily.timer apt-daily.service

创建自定义 timer

创建 timer 需要两个文件:一个 .service 文件和一个 .timer 文件。

步骤 1:创建服务文件

sudo nano /etc/systemd/system/my-backup.service
[Unit] Description=Daily Backup Job [Service] Type=oneshot ExecStart=/usr/local/bin/daily-backup.sh User=root StandardOutput=journal StandardError=journal

步骤 2:创建 timer 文件

sudo nano /etc/systemd/system/my-backup.timer
[Unit] Description=Run Daily Backup at 3 AM [Timer] OnCalendar=*-*-* 03:00:00 Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.target

步骤 3:启用 timer

sudo systemctl daemon-reload sudo systemctl enable --now my-backup.timer # 验证 systemctl list-timers | grep my-backup # 手动触发一次测试 sudo systemctl start my-backup.service # 查看执行日志 journalctl -u my-backup.service

OnCalendar 时间表达式

# 每天 3 点 OnCalendar=*-*-* 03:00:00 # 每周一 9 点 OnCalendar=Mon *-*-* 09:00:00 # 每月 1 号 OnCalendar=*-*-01 00:00:00 # 工作日每天 8 点 OnCalendar=Mon..Fri *-*-* 08:00:00 # 每 15 分钟 OnCalendar=*:0/15 # 每小时 OnCalendar=hourly # 每天 OnCalendar=daily # 每周 OnCalendar=weekly

验证时间表达式:

# 测试表达式,查看未来的触发时间 systemd-analyze calendar "Mon..Fri *-*-* 08:00:00" systemd-analyze calendar "*:0/15"

基于事件的 timer

除了基于日历时间,还可以基于事件触发:

[Timer] # 系统启动后 5 分钟执行 OnBootSec=5min # 上次执行完成后 1 小时再执行 OnUnitActiveSec=1h # 组合使用 OnBootSec=10min OnUnitActiveSec=1h

瞬时 timer(一次性延时执行)

# 30 分钟后执行一个命令 systemd-run --on-active=30m /usr/local/bin/task.sh # 在指定时间执行 systemd-run --on-calendar="2026-03-25 10:00:00" /usr/local/bin/task.sh

cron 与 systemd timers 对比

特性cronsystemd timers
配置复杂度简单,一行搞定需要两个文件
日志需要手动配置自动集成 journalctl
依赖管理不支持支持服务依赖
精度最小单位为分钟可以精确到秒
错过的任务不执行Persistent=true 会补执行
资源控制不支持支持 cgroup 资源限制
随机延迟不支持RandomizedDelaySec

最佳实践

  1. 简单定时任务用 cron,复杂的用 systemd timers。
  2. 始终记录日志,方便排查问题。
  3. 使用完整路径,避免 PATH 问题。
  4. 避免任务重叠,长时间运行的任务应加锁:
# 使用 flock 防止任务重叠 * * * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script.sh
  1. 测试后再部署,先手动执行脚本确认无误。
Last updated on