問題
最近遇到一個很詭異的問題,nginx 的日志使用
logrotate
不按計劃執行。多次排查,經過幾天的觀察也無效果。
分析
先分成幾步吧。一步一步找問題。我先列出以下幾個點:
- logrotate 運作機制
- nginx logrotate配置檔案
- 手動執行
- selinux
Nginx日志logrotate(輪替)
Nginx的日志,預設使用rpm或yum安裝的情況下,是自動會添加logrotate檔案的,我們不用特意的配置。但在編譯的nginx中,我們需要手動添加logrotate檔案的,不然日志是無法切割的。
運作機制
首先,系統在啟動時,會自動加載運作
crond
,預設系統也已經安裝了
logrotate
程式。它會根據設定對指定的檔案進行輪替切割。即 crond + logrotate 實作了日志的自動輪轉,不用我們寫腳本控制日志的輪替了。
預設的
cron
配置位于
/etc
目錄下:
ls /etc/cron*
cron.d/ cron.daily/ cron.deny cron.hourly/ cron.monthly/ crontab cron.weekly/
從上面檔案夾的名字可以看出,預設的
cron
計劃可以按天、小時、周、月來執行。
logrotate配置
預設logrotate的cron檔案位于
/etc/cron.daily/logrotate
下。即每天執行。
可以看下檔案内容:
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
其中需要注意的是,上面的這個檔案
/etc/logrotate.conf
,該檔案是logrotate服務的主配置檔案。
我們看下該檔案的内容:
# see "man logrotate" for details
# rotate log files weekly
weekly
# keep 4 weeks worth of backlogs
rotate 4
# create new (empty) log files after rotating old ones
create
# use date as a suffix of the rotated file
dateext
# uncomment this if you want your log files compressed
#compress
# RPM packages drop log rotation information into this directory
include /etc/logrotate.d
# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
monthly
create 0664 root utmp
minsize 1M
rotate 1
}
/var/log/btmp {
missingok
monthly
create 0600 root utmp
rotate 1
}
# system-specific logs may be also be configured here.
然後我們可以關注下
include
指令,這裡是rpm安裝包安裝完後,會把自己的
logrotate
配置放入到該子目錄中,是不是很像
nginx
的虛拟主機配置?
這個檔案是預設的配置,當然我們可以在子檔案中,添加相關的選項覆寫預設的配置。
Nginx logrotate配置
我們看下
/etc/logrotate.d/nginx
的内容:
"/data/nginx/logs/*.log"
{
daily
rotate 7
missingok
dateext
compress
delaycompress
sharedscripts
create 0640 nginx nginx
postrotate
if [ -f /usr/local/nginx/logs/nginx.pid ]; then kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` ; fi
endscript
}
裡面的指令網上一查就知道了,不過這裡還是簡單說明記錄下。
daily 每日執行
rotate 保留輪替的7份,先進先出,超過7就删除之前的檔案
missingok 忽略錯誤
dateext 定義日期字尾格式,這裡也可以修改預設值*dateext format -%Y-%m-%D*
compress 是否壓縮
delaycompress 延遲壓縮
create 定義新日志檔案的屬性
postrotate 輪轉日志檔案之後執行的腳本
sharedscripts 如果該檔案中定義了多個檔案需要logrotate,那麼該指令隻會執行一次postrotate腳本
測試驗證
可以通過手動執行驗證logrotate配置
logrotate -d /etc/logrotate.conf
-d:
開啟debug模式,不會實際執行輪轉檔案
在這裡都是沒有問題的,在第二天觀察的時候,發現還是不行。然後又修修補補,各種改nginx的logrotate檔案,發現還是各種不行。
檢查selinux
在和朋友聊了這麼詭異的問題之後,突然聊到了
selinux
, 對,就是我們在接觸linux時,一般各種文檔都會提示禁用
selinux
.
檢查下是否開啟了
selinux
:
# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 31
果然确實是開啟的狀态。看下審計日志(拒絕和關聯的系統調用記錄到/var/log/audit/audit.log)
grep nginx /var/log/audit/audit.log | grep logs
輸出如下面的内容:
type=AVC msg=audit(1574651401.550:22184): avc: denied { getattr } for pid=26928 comm="logrotate" path="/data/nginx/logs/access.log" dev="sda3" ino=68228788 scontext=system_u:system_r:logrotate_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
type=AVC msg=audit(1574651401.567:22185): avc: denied { getattr } for pid=26928 comm="logrotate" path="/data/nginx/logs/access.log" dev="sda3" ino=68228788 scontext=system_u:system_r:logrotate_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
可以把上面的時間戳複制下,通過以下指令看下具體發生的時間:
date -d "@1574651401.567"
調試下selinux,安裝
selinux tools 工具
yum install policycoreutils-python -y
我們使用剛安裝好的selinux工具,
audit2allow
可以從拒絕的操作的日志中生成SELinux政策允許規則。
grep nginx /var/log/audit/audit.log | audit2allow -m nginx -a
或者直接使用以下指令,可以看到系統目前出現過的audit日志
audit2allow -w -a
我們這裡先直接關閉
selinux
吧。驗證下。
setenforce 0
永久關閉
selinux
,需要修改selinux的配置檔案
/etc/sysconfig/selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
驗證
第二天再看下,日志已經成功輪替了,确認了下就是
selinux
的“鍋”. 另外文章底部的參考連結有開啟
selinux
讓日志logrotate正常 工作的方式。有需要的可以看下。