天天看點

Nginx log logrotate not work

問題

最近遇到一個很詭異的問題,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正常 工作的方式。有需要的可以看下。

參考連結

audit2allow nginx-log-rotation-without-disabling-selinux nginx-selinux-configuration

繼續閱讀