Cron.daily和cron.hourly不执行排查随记
环境+现象简述
Red Hat Enterprise Linux release 8.2 (Ootpa)
(Redhat系如centos其实都类似实现)
接报障称/var/log下的日志文件占用空间大导致触发了磁盘空间告警,登陆节点检查发现日志在4月3号后应该就没有再切割过
TL;DR
在Redhat系发行版(CentOS Linux/Redhat Linux/Oracle Linux/...)系统下,cron.daily
或 cron.weekly
或 cron.monthly
下的配置文件的执行是由anacron
组件实现的,而 anacron
的被调用执行又是由 crontab
的 cron.hourly/0anacron
实现的
每小时调用一次anacron判断是否需要执行每日或者每周或者每月任务(所以利用原生logrotate配置对nginx日志进行切割,如果发现实际切割时间与零点偏移过大的话也是anacron的配置问题)
注意/etc/cron.hourly/0anacron
文件需要可执行权限,不然 run-parts 不会去执行(可以通过 run-parts --test
参数测试确认,部分发行版系统下run-parts执行的文件甚至不能有扩展名)
而 cron.hourly
的被调用是在 /etc/cron.d/0hourly
中定义的
小插曲:
虽然随后我与当下大热的打工人作弊神器——ChatGPT交流后,ChatGPT告诉我:
anacron守护进程是一个长期运行的程序,它负责管理和协调anacron定时任务的执行。在Linux系统中,anacron守护进程通常是由系统服务管理器(如systemd)启动并运行的。
anacron守护进程的主要作用是检查上一次执行任务的时间戳,并根据每个定时任务的日期和时间来确定哪些任务需要执行,然后在系统处于闲置状态时调度这些任务,并记录任务执行的结果。通过启动anacron守护进程,我们可以确保在系统遇到意外关机或定时任务被跳过的情况下,任务仍然会在后续的闲置时间内得到执行。
通常,anacron守护进程还允许管理员配置每个任务的优先级,以便确保任务的执行顺序。
这与我的排查结论有一定的出入,应该是有不同的发行版系统存在不同的行为
排查过程
首先先检查确认logrotate配置没问题
/usr/sbin/logrotate /etc/logrotate.conf -d
回显没有明确的问题
由于logrotate默认属于没有守护进程的实现,需要依赖crontab去调用
确认logrotate的被调用配置文件存在和crontab的状态:
[root@prdmgtr01 cron.d]# ls /etc/cron.daily/ -l total 12 -rwx------. 1 root root 219 Apr 1 2020 logrotate -rwxr-xr-x. 1 root root 618 Oct 30 2018 man-db.cron -rwx------. 1 root root 558 May 18 2022 rhsmd
systemctl status crond
journalctl -u crond
确认crontab的守护进程正常,但是在输出的日志刚好发现crontab执行记录有问题
root@prdmgtr01:/etc/cron.daily >journalctl -u crond -n 15 -- Logs begin at Sun 2023-03-19 01:49:01 GMT, end at Sun 2023-04-16 14:56:19 IST. -- Apr 03 06:01:01 prdmgtr01 CROND[2411696]: (root) CMD (run-parts /etc/cron.hourly) Apr 03 07:01:01 prdmgtr01 CROND[2549785]: (root) CMD (run-parts /etc/cron.hourly) Apr 03 08:01:01 prdmgtr01 CROND[2687939]: (root) CMD (run-parts /etc/cron.hourly) Apr 03 09:01:01 prdmgtr01 CROND[2825903]: (root) CMD (run-parts /etc/cron.hourly) Apr 03 10:01:01 prdmgtr01 CROND[2964144]: (root) CMD (run-parts /etc/cron.hourly) Apr 03 11:01:01 prdmgtr01 CROND[3102130]: (root) CMD (run-parts /etc/cron.hourly) Apr 09 01:00:01 prdmgtr01 CROND[445672]: (root) CMD (/usr/sbin/raid-check) Apr 16 01:00:01 prdmgtr01 CROND[1962505]: (root) CMD (/usr/sbin/raid-check)
从这就可以看出来自Apr 03以后cron.hourly就没有再被执行过
root@prdmgtr01:/etc/cron.daily >journalctl -u crond --since 2023-04-01|grep daily Apr 01 03:01:01 prdmgtr01 anacron[3757301]: Will run job `cron.daily' in 6 min. Apr 01 03:07:01 prdmgtr01 anacron[3757301]: Job `cron.daily' started Apr 01 03:07:01 prdmgtr01 anacron[3757301]: Job `cron.daily' terminated (produced output) Apr 02 03:01:01 prdmgtr01 anacron[2876968]: Will run job `cron.daily' in 28 min. Apr 02 03:29:01 prdmgtr01 anacron[2876968]: Job `cron.daily' started Apr 02 03:29:01 prdmgtr01 anacron[2876968]: Job `cron.daily' terminated (produced output) Apr 03 03:01:01 prdmgtr01 anacron[1997420]: Will run job `cron.daily' in 30 min. Apr 03 03:31:01 prdmgtr01 anacron[1997420]: Job `cron.daily' started Apr 03 03:31:02 prdmgtr01 anacron[1997420]: Job `cron.daily' terminated (produced output) root@prdmgtr01:/etc/cron.daily >date Sun Apr 16 14:57:52 IST 2023
同样的cron.daily在Apr 03以后也没有再被执行过
问题定位方向大致清晰,就是cron.daily没有被按天执行导致logrotate不被执行
顺手查一下cron.daily下面的文件定义有没有异常
root@prdmgtr01:/etc/cron.daily >run-parts --test /etc/cron.daily /etc/cron.daily/logrotate root@prdmgtr01:/etc/cron.daily >ls -l /etc/cron.daily total 4 -rwxr-xr-x. 1 root root 189 Jan 4 2018 logrotate
cron.daily按天执行是由anacron实现的
[root@prdmgtr01 cron.d]# 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
确认anacron包没有被人误删
[root@prdmgtr01 root]# rpm -qa|grep anacron cronie-anacron-1.4.11-23.el7.x86_64
检查配置文件发现 /etc/cron.hourly/0anacron
被人误删了
原本应该有如下文件在节点上负责每小时执行一次0anacron,所以这个就是为什么cron.daily下面的配置例如logrotate没有每天执行的原因之一
[root@prdmgtr01 cron.hourly]# ls -l /etc/cron.hourly/ total 4 -rwxr-xr-x. 1 root root 392 Aug 9 2019 0anacron [root@prdmgtr01 cron.hourly]# 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 if test -x /usr/bin/on_ac_power; then /usr/bin/on_ac_power >/dev/null 2>&1 if test $? -eq 1; then exit 0 fi fi /usr/sbin/anacron -s
至于anacron s
参数的作用如下,记录一下,不做深入讨论:
[root@prdmgtr01 cron.hourly]# /usr/sbin/anacron -h Usage: anacron [options] [job] ... anacron -T [-t anacrontab-file] Options: -s Serialize execution of jobs -f Force execution of jobs, even before their time -n Run jobs with no delay, implies -s -d Don't fork to the background -q Suppress stderr messages, only applicable with -d -u Update the timestamps without actually running anything -V Print version information -h Print this message -t <file> Use alternative anacrontab -T Test an anacrontab -S <dir> Select a different spool directory See the anacron(8) manpage for more details.
至于cron.hourly下的文件定义同样没有被每小时执行的原因也是因为 /etc/cron.d/0hourly
配置文件被删了
原本应该有如下文件定义
[root@prdmgtr01 cron.d]# ls -l /etc/cron.d total 8 -rw-r--r--. 1 root root 128 Aug 9 2019 0hourly -rw-------. 1 root root 235 Apr 1 2020 sysstat [root@prdmgtr01 cron.d]# 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
PS: sar的性能采集间隔(默认十分钟)也是在这里定义的
[root@prdmgtr01 cron.d]# cat /etc/cron.d/sysstat # Run system activity accounting tool every 10 minutes */10 * * * * root /usr/lib64/sa/sa1 1 1 # 0 * * * * root /usr/lib64/sa/sa1 600 6 & # Generate a daily summary of process accounting at 23:53 53 23 * * * root /usr/lib64/sa/sa2 -A
最终补回原本应有的 /etc/cron.hourly/0anacron
和 /etc/cron.d/0hourly
配置即恢复正常工作,注意0anacron文件需要可执行权限,不然 run-parts 不会去执行(可以通过 run-parts --test
参数测试确认)
参考资料:
- man crontabs
- run-parts 相关特性
- logrotate自定义切割时间的一些坑/为什么logrotate没有在零点准时执行