https://mp.weixin.qq.com/s/EJGz2koxuvLzJhnKXUBiAA
任何一本 Linux 书籍都会讲到 Cron 和 At 两个命令,都是定时执行命令,不同的是 at 执行一次,cron 周期性执行。
我们常见的 cron 应该是有这 3 种:
- vixie cron
- 支持 @yearly @monthly 等关键字
- @reboot 关键字,用于系统启动之后执行
- 环境变量
- crontab
- 邮件通知
- 日志记录
- 多任务并发
- anacron
- systemd-cron
cron 是一个知名的定时任务服务,大多数 UNIX / Linux 系统都已经预装了。
cron 包包含两个可执行文件:
- /usr/bin/cron 后台程序(系统服务),定期执行命令或脚本,可精确到分钟
- /usr/bin/crontab 管理定时任务(增删改查),每个用户都有自己的 crontab 文件
检查是否安装:
which crontab
cron
定时任务定义语法(分时日月周):
* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of the week (0 - 6) (Sunday is both 0 and 7)
| | | ------- Month (1 - 12)
| | --------- Day of the month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)
比如:0 23 * * * bash /path/to/backup-script.sh 表示每晚 11 点运行一个备份脚本。
,表示多个值-表示一个范围/表示每隔多长时间
问题:cron 只能执行简单任务,不支持交互、错误处理、日志等功能。
crontab
crontab -e:编辑crontab -l:列出crontab -r:删除
脚本中可以使用 TZ 指定时区,如下(没用实操过):
TZ=UTC
0 0 * * * /path/to/backup-script.sh
配置文件
在大多数 UNIX 和类 UNIX 系统中,cron 会从多个文件中读取定时任务的配置。这些文件通常包括:
/etc/crontab系统级,需要指定执行用户/etc/cron.d//var/spool/cron/每个用户有一个自己名字的文件
anacron
好像 CentOS 中默认安装的是这货。
和 cron 相比,是基于时间间隔来的,也就是说发现距离上一次执行的时间超过了定义的间隔就再次执行。
cron 是指定到具体的时间点,如果那个时间点系统关机了,这个任务就错误了,不会执行。
提供 anacron,anacrontab 两个命令。
anacron [-s] [-f] [-n] [-d] [-t] [-S] [-T] [-u] [-r] [-V] [job] ...
-s:以非安静模式运行,输出详细信息。
-f:强制运行所有作业,忽略上次运行时间间隔。
-n:以模拟模式运行,输出将要运行的作业信息。
-d:以调试模式运行,输出调试信息。
-t:测试配置文件中所有作业是否可运行。
-S:停止所有正在运行的作业。
-T:将所有正在运行的作业的运行时间戳更新为当前时间。
-u:指定运行作业的用户。
-r:重新载入配置文件。
-V:显示版本信息。
cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
systemd-cron
Systemd 这个大管家引入之后,当然定时任务这点小事也可以顺带着就给做了。
采用和系统服务相同格式的 unit file 来声明定时任务,可以定义依赖关系,精度到毫秒。从各方面来看都应该强大得多,但是大多数使用场景下简单的 cron 足够了,所以我还没有使用过 systemd-cron。
systemd-cron 也提供一个 crontab 命令,可以兼容原来的语法。
systemctl list-units | grep cron
cron.service loaded active running Regular background program processing daemon
anacron.timer loaded active waiting Trigger anacron every hour
测试
# ll /opt/cron_test.sh /etc/cron.d/test
-rw-r--r-- 1 root root 33 Jun 8 12:53 /etc/cron.d/test
-rwxr-xr-x 1 root root 184 Jun 8 12:52 /opt/cron_test.sh
# cat /etc/cron.d/test
* * * * * root /opt/cron_test.sh
# cat /opt/cron_test.sh
#!/bin/bash
{
echo "===================="
echo "TIME: $(date '+%F %T')"
echo "USER: $(whoami)"
echo "PWD : $(pwd)"
echo "PATH: $PATH"
} >> /tmp/cron_test.log 2>&1
# tail -f /tmp/cron_test.log
====================
TIME: 2026-06-08 12:54:01
USER: root
PWD : /root
PATH: /usr/bin:/bin
^C
# journalctl -u cron
-- No entries --
# journalctl -u crond | grep test
Jun 08 12:54:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376687]: (root) CMD (/opt/cron_test.sh)
Jun 08 12:54:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376686]: (root) CMDEND (/opt/cron_test.sh)
Jun 08 12:55:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376701]: (root) CMD (/opt/cron_test.sh)
Jun 08 12:55:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376700]: (root) CMDEND (/opt/cron_test.sh)
Jun 08 12:56:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376711]: (root) CMD (/opt/cron_test.sh)
Jun 08 12:56:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376710]: (root) CMDEND (/opt/cron_test.sh)
Jun 08 12:57:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376750]: (root) CMD (/opt/cron_test.sh)
Jun 08 12:57:01 iZt4nerpnxvn37c1tlx3brZ CROND[1376749]: (root) CMDEND (/opt/cron_test.sh)