我们每天早晨都要起床吃饭,然后上班工作赚钱,如此往复,Linux操作系统也一样,总有一些任务需要定时执行,例如日志轮替、备份、清理垃圾数据等。驱动Linux定时任务系统背后的功臣是 crond 服务。在安装完操作系统后,系统默认会安装 crond 服务,并且默认是开机自动启动,可以检查一下它的工作状态。
# systemctl status crond
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2022-12-02 19:56:36 EST; 5 days ago
本文首先带您了解一下都有哪些 cron 配置文件,然后了解一下 cron 如何表示各种周期性时间,以及如何添加到cron中。
cron定时任务
cron 配置文件
Linux系统中的各种服务都有自己的配置文件,cron 服务也不例外,与它相关的配置文件和目录包括:
- /etc/crontab 全局配置文件
- /etc/cron.d/
- /var/spool/cron/ 用户配置文件
- /etc/cron.deny
- /etc/cron.hourly/
- /etc/cron.daily/
- /etc/cron.weekly/
- /etc/cron.monthly/
cron 服务会扫描 /etc/crontab 文件,以及 /var/spool/cron/ 目录下的配置文件,并且按照指定的周期去执行它们。不过 /etc/crontab 文件有一个user-name字段,它用来描述运行脚本的用户,而/var/spool/cron/ 目录下的配置文件是以用户名命名的,因此不需要用户名字段。
不推荐直接编辑/etc/crontab文件,而应该使用后面介绍的crontab -e命令添加定时任务。
注意:不同Linux发行版 cron服务的配置文件的内容并不一样,不过原理都差不多,本文实验环境如下所示:
操作系统:AlmaLinux 8.6
客户端:Windows 11
SSH客户端:MobaXterm 21.1
使用的用户:root
同时适用于RockyLinux8、AlmaLinux8、CentOS8,因为它们都是基于RedHat Linux。Ubuntu等操作系统原理也是类似的。
crontab 文件
初始状态下的/etc/crontab文件只是介绍了一下配置语法,没有任何定时任务。
/etc/crontab配置文件
定时任务都是以 “分钟 小时 天 月 周 命令” 形式呈现:
- 分钟:描述第几分钟运行任务,范围0-59。例如如果该字段等于5,那么将在第5分钟运行任务。
- 小时:描述第几小时运行任务,范围0-23。例如如果该字段等于3,那么将在凌晨3点运行任务。
- 天:描述第几天运行任务,范围1-31。例如如果该字段等于3,那么将在第3天运行任务。
- 月:描述几月运行任务,范围1-12。例如如果该字段等于3,那么将在3月运行任务。
- 周:描述周几运行任务,范围0-7。例如如果该字段等于3,那么将在星期三运行任务。
- 命令:任务脚本。
符号 | 含义 |
* | 任何时间,比如第一个 * 表示每分钟都运行此任务。 |
, | 不连续的时间 |
- | 连续的时间范围 |
/ | 每隔多久执行一次 |
定时任务示例
每一分钟执行一次 /bin/ls:
* * * * * /bin/ls
12月每天早上 6 点到 12 点,每隔 3 小时第 0 分钟执行一次 /usr/bin/backup:
0 6-12/3 * 12 * /usr/bin/backup
周一到周五每天下午 5:00 寄一封信给 alex@domain.name:
0 17 * * 1-5 mail -s "hi" alex@domain.name < /tmp/maildata
每天凌晨 0 点 20 分, 2 点 20 分, 4 点 20 分....执行 echo "haha":
20 0-23/2 * * * echo "haha"
不过实际工作中的时间设置不会这么复杂,一般就是每天几点运行备份脚本之类的。还有人专门编了一个图形化工具,地址:http://www.openjs.com/scripts/jslibrary/demos/crontab.php
添加定时任务
现在我们已经知道了如何编辑定时任务,现在来看看如何将其添加到cron配置文件。
在添加到cron服务到之前,请首先运行一下任务脚本,确保结果符号你的需求。
正确的方法是:使用专门的 crontab 命令,此时会进入vi编辑器,然后输入前面已经设计好的定时任务,最后保存退出vi编辑器。
注意:不要直接编辑 /etc/crontab 文件,而是使用 crontab命令,因为它会在退出编辑时检查语法是否正确。
crontab 命令的几个重要选项
crontab
-u 指定用户名,省略用户表表示操作当前用户的crontab
-e 编辑任务
-l 列出任务
-r 删除任务
最常使用的就是 e 和 l 选项。
例如root通过输入下面的命令开始编辑定时任务
crontab -e
然后输入两条任务
* * * * * echo $(date +"\%Y年\%m月\%d日 \%H时\%M分\%S秒") >> test.txt
* * * * * echo `date "+\%Y-\%m-\%d \%H:\%M:\%S"` >> test.txt
* * * * * echo 1 >> test.txt
* * * * * echo 2 >> test.txt
* * * * * echo 3 >> test.txt
这个任务会在当前用户家目录test.txt文件中输出当前日期和时间。
从输出信息来看,任务的执行顺序是随机的,并没有什么规律。
2022-12-09 08:59:01
1
2022年12月09日 08时59分01秒
2
3
3
1
2022年12月09日 09时00分01秒
2
2022-12-09 09:00:01
之所以举这个例子是因为折腾了我一阵子,因为它一直不能正常工作,直到搜索了一番才发现 % 需要 转义。
The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or % character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. Percent-signs (%) in the command, unless escaped with backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.
"第六"个字段描述希望运行的命令。命令部分以换行或者 % 字符作为结束标志,如果命令需要用到百分比符号(%),必须使用反斜杠(\)转义,否则视为换行符,同时第一个%之后的所有数据将作为标准输入发送到命令中。
如果打开 /etc/crontab ,你会发现这个文件内容没有发生任何变化,刚才以root身份添加的两条任务保存在哪个文件中呢?答案是/var/spool/cron/root。
在大多数Linux发行版中,各个用户的crontabs通常存储在 /var/spool/cron/crontabs/<username>。基于RHEL的发行版则存储在/var/spool/cron/<username>。
如果任务比较复杂,不能在一行中写完,那么可以将任务写在脚本文件中,然后直接调用这个文件。注意需要为脚本文件添加执行权限。
00 02 * * * /usr/bin/bash /home/cron/dbbackup.sh
固定周期任务
对于每小时、每天、每周、每月执行一次的任务,您还可以直接将它们放到下面的文件夹中,cron 服务和anacron会按照指定的周期运行这些目录下的任务。
怎么又多了一个anacron?不要着急,目前只需要记住/etc/cron.hourly/目录中的脚本由cron驱动,而cron.daily、cron.weekly和cron.monthly目录中的脚本由anacron驱动即可,这是因为anacron也有点复杂,我们将在下一篇文章中进行讲解。
- /etc/cron.hourly/
- /etc/cron.daily/
- /etc/cron.weekly/
- /etc/cron.monthly/
/etc/cron.d/ 目录中只有一个0hourly配置文件,它的内容如下所示:
可以看出0hourly添加了一个每小时执行一次的定时任务,它在每小时的第1分钟以root身份启动 run-parts 执行 /etc/cron.hourly 目录下的脚本。
# cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly
而/etc/cron.hourly/目录初始只有一个0anacron脚本,它最后启动了anacron (/usr/sbin/anacron -s),即每小时系统都会运行一次anacron,而anacron又会去干它应该干的一些重要的事情。
# cat /etc/cron.hourly/0anacron
#!/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then
day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
exit 0
fi
# Do not run jobs when on battery power
online=1
for psupply in AC ADP0 ; do
sysfile="/sys/class/power_supply/$psupply/online"
if [ -f $sysfile ] ; then
if [ `cat $sysfile 2>/dev/null`x = 1x ]; then
online=1
break
else
online=0
fi
fi
done
if [ $online = 0 ]; then
exit 0
fi
/usr/sbin/anacron -s
查看定时任务运行日志
定时任务运行日志保存在 /var/log/cron 文件中,输入下面的命令可以实时查看文件内容的变化情况
tail -f /var/log/cron
很多系统“被黑”之后,黑客会添加一些定时任务,出现问题的时候看看定时任务执行日志说不定有帮助。
通过查看运行日志也可以进行定时任务错误调试,通常的错误包括:
- crontab 服务是否正常
- 脚本是否添加了执行权限
- 脚本路径前是否添加了 bash 或 /bin/sh
权限
如果希望严格控制哪些用户可以编辑/运行定时任务,可以在文件 /etc/cron.allow 和 /etc/cron.deny 中进行配置,这适用于大多数Linux发行版。编辑或创建 cron.deny 和 cron.allow文件需要root权限。
根据 /etc/cron.allow 和 /etc/cron.deny 是否存在,按照以下顺序判断用户是否可以编辑crontab。
- 如果cron.allow存在--只有列在其中的用户可以使用crontab。
- 如果cron.allow不存在--除了cron.deny中列出的用户,所有用户都可以使用crontab。
- 如果这两个文件都不存在--只有root可以使用crontab。
- 如果一个用户同时列在cron.allow和cron.deny中 - 该用户可以使用crontab。
参考文章
- Linux日志切割工具Logrotate配置详解
- https://unix.stackexchange.com/questions/29578/how-can-i-execute-date-inside-of-a-cron-tab-job
- https://www.macgasm.net/news/tips/terminal-tip-scheduling-rsync-backup-ssh-cron-job/
- https://www.cyberciti.biz/cloud-computing/why-is-my-linux-unix-crontab-job-not-working/