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對比
是以如果你想在指定時間點,讓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的指令,此方法采用的是先拷貝再清空的方式,整個過程中日志檔案的操作句柄沒有發生改變,是以不需要通知應用程式重新打開日志檔案,但是需要注意的是,在拷貝和清空之間有一個時間差,是以可能會丢失部分日志資料。