Linux中Logrotate命令简介
1. 概述
在本教程中,我们将研究logrotate工具。具体来说,我们将学习如何在 Linux 中使用logrotate自动执行日志循环。
2. logrotate
在 Linux 中,应用程序和后台进程不断地产生日志。通过按特定时间表修剪这些日志来检查这些日志很重要。然而,手动这样做是劳动密集型的。为了减少人工干预,我们可以使用logrotate自动化该过程。
logrotate 是 Linux 中的日志管理命令行工具。管理员将处理不同日志文件的规则和策略写到配置文件中。通过配置文件,logrotate会执行相应的功能来管理匹配的日志文件。
尽管logrotate适用于任何类型的文件,但它通常用于管理日志文件。
2.1. 安装
要安装 logrotate,我们可以使用不同 Linux 发行版中的包管理器。
在 Ubuntu 上,我们可以使用apt-get 安装包 :
$ sudo apt-get update
$ sudo apt-get install -y logrotate
对于 CentOS 等基于 RHEL 的 Linux,我们可以使用 *yum *包管理器:
$ sudo yum update
$ sudo yum install -y logrotate
最后,我们可以 使用*apk 包管理器在 alpine 中安装logrotate*:
$ sudo apk update
$ sudo apk add logrotate
2.2. 命令语法
通常,我们通过指定选项列表后跟每个配置文件的路径来运行logrotate命令:
logrotate [OPTION...] <config file1> <config file2>...
**当有多个配置文件时,后面的定义会覆盖前面的定义。**换句话说,第一个配置文件的优先级最低。
2.3. 指令
**这些指令是logrotate配置的基本构建块,它们定义了不同的功能。**然后将它们组合起来形成适用于不同日志文件的配置文件。此外,这些指令中的每一个都允许我们配置logrotate的不同方面。例如,copy指令改变循环过程。另一方面,compress指令改变了循环文件的处理方式。
此外,这些指令中的大多数都有一个否定指令对应物。这些否定指令在指定时取消它们的对应效果。例如, 在配置块中 指定nocompress指令会取消全局compress指令。
有关指令的完整列表,我们可以在官方手册页 上找到它。
2.4. 配置文件
使用这些指令,我们可以组成一组可供logrotate使用的配置文件。通常,配置文件由以下格式组成:
<global directive 1>
<global directive 2>
<file path matchers 1> {
<directive 1>
<directive 2>
...
<directive n>
}
<file path matchers 2a> <file path matchers 2b> {
<directive 1>
<directive 2>
...
<directive n>
}
在配置文件的顶部,我们可以指定 0 个或多个全局指令。全局指令影响由 logrotate 管理的所有日志文件。
然后,我们指定多个 glob 模式来匹配我们要循环的文件。此外,我们在花括号内定义了一组指令,这些指令特定于与模式匹配的文件。
让我们看一个配置文件的例子:
compress
/var/log/nginx/* {
rotate 3
daily
}
/var/log/nginx/error.log {
rotate 3
size 1M
lastaction
/usr/bin/killall -HUP nginx
endscript
nocompress
}
在这个例子中,我们可以看到 顶部有一个全局compress指令。具体来说,任何匹配的日志文件都将在循环时被压缩。
然后,我们可以看到定义了 2 个模式:/var/log/nginx/* 和 /var/log/nginx/error.log。第一个匹配器使用通配符匹配*/var/log/nginx目录中的每个文件。另一方面,第二个匹配器只匹配/var/log/nginx中的特定error.log*文件。
在第二个配置块中,指定了一个nocompress指令来覆盖全局compress指令。
2.5. 默认配置
当我们安装 logrotate时,它会在*/etc/logrotate.conf中创建一个默认配置 。此配置文件包含几个全局指令,这些指令定义了logrotate的一些默认行为。由于logrotate*中的配置文件是附加的,我们必须记住默认配置,以便在需要时覆盖。
例如,Ubuntu 上的logrotate安装带有全局指令,如 weekly、rotate 4和 create。
2.6. 应用配置文件
一旦我们在配置文件上编写了循环策略,我们就需要运行 logrotate命令使其生效。具体来说,要应用log-rotation.conf配置文件,我们可以运行logrotate命令,然后运行配置文件路径:
$ logrotate log-rotation.conf
如果我们希望 logrotate立即评估条件,我们可以通过 -f选项强制运行它:
$ logrotate -f log-rotation.conf
3. 循环条件
使用logrotate,我们可以在不同条件下循环日志文件。特别是,我们可以在固定的持续时间内或文件增长到一定大小时循环日志文件。
3.1. 根据持续时间循环日志文件
要根据持续时间循环文件,我们可以指定 4 个指令中的一个:daily、weekly、monthly和yearly。例如,我们可以 通过在配置文件中指定 daily指令来每天循环*/var/log/nginx/access.log* :
/var/log/nginx/access.log {
daily
}
或者,要每周循环它,我们只需指定weekly指令:
/var/log/nginx/access.log {
weekly
}
3.2. 根据大小循环日志文件
大多数时候,我们希望在日志文件达到一定大小时循环它。为此,我们可以指定size指令,后跟尺寸限制。例如,要在*/var/log/nginx/access.log达到 1 兆字节后循环它,我们可以使用size 1M*指令:
/var/log/nginx/access.log {
size 1M
}
除了将后缀M识别为兆字节外,该指令还将后缀 k识别为千字节,将G识别为千兆字节。具体来说,指定 size 1000k 与指定size 1M具有相同的效果。
4. 处理循环文件
一旦日志文件被循环,我们可以通过一组不同的指令指定它们应该发生什么。例如,我们可以将循环后的文件发送到电子邮件中或直接丢弃它们。
4.1. 只保留少数循环日志文件
我们可以通过rotate n指令限制我们在系统中保留的循环文件的数量,其中n是一个整数值。一旦达到限制 n,任何进一步的循环将删除最旧的循环日志文件,以便遵守限制。例如,只保留 3 个循环的*/var/log/nginx/access.log*文件:
/var/log/nginx/access.log {
size 1M
rotate 3
}
轮转时,logrotate会检查系统中是否已经有 3 个轮转的access.log 。如果有,它将丢弃最旧的文件以便为新的循环文件腾出空间。最终,此配置确保系统中将有 3 个或更少的循环*/var/log/nginx/access.log* 。
4.2. 按年龄删除循环文件
此外,我们可以根据年龄删除循环的文件。特别是,我们可以使用maxage指令丢弃早于特定天数的文件。该指令采用一个额外的整数参数来指定天数。
例如,我们可以丢弃已经在系统中超过 5 天的循环日志:
/var/log/nginx/access.log {
size 1M
maxage 5
}
4.3. 压缩循环文件
logrotate工具可以选择在每次循环后压缩旧日志文件。具体来说,我们可以使用compress指令让logrotate压缩循环的日志文件:
/var/log/nginx/access.log {
size 1M
compress
}
在上面的示例中, 一旦日志文件大小达到 1 兆字节,logrotate 就会循环日志文件。随后,它将使用gzip 命令压缩旧日志文件。要否定全局应用的 compress指令,我们可以使用 nocompress指令:
compress
/var/log/nginx/access.log {
size 1M
}
/var/log/nginx/error.log {
size 1M
nocompress
}
在上面的示例中,logrotate会在每次循环后压缩access.log文件。但是,由于nocompress指令,它将免除error.log的压缩。
4.4. 邮寄循环文件
每次循环后,我们可以让logrotate使用mail指令将循环后的文件通过电子邮件发送给一些收件人。为此,我们首先必须在系统上配置一个工作的电子邮件客户端 。然后,我们可以指定mail指令来邮寄即将因循环而被丢弃的日志文件:
/var/log/nginx/error.log {
size 1M
rotate 2
mail
}
使用上面的配置, logrotate将为*/var/log/nginx/error.log*保留最多 2 个循环日志文件副本。此外,在丢弃任何循环日志之前, logrotate会将其邮寄给指定的收件人。
我们可以使用mailfirst指令邮寄新循环的日志文件,而不是邮寄过期的日志:
/var/log/nginx/error.log {
size 1M
rotate 2
mail
mailfirst
}
当循环发生时, logrotate将通过电子邮件发送最新的循环日志文件,而不是最旧的。
5. 处理活动日志文件
在默认行为中,轮转过程通过logrotate将活动日志文件重命名为不同的名称。然后,它会创建一个同名的新日志文件。最后调用compress、mail等其他逻辑来完成轮转过程。
对于某些应用程序,此默认行为太具有破坏性。特别是,如果应用程序不够灵活,无法处理到新文件的转换,它可能会崩溃。在这些情况下,我们可以使用 3 个指令中的一个来改变行为:create、copy和copytruncate。
5.1. 创建一个新的日志文件
**create指令是logrotate默认处理循环的方式。**使用此策略,它只需重命名日志文件并重新创建具有相同名称的日志文件。从表面上看,循环后的日志文件看起来还是一样的。但是,在循环之后,我们会为同一个文件获得不同的 inode 值。
让我们为*/tmp/logs/error.log配置create*指令:
/tmp/logs/error.log {
size 100k
rotate 2
create
}
然后,我们在error.log文件中输入 200 KB 的数据 并记下它的 inode 值:
$ ls -hil /tmp/logs
total 200K
402882 -rw-r--r-- 1 user user 200K Sep 5 12:45 error.log
接下来,我们运行logrotate命令来触发循环:
$ logrotate logrotate.conf
$ ls -hil /tmp/logs
total 200K
402878 -rw-r--r-- 1 user user 0 Sep 5 13:00 error.log
402882 -rw-r--r-- 1 user user 200K Sep 5 12:59 error.log.1
正如我们所见,inode 值为 402882 的文件被重命名为 error.log.1。另一方面,error.log文件有一个新的 inode 值。换句话说,logrotate命令首先将日志文件重命名为error.log.1。随后,它创建一个新的 error.log。
5.2. 制作活动日志文件的副本
为了减少循环过程的中断,我们可以通过将旧日志复制到不同的文件并清除内容来循环日志。
这种循环风格以 2 种不同的指令形式出现:copytruncate和 copy。与create相反,copy和copytruncate都复制主日志文件而不是重命名它。
但是,在涉及主文件内容发生的情况时,copy和copytruncate之间存在差异。一方面copytruncate指令清除了原始日志文件中的内容。另一方面,copy指令不会清除原始日志文件的内容。
让我们看一个例子来深入了解它们的确切行为。首先,我们将 /tmp/logs/error.log创建为一个 200 KB 的文件:
$ ls -hil /tmp/logs
total 200K
402878 -rw-r--r-- 1 user user 200K Sep 5 13:10 error.log
接下来,我们为*/tmp/logs/error.log创建一个配置文件, 使用copytruncate*指令以 100 KB 的大小循环 :
/tmp/logs/error.log {
size 100k
rotate 2
copytruncate
}
最后,我们运行logrotate命令来触发循环:
$ logrotate logrotate.conf
ls -hil /tmp/logs
total 200K
402878 -rw-r--r-- 1 user user 0 Sep 5 13:13 error.log
402882 -rw-r--r-- 1 user user 200K Sep 5 13:13 error.log.1
通过检查,我们可以观察到*error.log * inode 值仍然为402878 的同一个文件。此外, logrotate在轮转过程中清除了 error.log的内容,现在大小为0 字节。
让我们使用copy指令重复实验 :
$ cat logrotate.conf
/tmp/logs/error.log {
size 100k
rotate 2
copy
}
$ logrotate logrotate.conf
$ ls -hil /tmp/logs
total 400K
402878 -rw-r--r-- 1 user user 200K Sep 5 13:16 error.log
402882 -rw-r--r-- 1 user user 200K Sep 5 13:16 error.log.1
与copytruncate类似 ,error.log是同一个文件。但是,日志文件并没有清除error.log的内容,而是在轮转后仍然有 200 KB 的大小。
应谨慎使用copy指令,尤其是对于繁琐的日志。**这是因为copy指令的非删除性质 导致主日志和循环日志的大小不断增长。**最终,它可能会导致系统磁盘空间不足。
6.循环期间运行脚本
除了预定义的指令之外,logrotate还提供了在循环期间在不同挂钩点运行自定义脚本的可能性。具体来说,我们可以在循环过程中在 4 个不同的挂钩点上运行附加脚本:
- 在任何循环之前
- 每次循环前
- 每次循环后
- 全部循环后
6.1. 在所有循环之前或之后
使用firstaction指令,我们可以在任何循环发生之前运行一些自定义脚本。另一方面,** logrotate在所有循环发生后立即运行lastaction指令中的脚本。**在这两种情况下,logrotate都会将文件路径模式作为第一个参数传递给脚本。
例如,我们可以使用这些指令记录循环前后的时间戳:
/tmp/logs/*.log {
size 100k
firstaction
echo "start rotation $(date)" >> /tmp/rotation.log
endscript
lastaction
echo "complete rotation $(date)" >> /tmp/rotation.log
endscript
}
在上面的配置中,我们将在任何循环发生之前将时间戳写入 /tmp/rotation.log 。一旦所有轮转完成,我们将再次将时间戳附加到*/tmp/rotation.log*文件。
6.2. 每次循环之前或之后
要在每次循环之前运行脚本,我们可以使用prerotate指令编写脚本。同样,我们可以使用postrotate指令在每次循环后运行脚本。当logrotate运行脚本时,它会将每个日志文件的文件路径作为第一个参数传递给脚本。
例如,我们可以使用prerotate和 postrotate指令编写一个脚本来记录每个日志文件循环发生的时刻:
/tmp/logs/*.log {
size 100k
prerotate
echo "start rotation for $1 $(date)" >> /tmp/rotation.log
endscript
postrotate
echo "complete rotation for $1 $(date)" >> /tmp/rotation.log
endscript
}
上面的配置将在*/tmp/rotation.log*文件中为每个循环的日志文件生成 2 个日志行。
6.3. firstaction/lastaction和prerotate/postrotate之间的差异
从表面上看,firstaction/lastaction和prerotate/postrotate似乎都在做同样的事情:在循环前后运行脚本。但是,指令对之间的区别在于它们在 1 个匹配器的循环期间运行的次数。
** firstaction/lastaction指令对中的脚本只会为每个匹配器运行一次。另一方面,logrotate将为每个匹配的文件路径运行prerotate/postrotate中的脚本。**
比如pattern匹配3个文件,firstaction/lastaction只会在3个文件循环前后运行一次。另一方面,prerotate/postrotate中的脚本将执行 3 次,因为有 3 个文件需要循环。
为了更好地理解它们,让我们看一个例子。首先,我们创建一个logrotate配置来演示差异:
$ cat logrotate.conf
/tmp/logs/*.log {
size 100k
firstaction
echo "on first action. first argument: $1" >> /tmp/event-hooks.log
endscript
lastaction
echo "on last action. first argument: $1" >> /tmp/event-hooks.log
endscript
prerotate
echo "on prerotate. first argument: $1" >> /tmp/event-hooks.log
endscript
postrotate
echo "on postrotate. first argument: $1" >> /tmp/event-hooks.log
endscript
}
通过配置, 一旦文件大小达到 100 KB,我们将循环所有匹配路径 /tmp/logs/*.log的文件。然后,我们定义将事件名称和第一个参数打印到文件*/tmp/event-hooks.log*的脚本。
接下来,我们在*/tmp/logs*目录中创建 3 个不同的文件。此外,每个文件都是用 977 KB 的数据创建的,以触发循环:
ls -hl
total 2.9M
-rw-r--r-- 1 user user 977K Sep 5 14:57 access.log
-rw-r--r-- 1 user user 977K Sep 5 14:57 auth.log
-rw-r--r-- 1 user user 977K Sep 5 14:57 error.log
最后,我们可以运行命令来循环log目录中的文件:
$ logrotate logrotate.conf
之后,我们可以检查 /tmp/event-hooks.log来验证每个脚本的执行顺序:
$ cat /tmp/event-hooks.log
on first action. first argument: /tmp/logrotate/logs/*.log
on prerotate. first argument: /tmp/logrotate/logs/access.log
on postrotate. first argument: /tmp/logrotate/logs/access.log
on prerotate. first argument: /tmp/logrotate/logs/auth.log
on postrotate. first argument: /tmp/logrotate/logs/auth.log
on prerotate. first argument: /tmp/logrotate/logs/error.log
on postrotate. first argument: /tmp/logrotate/logs/error.log
on last action. first argument: /tmp/logrotate/logs/*.log