18.3 登录文件的轮替(logrotate)

假设我们已经将登录数据写入了记录文件中了,也已经利用 chattr 设置了 +a 这个属性了,那么该如何进行 logrotate 的工作呢?这里请特别留意的是:“rsyslogd 利用的是 daemon 的方式来启动的, 当有需求的时候立刻就会被执行的,但是 logrotate 却是在规定的时间到了之后才来进行登录文件的轮替, 所以这个 logrotate 程序当然就是挂在 cron 下面进行的呦!” 仔细看一下 /etc/cron.daily/ 里面的文件,嘿嘿~看到了吧! /etc/cron.daily/logrotate 就是记录了每天要进行的登录文件轮替的行为啦! ^_^!下面我们就来谈一谈怎么样设计这个 logrotate 吧!

18.3.1 logrotate 的配置文件

既然 logrotate 主要是针对登录文件来进行轮替的动作,所以啰,他当然必须要记载“ 在什么状态下才将登录文件进行轮替”的设置啊!那么 logrotate 这个程序的参数配置文件在哪里呢?呵呵!那就是:

  • /etc/logrotate.conf
  • /etc/logrotate.d/

那个 logrotate.conf 才是主要的参数文件,至于 logrotate.d 是一个目录, 该目录里面的所有文件都会被主动的读入 /etc/logrotate.conf 当中来进行!另外,在 /etc/logrotate.d/ 里面的文件中,如果没有规定到的一些细部设置,则以 /etc/logrotate.conf 这个文件的规定来指定为默认值!

好了,刚刚我们提到 logrotate 的主要功能就是将旧的登录文件移动成旧文件, 并且重新创建一个新的空的文件来记录,他的执行结果有点类似下面的图示:

登录文件进行 logrotate 的结果图18.3.1、登录文件进行 logrotate 的结果

由上面的图示我们可以清楚的知道,当第一次执行完 rotate 之后,原本的 messages 会变成 messages.1 而且会制造一个空的 messages 给系统来储存登录文件。而第二次执行之后,则 messages.1 会变成 messages.2 而 messages 会变成 messages.1 ,又造成一个空的 messages 来储存登录文件!那么如果我们仅设置保留三个登录文件而已的话,那么执行第四次时,则 messages.3 这个文件就会被删除,并由后面的较新的保存登录文件所取代!基本的工作就是这样啦!

不过近年来磁盘空间容量比较大了,加上管理员又担心登录文件数据真的给它不见去,因此,你可能已经发现到,最近的登录文件轮替后的文件名已经会加上日期参数, 然后源源不绝的保留在你的系统上耶~虽然这个设置是可以修订的,不过,鸟哥也真的希望保留日期的文件名延伸记录,真的比较不用担心未来要找问题时, 登录文件却已经 GG 了...

那么多久进行一次这样的 logrotate 工作呢?这些都记录在 logrotate.conf 里面,我们来看一下默认的 logrotate 的内容吧!

[root@study ~]# vim /etc/logrotate.conf
# 下面的设置是 "logrotate 的默认设置值" ,如果个别的文件设置了其他的参数,
# 则将以个别的文件设置为主,若该文件没有设置到的参数则以这个文件的内容为默认值!

weekly    <==默认每个礼拜对登录文件进行一次 rotate 的工作
rotate 4  <==保留几个登录文件呢?默认是保留四个!
create    <==由于登录文件被更名,因此创建一个新的来继续储存之意!
dateext   <==就是这个设置值!可以让被轮替的文件名称加上日期作为文件名喔!
#compress <==被更动的登录文件是否需要压缩?如果登录文件太大则可考虑此参数启动

include /etc/logrotate.d
# 将 /etc/logrotate.d/ 这个目录中的所有文件都读进来执行 rotate 的工作!

/var/log/wtmp {       <==仅针对 /var/log/wtmp 所设置的参数
    monthly           <==每个月一次,取代每周!
    create 0664 root utmp <==指定新建文件的权限与所属帐号/群组
    minsize 1M        <==文件大小一定要超过 1M 后才进行 rotate (略过时间参数)
    rotate 1          <==仅保留一个,亦即仅有 wtmp.1 保留而已。
}
# 这个 wtmp 可记录登陆者与系统重新开机时的时间与来源主机及登陆期间的时间。
# 由于具有 minsize 的参数,因此不见得每个月一定会进行一次喔!要看文件大小。
# 由于仅保留一个登录文件而已,不满意的话可以将他改成 rotate 5 吧!

由这个文件的设置我们可以知道 /etc/logrotate.d 其实就是由 /etc/logrotate.conf 所规划出来的目录,所以,其实我们可以将所有的数据都给他写入 /etc/logrotate.conf 即可,但是这样一来这个文件就实在是太复杂了,尤其是当我们使用很多的服务在系统上面时, 每个服务都要去修改 /etc/logrotate.conf 的设置也似乎不太合理~ 所以,如果独立出来一个目录,那么每个以 RPM 打包方式所创建的服务的登录文件轮替设置, 就可以独自成为一个文件,并且放置到 /etc/logrotate.d/ 当中即可,真是方便又合理的做法啊! ^_^

一般来说,这个 /etc/logrotate.conf 是“默认的轮替状态”而已, 我们的各个服务都可以拥有自己的登录文件轮替设置,你也可以自行修改成自己喜欢的样式啊! 例如,如果你的系统的空间够大,并且担心除错以及骇客的问题,那么可以:

  • 将 rotate 4 改成 rotate 9 左右,以保存较多的备份文件。不过如果已经加上 dateext 的参数,那这个项目就不用更动了!
  • 大部分的登录文件不需要 compress 啰!但是空间太小就需要 compress !尤其是很占硬盘空间的 httpd 更需要 compress 的!

好了,上面我们大致介绍了 /var/log/wtmp 这个文件的设置,现在你知道了 logrotate.conf 的设置语法是:

登录文件的绝对路径文件名 ... {
    个别的参数设置值,如 monthly, compress 等等
}

下面我们再以 /etc/logrotate.d/syslog 这个轮替 rsyslog.service 服务的文件,来看看该如何设置他的 rotate 呢?

[root@study ~]# vim /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

在上面的语法当中,我们知道正确的 logrotate 的写法为:

  • 文件名:被处理的登录文件绝对路径文件名写在前面,可以使用空白字符分隔多个登录文件;
  • 参数:上述文件名进行轮替的参数使用 { } 包括起来;
  • 执行脚本:可调用外部指令来进行额外的命令下达,这个设置需与 sharedscripts .... endscript 设置合用才行。至于可用的环境为:

    • prerotate:在启动 logrotate 之前进行的指令,例如修改登录文件的属性等动作;
    • postrotate:在做完 logrotate 之后启动的指令,例如重新启动 (kill -HUP) 某个服务!
    • Prerotate 与 postrotate 对于已加上特殊属性的文件处理上面,是相当重要的执行程序!

那么 /etc/logrotate.d/syslog 内设置的 5 个文件的轮替功能就变成了:

  • 该设置只对 /var/log/ 内的 cron, maillog, messages, secure, spooler 有效;
  • 登录文件轮替每周一次、保留四个、且轮替下来的登录文件不进行压缩(未更改默认值);
  • 轮替完毕后 (postrotate) 取得 syslog 的 PID 后,以 kill -HUP 重新启动 syslogd

假设我们有针对 /var/log/messages 这个文件增加 chattr +a 的属性时, 依据 logrotate 的工作原理,我们知道,这个 /var/log/messages 将会被更名成为 /var/log/messages.1 才是。但是由于加上这个 +a 的参数啊,所以更名是不可能成功的! 那怎么办呢?呵呵!就利用 prerotate 与 postrotate 来进行登录文件轮替前、后所需要作的动作啊! 果真如此时,那么你可以这样修改一下这个文件喔!

[root@study ~]# vim /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    sharedscripts
    prerotate
       /usr/bin/chattr -a /var/log/messages
    endscript
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
        /usr/bin/chattr +a /var/log/messages
    endscript
}

看到否?就是先给他去掉 a 这个属性,让登录文件 /var/log/messages 可以进行轮替的动作, 然后执行了轮替之后,再给他加入这个属性!请特别留意的是,那个 /bin/kill -HUP ... 的意义,这一行的目的在于将系统的 rsyslogd 重新以其参数文件 (rsyslog.conf) 的数据读入一次!也可以想成是 reload 的意思啦! 由于我们创建了一个新的空的记录文件,如果不执行此一行来重新启动服务的话, 那么记录的时候将会发生错误呦!(请回到第十六章读一下 kill 后面的 signal 的内容说明)

18.3.2 实际测试 logrotate 的动作

好了,设置完成之后,我们来测试看看这样的设置是否可行呢?给他执行下面的指令:

[root@study ~]# logrotate [-vf] logfile
选项与参数:
-v  :启动显示模式,会显示 logrotate 运行的过程喔!
-f  :不论是否符合配置文件的数据,强制每个登录文件都进行 rotate 的动作!

范例一:执行一次 logrotate 看看整个流程为何?
[root@study ~]# logrotate -v /etc/logrotate.conf
reading config file /etc/logrotate.conf <==读取主要配置文件
including /etc/logrotate.d              <==调用外部的设置
reading config file chrony              <==就是外部设置啊!
....(中间省略)....
Handling 18 logs                        <==共有 18 个登录文件被记录
....(中间省略)....
rotating pattern: /var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
 weekly (52 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/cron
  log does not need rotating
considering log /var/log/maillog
  log does not need rotating
considering log /var/log/messages       <==开始处理 messages
  log does not need rotating            <==因为时间未到,不需要更动!
....(下面省略)....

范例二:强制进行 logrotate 的动作
[root@study ~]# logrotate -vf /etc/logrotate.conf
....(前面省略)....
rotating log /var/log/messages, log->rotateCount is 52
dateext suffix '-20150820'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
compressing log with: /bin/gzip
....(下面省略)....
# 看到否?整个 rotate 的动作就是这样一步一步进行的~

[root@study ~]# ll /var/log/messages*; lsattr /var/log/messages
-rw-------. 1 root root    143 Aug 20 01:45 /var/log/messages
-rw-------. 1 root root 167125 Aug 20 01:40 /var/log/messages-20150820
-----a---------- /var/log/messages  <==主动加入 a 的隐藏属性啰!

上面那个 -f 具有“强制执行”的意思,如果一切的设置都没有问题的话,那么理论上,你的 /var/log 这个目录就会起变化啰!而且应该不会出现错误讯息才对!嘿嘿!这样就 OK 了!很棒不是吗?!

由于 logrotate 的工作已经加入 crontab 里头了!所以现在每天系统都会自动的给他查看 logrotate 啰!不用担心的啦!只是要注意一下那个 /var/log/messages 里头是否常常有类似下面的字眼:

Aug 20 01:45:34 study rsyslogd: [origin software="rsyslogd" swVersion="7.4.7" x-pid="2145" x-info="http://www.rsyslog.com"] rsyslogd was HUPed

这说明的是 rsyslogd 重新启动的时间啦 (就是因为 /etc/logrotate.d/syslog 的设置之缘故!) 下面我们来进行一些例题的练习,让你更详细的了解 logrotate 的功用啊!

18.3.3 自订登录文件的轮替功能

假设前提是这样的,前一小节当中,假设你已经创建了 /var/log/admin.log 这个文件, 现在,你想要将该文件加上 +a 这个隐藏标签,而且设置下面的相关信息:

  • 登录文件轮替一个月进行一次;
  • 该登录文件若大于 10MB 时,则主动进行轮替,不需要考虑一个月的期限;
  • 保存五个备份文件;
  • 备份文件需要压缩

那你可以怎么样设置呢?呵呵~很简单啊!看看下面的动作吧!

# 1\. 先创建 +a 这个属性啊!
[root@study ~]# chattr +a /var/log/admin.log
[root@study ~]# lsattr /var/log/admin.log
-----a---------- /var/log/admin.log
[root@study ~]# mv /var/log/admin.log /var/log/admin.log.1
mv: cannot move `/var/log/admin.log' to `/var/log/admin.log.1': Operation not permitted
# 这里确定了加入 a 的隐藏属性!所以 root 无法移动此登录文件!

# 2\. 开始创建 logrotate 的配置文件,增加一个文件在 /etc/logrotate.d 内就对了!
[root@study ~]# vim /etc/logrotate.d/admin
# This configuration is from VBird 2015/08/19
/var/log/admin.log {
        monthly   <==每个月进行一次
        size=10M  <==文件大小大于 10M 则开始处置
        rotate 5  <==保留五个!
        compress  <==进行压缩工作!
        sharedscripts
        prerotate
                /usr/bin/chattr -a /var/log/admin.log
        endscript
        sharedscripts
        postrotate
                /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
                /usr/bin/chattr +a /var/log/admin.log
        endscript
}

# 3\. 测试一下 logrotate 相关功能的信息显示:
[root@study ~]# logrotate -v /etc/logrotate.conf
....(前面省略)....
rotating pattern: /var/log/admin.log  10485760 Bytes (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
  log does not need rotating
not running prerotate script, since no logs will be rotated
not running postrotate script, since no logs were rotated
....(下面省略)....
# 因为还不足一个月,文件也没有大于 10M,所以不需进行轮替!

# 4\. 测试一下强制 logrotate 与相关功能的信息显示:
[root@study ~]# logrotate -vf /etc/logrotate.d/admin
reading config file /etc/logrotate.d/admin
reading config file /etc/logrotate.d/admin

Handling 1 logs

rotating pattern: /var/log/admin.log  forced from command line (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
  log needs rotating
rotating log /var/log/admin.log, log->rotateCount is 5
dateext suffix '-20150820'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/admin.log.5.gz to /var/log/admin.log.6.gz (rotatecount 5, logstart 1, i 5),
old log /var/log/admin.log.5.gz does not exist
renaming /var/log/admin.log.4.gz to /var/log/admin.log.5.gz (rotatecount 5, logstart 1, i 4),
old log /var/log/admin.log.4.gz does not exist
renaming /var/log/admin.log.3.gz to /var/log/admin.log.4.gz (rotatecount 5, logstart 1, i 3),
old log /var/log/admin.log.3.gz does not exist
renaming /var/log/admin.log.2.gz to /var/log/admin.log.3.gz (rotatecount 5, logstart 1, i 2),
old log /var/log/admin.log.2.gz does not exist
renaming /var/log/admin.log.1.gz to /var/log/admin.log.2.gz (rotatecount 5, logstart 1, i 1),
old log /var/log/admin.log.1.gz does not exist
renaming /var/log/admin.log.0.gz to /var/log/admin.log.1.gz (rotatecount 5, logstart 1, i 0),
old log /var/log/admin.log.0.gz does not exist
log /var/log/admin.log.6.gz doesn't exist -- won't try to dispose of it
running prerotate script
fscreate context set to system_u:object_r:var_log_t:s0
renaming /var/log/admin.log to /var/log/admin.log.1
running postrotate script
compressing log with: /bin/gzip

[root@study ~]# lsattr /var/log/admin.log*
-----a---------- /var/log/admin.log
---------------- /var/log/admin.log.1.gz  <==有压缩过喔!

看到了吗?通过这个方式,我们可以创建起属于自己的 logrotate 设置文件, 很简便吧!尤其是要注意的, /etc/rsyslog.conf 与 /etc/logrotate.d/* 文件常常要搭配起来,例如刚刚我们提到的两个案例中所创建的 /var/log/admin.log 就是一个很好的例子~创建后,还要使用 logrotate 来轮替啊! ^_^