概述
本章,您将学习到如何优化 Apache httpd 的日志。
若您的 Apache httpd 是从存储库进行安装的,则日志在绝大多数情况下都不需要变更或优化,但是,由于作者这里采用的是源代码编译安装,因此有必要优化我们的日志。
前面提到:
- logs 目录 - 日志文件所存放的目录。通常情况下会存在三个文件:access_log(访问日志)、error_log(错误日志)、httpd.pid(进程 ID 文件)。如果服务器启用了 SSL/TLS,logs 目录下还可能额外出现 ssl_access_log、ssl_error_log 和 ssl_request_log 三个专用于记录 HTTPS 相关访问、错误及握手请求信息的日志文件。
日志格式说明
Apache httpd 的日志格式非常丰富,参阅 这里
在主配置 httpd.conf 文件当中,日志格式的定义如下:
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog "logs/access_log" common
</IfModule>
LogFormat 指令的后面就是指令参数,第一个指令参数定义日志的格式,第二个指令参数定义该格式的昵称名,方便后续调用。
日志优化
如果将 Apache httpd 的日志全部记录在单个文件当中,随着时间的推移,日志文件所占有的存储空间会越来越大而且查询起来也很不方便,因此需要对日志文件进行处理,这里的处理指的是轮替(切割和删除)。
- 切割 - 将日志按照特定的规则分隔成一个又一个小文件,比如以天为单位切割大日志文件、以文件大小为单位切割大日志文件
- 删除 - 保留一定时间内的文件但删除该时间之前的日志,比如保留最近一个月内的日志,但删除最近一个月之前的日志
- 轮替 - 指切割与删除的统称
与日志轮替相关的命令
虽然 Apache httpd 有自带的 rotatelogs 命令工具可以对日志进行优化,但是在生产环境下通常会使用更加成熟的 logrotate 命令进行替代。
提到 logrotate 命令,需要先介绍 /etc/logrotate.conf 文件和 /etc/logrotate.d/ 目录。
Shell > grep -v -E "^#|^$" /etc/logrotate.conf
weekly
rotate 4
create
dateext
include /etc/logrotate.d
Shell > ls -l /etc/logrotate.d/
-rw-r--r-- 1 root root 130 Feb 7 2023 btmp
-rw-r--r--. 1 root root 160 Dec 5 2023 chrony
-rw-r--r--. 1 root root 88 Apr 12 2021 dnf
-rw-r--r-- 1 root root 93 Mar 11 17:29 firewalld
-rw-r--r--. 1 root root 162 Apr 16 19:49 kvm_stat
-rw-r--r-- 1 root root 289 Dec 18 01:38 sssd
-rw-r--r-- 1 root root 226 Nov 5 15:43 syslog
-rw-r--r-- 1 root root 145 Feb 19 2018 wtmp
/etc/logrotate.conf - 日志轮替的全局配置文件。如果配置项或参数重叠,则以 logrotate 最后读取到的配置项或参数为准。读取顺序为:
- 从上到下读取 /etc/logrotate.conf 文件的内容
- 使用 "include" 关键字包含的文件
常见的配置项或参数为:
| 项 | 说明 |
|---|---|
daily |
定义以天为单位的日志轮替周期 |
weekly |
定义以周为单位的日志轮替周期 |
monthly |
定义以月为单位的日志轮替周期 |
rotate <NUMBER> |
日志轮替后保存的文件数 |
compress |
在日志轮替后压缩旧日志 |
create <MODE> <OWNER> <GROUP> |
日志轮替后,定义新日志文件的权限、所有者以及所属组 |
mail <E-MAIL ADDRESS> |
日志轮替后,将输出的内容以邮件的方式发送到指定的邮箱 |
missingok |
如果日志文件不存在,则忽略日志的警告信息 |
notifempty |
如果日志文件的内容为空,则不会发生日志轮替 |
minsize <SIZE> |
日志轮替的文件大小条件,即日志轮替仅在满足此条件时发生 |
dateext |
使用日期作为日志轮替的文件后缀名 |
Apache httpd 所有的日志文件都存放在 /usr/local/apache2/logs/ 目录中,日志轮替的配置如下:
Shell > vim /etc/logrotate.d/httpd
/usr/local/apache2/logs/*log {
daily
rotate 30
create 0640 daemon daemon
missingok
notifempty
dateext
sharedscripts
postrotate
/usr/local/apache2/bin/apachectl graceful &> /dev/null || true
endscript
}
强制 logrotate 发生一次轮替行为:
Shell > logrotate -f /etc/logrotate.conf
访问日志中不记录静态文件的访问记录
在 Apache httpd 2.4 中,默认会在访问日志(access_log)中记录图片、js、css等静态文件的访问记录,这些文件的访问量是巨大的且对实际的日志分析没有太多作用,所以我们需要在访问日志中忽略掉。
默认情况下,access_log 记录一张图片的访问记录是这样的:
192.168.100.20 - - [27/Jul/2020:20:35:05 +0800] "GET /dog.jpg HTTP/1.1" 200 60504
在主配置文件 httpd.conf 中进行修改,修改的位置为网页根目录的 Directory 配置段以及访问日志的位置:
<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
SetEnvIf Request_URI "\.(gif|jpg|jpeg|png|bmp|ico|swf|js|css|woff|woff2|ttf|eot|svg|mp4|mp3|pdf|zip|rar|gz|tar)$" image-request
</Directory>
...
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog "logs/access_log" common env=!image-request
</IfModule>
...
若 Apache httpd 开启了 TLS/SSL 协议的支持,则还应该修改 httpd-ssl.conf(/usr/local/apache2/conf/extra/httpd-ssl.conf) 文件:
<VirtualHost 192.168.168.20:80>
ServerName myhost.rockylinux.org
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [L,R=301]
</VirtualHost>
<VirtualHost 192.168.168.20:443>
SetEnvIf Request_URI "\.(gif|jpg|jpeg|png|bmp|ico|swf|js|css|woff|woff2|ttf|eot|svg|mp4|mp3|pdf|zip|rar|gz|tar)$" static-request
DocumentRoot "/usr/local/apache2/htdocs"
ServerName myhost.rockylinux.org
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
SSLCertificateFile /usr/local/apache2/web-ssl/httpd.crt
SSLCertificateKeyFile /usr/local/apache2/web-ssl/httpd.key
SSLCertificateChainFile /usr/local/apache2/web-ssl/root_bundle.crt
SSLSessionCache shmcb:/usr/local/apache2/logs/ssl_gcache_data(512000)
SSLSessionCacheTimeout 300
ErrorLog "/usr/local/apache2/logs/ssl_error_log"
CustomLog "/usr/local/apache2/logs/ssl_access_log" combined env=!static-request
</VirtualHost>









