天天看點

Openresty學習使用(四)日志切割

Openresty學習使用(四)日志切割

    • 說明
    • Logrotate
    • 日志切割
    • 問題
      • 執行時間的問題
      • 如何告訴應用程式重新打開日志檔案

說明

安裝新版nginx的時候,會自動在/etc/logrotate.d目錄下面生成一個nginx的檔案,每天會自動進行日志切割,保留10天的檔案等。但是openresty并沒有這個功能,是以需要手動建立配置檔案。

Logrotate

Linux伺服器上我們可以用Logrotate來分割歸檔日志檔案,結合crond我們可以指定每天在某個時間自動整理日志等文檔,避免自己去編寫複雜的crontab腳本。

Logrotate的配置檔案位于 /etc/logrotate.conf,

Logrotate的子配置檔案位于檔案夾 /etc/logrotate.d/ 下。

常用指令

常用指令 描述
logrotate -d -v /etc/logrotate.d/nginx 測試指定的logrotate配置
logrotate /etc/logrotate.conf 重新讀取配置檔案,并對符合條件的檔案檔案進行rotate

logrotate主要參數如下表:

配置參數 功能說明
compress 通過gzip 壓縮日志檔案的所有非目前版本
nocompress 不需要壓縮時,用這個參數
copytruncate 用于還在打開中的日志檔案,把目前日志備份并截斷
nocopytruncate 備份日志檔案但是不截斷
create mode owner group 轉儲檔案,使用指定的檔案模式建立新的日志檔案
nocreate 不建立新的日志檔案
delaycompress 和 compress 一起使用時,壓縮所有版本,除了目前和下一個最近的
nodelaycompress delaycompress 選項,轉儲同時壓縮。
errors address 專儲時的錯誤資訊發送到指定的Email 位址
ifempty 即使是空檔案也轉儲,這個是 logrotate 的預設選項。
notifempty 如果是空檔案的話,不轉儲
dateext 定義日志檔案字尾是日期格式,也就是切割後檔案是:xxx.log-20160402.gz這樣的格式。如果該參數被注釋掉,切割出來是按數字遞增,即前面說的 xxx.log-1這種格式
mail address 把轉儲的日志檔案發送到指定的E-mail 位址
nomail 轉儲時不發送日志檔案
olddir directory 轉儲後的日志檔案放入指定的目錄,必須和目前日志檔案在同一個檔案系統
noolddir 轉儲後的日志檔案和目前日志檔案放在同一個目錄下
prerotate/endscript 在轉儲以前需要執行的指令可以放入這個對,這兩個關鍵字必須單獨成行
postrotate/endscript 在轉儲以後需要執行的指令可以放入這個對,這兩個關鍵字必須單獨成行
daily 指定轉儲周期為每天
weekly 指定轉儲周期為每周
monthly 指定轉儲周期為每月
rotate 指定日志檔案删除之前轉儲的次數,0 指沒有備份,5 指保留5 個備份
tabootext [+] list 讓logrotate不轉儲指定擴充名的檔案,預設的擴充名是:.rpm-orig, .rpmsave, v, 和 ~
sharedscripts 對于整個日志組隻運作一次腳本
size size當日志檔案到達指定的大小時才轉儲,Size 可以指定 bytes (預設)以及KB (sizek)或者MB (sizem).

日志切割

我們在/etc/logrotate.d下面建立openresty檔案

/usr/local/openresty/nginx/logs/*log {
    daily
    missingok
    rotate 7
    notifempty
    sharedscripts
    compress
    delaycompress
    dateext
    postrotate
        [ ! -f /usr/local/openresty/nginx/logs/nginx.pid ] || kill -USR1 `cat /usr/local/openresty/nginx/logs/nginx.pid`
    endscript
}
           

執行logrotate /etc/logrotate.conf

需要說明的是sharedscripts,我在前面Nginx的例子裡聲明日志檔案的時候用了星号通配符,也就是說這裡可能涉及多個日志檔案,比如:access.log和error.log。sharedscripts的作用是在所有的日志檔案都輪轉完畢後統一執行一次腳本。如果沒有配置這條指令,那麼每個日志檔案輪轉完畢後都會執行一次腳本。

問題

執行時間的問題

Logrotate是基于CRON運作的,是以這個時間是由CRON控制的。如果使用的是新版CentOS,那麼配置檔案為:/etc/anacrontab。

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1	5	cron.daily		nice run-parts /etc/cron.daily
7	25	cron.weekly		nice run-parts /etc/cron.weekly
@monthly 45	cron.monthly		nice run-parts /etc/cron.monthly
           

RANDOM_DELAY 指的是最大的延遲時間,這個時間被加在delay in minutes中,為最後生效的delay分鐘數,也就是說每次執行日常任務是總是有一個随機5-50分鐘的延時。

START_HOURS_RANGE 指定任務開始的小時數。

cron與anacron對比

Openresty學習使用(四)日志切割

是以如果你想在指定時間點,讓logrotate切割日志的話,是不合适的。我們目前的場景是走了日志收集,是以啥時候切割并不是很重要。

如果想在指定時間點進行切割的話,參考如下腳本,然後配置crontab進行執行

#!/bin/bash
#初始化
LOGS_PATH=/usr/local/openresty/nginx/logs/
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

#按天切割日志
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log

#向nginx主程序發送USR1信号,重新打開日志檔案,否則會繼續往mv後的檔案寫資料的。原因在于:linux系統中,核心是根據檔案描述符來找檔案的。如果不這樣操作導緻日志切割失敗。

kill -USR1 `ps axu | grep "nginx: master process" | grep -v grep | awk '{print $2}'`

#删除7天前的日志
cd ${LOGS_PATH}
find . -mtime +7 -name "*20[1-9][3-9]*" | xargs rm -f
exit 0
           

如何告訴應用程式重新打開日志檔案

以Nginx為例,是通過postrotate指令發送USR1信号來通知Nginx重新打開日志檔案的。但是其他的應用程式不一定遵循這樣的約定,比如說MySQL是通過flush-logs來重新打開日志檔案的。更有甚者,有些應用程式就壓根沒有提供類似的方法,此時如果想重新打開日志檔案,就必須重新開機服務,但為了高可用性,這往往不能接受。Logrotate提供了一個名為copytruncate的指令,此方法采用的是先拷貝再清空的方式,整個過程中日志檔案的操作句柄沒有發生改變,是以不需要通知應用程式重新打開日志檔案,但是需要注意的是,在拷貝和清空之間有一個時間差,是以可能會丢失部分日志資料。

繼續閱讀