logrotate介紹
對於Linux系統安全來說,日誌檔案是極其重要的工具。日誌檔案包含了關於系統中發生的事件的有用資訊,在排障過程中或者系統效能分析時經常被用到。當日志檔案不斷增長的時候,就需要定時切割,否則,寫日誌的速度和效能也會下降,更不便於我們歸檔,查詢。
所以便有了使用logrotate的時候 ,logrotate是個十分有用的工具,它可以自動對日誌進行截斷(或輪循)、壓縮以及刪除舊的日誌檔案。例如,你可以設定logrotate,讓/var/log/foo日誌檔案每30天輪循,並刪除超過6個月的日誌。配置完後,logrotate的運作完全自動化,不必進行任何進一步的人為干預。
logrotate配置檔案位置
Linux系統預設安裝logrotate工具,它預設的配置檔案在:
1 2 |
/etc/logrotate.conf /etc/logrotate.d/ |
logrotate.conf 才主要的配置檔案,logrotate.d 是一個目錄,該目錄裡的所有檔案都會被主動的讀入/etc/logrotate.conf中執行。
另外,如果 /etc/logrotate.d/ 裡面的檔案中沒有設定一些細節,則會以/etc/logrotate.conf這個檔案的設定來作為預設值。
實際執行時,Logrotate會呼叫配置檔案/etc/logrotate.conf。
可以在/etc/logrotate.d目錄裡放置自定義好的配置檔案,用來覆蓋Logrotate的預設值。
定時輪循機制
Logrotate是基於CRON來執行的,其指令碼是/etc/cron.daily/logrotate,日誌輪轉是系統自動完成的。
logrotate這個任務預設放在cron的每日定時任務cron.daily下面 /etc/cron.daily/logrotate/etc/目錄下面還有cron.weekly/, cron.hourly/, cron.monthly/ 的目錄都是可以放定時任務的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[/etc]$ cat /etc/cron.daily/logrotate #!/bin/sh # Clean non existent log file entries from status file cd /var/lib/logrotate test -e status || touch status head -1 status > status.clean sed 's/"//g' status | while read logfile date do [ -e "$logfile" ] && echo "\"$logfile\" $date" done >> status.clean mv status.clean status test -x /usr/sbin/logrotate || exit 0 /usr/sbin/logrotate /etc/logrotate.conf |
這裡實際操作輪詢的命令最後一行
/usr/sbin/logrotate /etc/logrotate.conf
定義好了每日執行任務的指令碼cron.daily/logrotate ,再檢視crontab的內容,裡面設定好了對應的cron.xxly
執行時間
1 2 3 4 5 6 7 8 9 |
[/etc]$ vim /etc/crontab SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) |
可以看出來了只要是在
- /etc/cron.daily/ 下面的任務都是每天6:25 執行
- /etc/cron.weekly/ 下面的任務都是每週日 6:47 執行
- /etc/cron.monthly/ 下面的任務都是每月1號 6:52 執行
如果等不及cron自動執行日誌輪轉,想手動強制切割日誌,需要加-f引數;
不過正式執行前最好通過Debug選項來驗證一下(-d引數),這對除錯也很重要
1 2 |
# /usr/sbin/logrotate -f /etc/logrotate.d/nginx // 未到時間或者未到切割條件,強制切割 # /usr/sbin/logrotate -d -f /etc/logrotate.d/nginx // 輸出切割debug資訊 |
那麼至此,我們就知道logrotate是如何實現自動切割日誌的
logrotate配置案例
nginx 常用日誌切割配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/data/log/nginx/*.log /data/log/nginx/*/*.log { # 對匹配上的日誌檔案進行切割 weekly # 每週切割 missingok # 在日誌輪循期間,任何錯誤將被忽略,例如“檔案無法找到”之類的錯誤。 rotate 6 # 保留 6 個備份 compress # 壓縮 delaycompress # delaycompress 和 compress 一起使用時,轉儲的日誌檔案到下一次轉儲時才壓縮 notifempty # 如果是空檔案的話,不轉儲 create 0644 www-data ymserver # mode owner group 轉儲檔案,使用指定的檔案模式建立新的日誌檔案 sharedscripts # 下面詳細說 prerotate # 在logrotate轉儲之前需要執行的指令,例如修改檔案的屬性等動作;必須獨立成行 if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ run-parts /etc/logrotate.d/httpd-prerotate; \ fi \ endscript postrotate # 在logrotate轉儲之後需要執行的指令,例如重新啟動 (kill -HUP) 某個服務!必須獨立成行 [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid` endscript su root ymserver # 輪訓日誌時切換設定的使用者/使用者組來執行(預設是root),如果設定的user/group 沒有許可權去讓檔案容用 create 選項指定的擁有者 ,會觸發錯誤。 } |
如果要配置一個每日0點執行切割任務,怎麼做到?我們的logrotate預設每天執行時間已經寫到了/etc/cron.daily/目錄下面,而這個目錄下面的任務執行時間上面也說了,在/etc/crontab裡面定義了時6:25。我之前就有個這樣的需求,看看下面的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/data/log/owan_web/chn_download_stat/chn_app_rec.log { copytruncate # weekly 註釋了 但是會繼承/etc/logrorate.conf的全域性變數,也是weekly missingok rotate 10 compress delaycompress size=1000M # 大小到達size開始轉存 notifempty create 664 www-data ymserver su root dateext //這個引數很重要!就是切割後的日誌檔案以當前日期為格式結尾,如xxx.log-20131216這樣,如果註釋掉,切割出來是按數字遞增,即前面說的 xxx.log-1這種格式 compress //是否通過gzip壓縮轉儲以後的日誌檔案,如xxx.log-20131216.gz ;如果不需要壓縮,註釋掉就行 } |
然後去root的crontab配置一個0點執行的任務
1 2 |
wwwadm@host:/etc/logrotate.d$ sudo crontab -l -u root 0 0 * * * /usr/sbin/logrotate /etc/logrotate.d/web_roteate -fv >/tmp/logro.log 2>&1 |
因為logrotate的切割週期是weekly,每次切割都是根據上一個切割的時間來進行,如果距離上一次有一週時間,就會切割,但是我們設定了crontab的每天切割,既不會進入/etc/cron.daily/的每日切割,也不會每週切割。這樣就能完美定製自己想要的切割日誌時間
logrotate引數說明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
compress 通過gzip 壓縮轉儲以後的日誌 nocompress 不做gzip壓縮處理 create mode owner group 輪轉時指定建立新檔案的屬性,如create 0777 nobody nobody nocreate 不建立新的日誌檔案 delaycompress 和compress 一起使用時,轉儲的日誌檔案到下一次轉儲時才壓縮 nodelaycompress 覆蓋 delaycompress 選項,轉儲同時壓縮。 missingok 如果日誌丟失,不報錯繼續滾動下一個日誌 ifempty 即使日誌檔案為空檔案也做輪轉,這個是logrotate的預設選項。 notifempty 當日志檔案為空時,不進行輪轉 mail address 把轉儲的日誌檔案傳送到指定的E-mail 地址 olddir directory 轉儲後的日誌檔案放入指定的目錄,必須和當前日誌檔案在同一個檔案系統 noolddir 轉儲後的日誌檔案和當前日誌檔案放在同一個目錄下 sharedscripts 執行postrotate指令碼,作用是在所有日誌都輪轉後統一執行一次指令碼。如果沒有配置這個,那麼每個日誌輪轉後都會執行一次指令碼 prerotate 在logrotate轉儲之前需要執行的指令,例如修改檔案的屬性等動作;必須獨立成行 postrotate 在logrotate轉儲之後需要執行的指令,例如重新啟動 (kill -HUP) 某個服務!必須獨立成行 daily 指定轉儲週期為每天 weekly 指定轉儲週期為每週 monthly 指定轉儲週期為每月 rotate count 指定日誌檔案刪除之前轉儲的次數,0 指沒有備份,5 指保留5 個備份 dateext 使用當期日期作為命名格式 dateformat .%s 配合dateext使用,緊跟在下一行出現,定義檔案切割後的檔名,必須配合dateext使用,只支援 %Y %m %d %s 這四個引數 size(或minsize) log-size 當日志檔案到達指定的大小時才轉儲,log-size能指定bytes(預設)及KB (sizek)或MB(sizem). 當日志檔案 >= log-size 的時候就轉儲。 以下為合法格式:(其他格式的單位大小寫沒有試過) size = 5 或 size 5 (>= 5 個位元組就轉儲) size = 100k 或 size 100k size = 100M 或 size 100M |
值得注意的一個配置是:copytruncate
copytruncate
如果沒有這個選項的話,操作方式:是將原log日誌檔案,移動成類似log.1的舊檔案, 然後建立一個新的檔案。 如果設定了,操作方式:拷貝原日誌檔案,並且將其變成大小為0的檔案。
區別是如果程式,比如nginx 使用了一個檔案寫日誌,沒有copytruncate的話,切割日誌時, 把舊日誌log->log.1 ,然後建立新日誌log。這時候nginx 開啟的檔案描述符依然時log.1,由沒有訊號通知nginx 要換日誌描述符,所以它會繼續向log.1寫日誌,這樣就不符合我們的要求了。 因為我們想切割日誌後,nginx 自動會向新的log 檔案寫日誌,而不是舊的log.1檔案
解決方法有兩個:
1.向上面的nginx 切割日誌配置,再postrotate裡面寫個指令碼
1 2 3 |
postrotate # 在logrotate轉儲之後需要執行的指令,例如重新啟動 (kill -HUP) 某個服務!必須獨立成行 [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid` endscript |
這樣就是發訊號給nginx ,讓nginx 關閉舊日誌檔案描述符,重新開啟新的日誌檔案描述,並寫入日誌
2.使用copytruncate
引數,向上面說的,配置了它以後,操作方式是把log 複製一份 成為log.1,然後清空log的內容,使大小為0,那此時log依然時原來的舊log,對程式(nginx)來說,依然開啟的是原來的檔案描述符,可以繼續往裡面寫日誌,而不用傳送訊號給nginx
copytruncate這種方式操作的時候, 拷貝和清空之間有一個時間差,可能會丟失部分日誌資料。
nocopytruncate
備份日誌檔案不過不截斷