Linux logrotate执行流程分析

原文地址: http://www.jianshu.com/p/23b49d149426

1. 前言

最近在看logrotate使用,现将一些问题和分析过程记录下.

内核版本和系统信息如下:

Linux xxx 4.10.0-37-generic #41~16.04.1-Ubuntu SMP Fri Oct 6 22:42:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

不同版本的不同软件配置信息可能会有差异

2. 基本使用

logrotate基本的使用的流程如下:

  1. 创建一个logrotate配置文件
  2. 将文件放到/etc/logrotate.d目录下

拿一个官方文档的示例,具体配置不在这里展开,如下:

# sample logrotate configuration file
compress

/var/log/messages {
    rotate 5
    weekly
    postrotate
        /usr/bin/killall -HUP syslogd
    endscript
}

3. 问题

  1. 为什么只要将logrotate配置文件放在logrotate.d下面就会自动执行?
  2. 具体什么时候执行呢?

4. 分析

既然跟logrotate命令有关,那就使用man logrotate查看下详情:

     1  LOGROTATE(8)                           System Administrator's Manual                          LOGROTATE(8)
     2  
     3  NAME
     4         logrotate ‐ rotates, compresses, and mails system logs
     5  
     6  SYNOPSIS
     7         logrotate [-dv] [-f|--force] [-s|--state file] config_file ..
     8  
     9  DESCRIPTION
    10         logrotate  is  designed to ease administration of systems that generate large numbers of log files.
    11         It allows automatic rotation, compression, removal, and mailing of log files.  Each log file may be
    12         handled daily, weekly, monthly, or when it grows too large.
    13  
    14         Normally, logrotate is run as a daily cron job.  It will not modify a log more than once in one day
    15         unless the criterion for that log is based on the log's size and logrotate is being run  more  than
    16         once each day, or unless the -f or --force option is used.

可以看到第14行中的: Normally, logrotate is run as a daily cron job,表示logrotate一般是以一个cron job的形式每天执行,而cron的每天任务是放在/etc/cron.daily目录下的,查看该目录:

kk:~$ ll /etc/cron.daily
total 68
drwxr-xr-x   2 root root  4096 10月 10 22:48 ./
drwxr-xr-x 138 root root 12288 10月 25 20:20 ../
-rwxr-xr-x   1 root root   311 12月 29  2014 0anacron*
-rwxr-xr-x   1 root root   372 5月   6  2015 logrotate*

发现该目录下有个logrotate文件,里面内容如下:

1   #!/bin/sh
2   
3   # Clean non existent log file entries from status file
4   cd /var/lib/logrotate
5   test -e status || touch status
6   head -1 status > status.clean
7   sed 's/"//g' status | while read logfile date
8   do
9       [ -e "$logfile" ] && echo "\"$logfile\" $date"
10  done >> status.clean
11  mv status.clean status
12  
13  test -x /usr/sbin/logrotate || exit 0
14  /usr/sbin/logrotate /etc/logrotate.conf

重点在14行: /usr/sbin/logrotate /etc/logrotate.conf. 打开/etc/logrotate.conf:

1   # see "man logrotate" for details
-----------------------------------------------------------skip----------------------------------------------------------------
18  # packages drop log rotation information into this directory
19  include /etc/logrotate.d
-----------------------------------------------------------skip----------------------------------------------------------------

在第19行看到:include /etc/logrotate.d. 根据include指令的定义,该指令后面所跟的路径的文件会被按顺序读取(除了路径和特殊文件),这样可以解释问题1了.

但是还不完整,现在要找的是这个cron.daily下面的文件什么在哪里被使用到. 使用man cron查看说明:

1   CRON(8)                                        System Manager's Manual                                        CRON(8)
-----------------------------------------------------------skip----------------------------------------------------------------
35  NOTES
36         cron searches its spool area (/var/spool/cron/crontabs) for crontab files (which are named after  accounts  in
37         /etc/passwd);  crontabs  found  are  loaded  into  memory.  Note that crontabs in this directory should not be
38         accessed directly - the crontab command should be used to access and update them.
39  
40         cron also reads /etc/crontab, which is in a slightly different format (see crontab(5)).  In Debian,  the  con‐
41         tent  of  /etc/crontab is predefined to run programs under /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly
42         and /etc/cron.monthly. This configuration is specific to Debian, see the note under DEBIAN SPECIFIC below.
43  
44         Like /etc/crontab, the files in the /etc/cron.d directory are monitored for changes. In general, the system administrator should not use /etc/cron.d/, but use the  standard  system
45         crontab /etc/crontab.

100 DEBIAN SPECIFIC
-----------------------------------------------------------skip-----------------------------------------------------------------
124        Support for /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly and /etc/cron.monthly is  provided  in  Debian
125        through the default setting of the /etc/crontab file (see the system-wide example in crontab(5)).  The default
126        system-wide crontab contains four tasks: run every hour, every day, every week and every month. Each of  these
127        tasks will execute run-parts providing each one of the directories as an argument. These tasks are disabled if
128        anacron is installed (except for the hourly task) to prevent conflicts between both daemons.

可以看到第40到45行说cron默认会读取/etc/crontab/etc/cron.d下面的文件(mark一下,下文有用到),先看下/etc/crontab:

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

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 )

发现有执行cron.daily,在每天的6:25.但是由于本机是ubuntu,属于DEBIAN分支,看下DEBIAN SPECIFIC,发现第127到128行又说These tasks are disabled if anacron is installed(except for the hourly task),查看下:

kk:~$ dpkg -l | grep anacron
ii  anacron                                2.3-23                                       amd64        cron-like program that doesn't go by time

既然anacron有安装,那/etc/crontabcron.daily就要被disable了,那只能看anacron了,使用man anacron:

1   ANACRON(8)                                                                         Anacron Users' Manual                                                                         ANACRON(8)
2   
-----------------------------------------------------------skip----------------------------------------------------------------
15  
16         When executed, Anacron reads a list of jobs from a configuration file, normally /etc/anacrontab (see anacrontab(5)).  This file contains the list of  jobs  that  Anacron  controls.
17         Each job entry specifies a period in days, a delay in minutes, a unique job identifier, and a shell command.

从第16行中可以看到anacron的默认配置文件为/etc/anacrontab,看下:

1   # /etc/anacrontab: configuration file for anacron
2   
3   # See anacron(8) and anacrontab(5) for details.
4   
5   SHELL=/bin/sh
6   PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
7   HOME=/root
8   LOGNAME=root
9   
10  # These replace cron's entries
11  1   5   cron.daily  run-parts --report /etc/cron.daily
12  7   10  cron.weekly run-parts --report /etc/cron.weekly
13  @monthly    15  cron.monthly    run-parts --report /etc/cron.monthly

第11行中的1表示一天执行一次,5表示延迟5分钟

终于在第11行看到cron.daily了,那anacron又是何时执行呢?上文在讲cron默认读取的文件时,除了/etc/crontab之外,还会读取/etc/cron.d/下的文件,将该目录列出:

keith@keith-desktop:/etc$ ll /etc/cron.d
total 28
drwxr-xr-x   2 root root  4096 2月  16  2017 ./
drwxr-xr-x 138 root root 12288 10月 25 20:20 ../
-rw-r--r--   1 root root   244 12月 29  2014 anacron

发现有个anacron文件,查看下:

# /etc/cron.d/anacron: crontab entries for the anacron package

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

30 7    * * *   root    test -x /etc/init.d/anacron && /usr/sbin/invoke-rc.d anacron start >/dev/null

可以看到anacron的执行时间为每天的7:30分,这当然是不关机的情况,但如果超过这个点才开机呢?看下开机启动项有没有:

kk:~$ ll /etc/init.d | grep anacron
-rwxr-xr-x   1 root root  2014 12月 29  2014 anacron*

果然有,那就说明它有两种启动方式,一种是开机自启,一种是/etc/cron.d/anacron中编排的. 但是现在又有一个问题,既然都开机自启了,再在cron中编排时间有什么意义呢?打开看下:

1   #! /bin/sh
2   ### BEGIN INIT INFO
3   # Provides:          anacron
4   # Required-Start:    $remote_fs $syslog $time
5   # Required-Stop:     $remote_fs $syslog $time
6   # Default-Start:     2 3 4 5
7   # Default-Stop:
8   # Short-Description: Run anacron jobs
9   # Description: The first purpose of this script is to run anacron at
10  #              boot so that it can catch up with missed jobs.  Note
11  #              that anacron is not a daemon.  It is run here just once
12  #              and is later started by the real cron.  The second
13  #              purpose of this script is that said cron job invokes
14  #              this script to start anacron at those subsequent times,
15  #              to keep the logic in one place.
16  ### END INIT INFO
17  
18  PATH=/bin:/usr/bin:/sbin:/usr/sbin
19  
20  test -x /usr/sbin/anacron || exit 0
21  test -r /etc/default/anacron && . /etc/default/anacron
-----------------------------------------------------------skip----------------------------------------------------------------

上面说anacron不是一个后台进程,开机自启的目的是为了把遗漏的任务给补上,运行完任务后就退出了,在本次开机后的下一次执行任务就要由cron来编排了,这么说就清楚了. 那么logrotate配置文件的执行时间就是开机时间+延时时间或者7:30加延时时间.

流程总结如下:

《Linux logrotate执行流程分析》 logrotate配置文件执行流程 (1).png

  • 是否安装anacron的检查由cron来执行
  • 默认anacron有安装就有设置开机自启

5. 总结

最后回答刚开始提出的问题

  1. 为什么只要将logrotate配置文件放在logrotate.d下面就会自动执行? 这个可以上述分析和流程图.
  2. 具体什么时候执行呢? 如果anacron有安装,则在刚开机时如果条件满足则是开机时间+延时时间,如果是已经开机后条件满足则是/etc/cron.d/anacron中编排的时间+延时时间;如果没有安装,则时间为/etc/crontab中编排的时间.

注:

  1. 以上的分析是跟操作系统有关系的
  2. anacrontab中的还有会影响执行时间的因素如:RANDOM_DELAY等,这里不深究了.

真是刚开始只是一些小小的问题, 如果要深究的话真的会发现一串一串的新东西跑出来. 擦码到现在发现都凌晨了,我还计划最迟9点能搞定然后…never mind.

    原文作者:keith666
    原文地址: https://www.jianshu.com/p/23b49d149426
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞