linux基礎:日誌定時輪詢詳解

logrotate介紹

對於Linux系統安全來講,日誌文件是極其重要的工具。日誌文件包含了關於系統中發生的事件的有用信息,在排障過程當中或者系統性能分析時常常被用到。當日志文件不斷增加的時候,就須要定時切割,不然,寫日誌的速度和性能也會降低,更不便於咱們歸檔,查詢。因此便有了使用logrotate的時候 ,logrotate是個十分有用的工具,它能夠自動對日誌進行截斷(或輪循)、壓縮以及刪除舊的日誌文件。例如,你能夠設置logrotate,讓/var/log/foo日誌文件每30天輪循,並刪除超過6個月的日誌。配置完後,logrotate的運做徹底自動化,沒必要進行任何進一步的人爲干預。html

logrotate配置文件位置

Linux系統默認安裝logrotate工具,它默認的配置文件在:/etc/logrotate.conf/etc/logrotate.d/nginx

logrotate.conf 才主要的配置文件,logrotate.d 是一個目錄,該目錄裏的全部文件都會被主動的讀入/etc/logrotate.conf中執行。另外,若是 /etc/logrotate.d/ 裏面的文件中沒有設定一些細節,則會以/etc/logrotate.conf這個文件的設定來做爲默認值。web

實際運行時,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/ 的目錄都是能夠放定時任務的vim

[/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複製代碼

這裏實際操做輪詢的命令最後一行安全

定義好了每日執行任務的腳本cron.daily/logrotate ,再查看crontab的內容,裏面設置好了對應的cron.xxly
執行時間複製代碼

[/etc]$ vim /etc/crontabSHELL=/bin/shPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binapp

m h dom mon dow user command

17 root cd / && run-parts --report /etc/cron.hourly25 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 )dom

能夠看出來了只要是在
* /etc/cron.daily/ 下面的任務都是天天6:25 執行
* /etc/cron.weekly/ 下面的任務都是每週日 6:47 執行
* /etc/cron.monthly/ 下面的任務都是每個月1號  6:52 執行

若是等不及cron自動執行日誌輪轉,想手動強制切割日誌,須要加-f參數;
不過正式執行前最好經過Debug選項來驗證一下(-d參數),這對調試也很重要複製代碼

/usr/sbin/logrotate -f /etc/logrotate.d/nginx // 未到時間或者未到切割條件,強制切割

/usr/sbin/logrotate -d -f /etc/logrotate.d/nginx // 輸出切割debug信息

那麼至此,咱們就知道logrotate是如何實現自動切割日誌的


## logrotate配置案例
nginx 經常使用日誌切割配置複製代碼

/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 endscriptpostrotate # 在logrotate轉儲以後須要執行的指令,例如從新啓動 (kill -HUP) 某個服務!必須獨立成行[ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`endscriptsu root ymserver # 輪訓日誌時切換設置的用戶/用戶組來執行(默認是root),若是設置的user/group 沒有權限去讓文件容用 create 選項指定的擁有者 ,會觸發錯誤。}工具

---
若是要配置一個每日0點執行切割任務,怎麼作到?咱們的logrotate默認天天執行時間已經寫到了/etc/cron.daily/目錄下面,而這個目錄下面的任務執行時間上面也說了,在/etc/crontab裏面定義了時6:25。我以前就有個這樣的需求,看看下面的配置
複製代碼

/data/log/owanweb/chndownloadstat/chnapp_rec.log {copytruncatepost

weekly 註釋了 可是會繼承/etc/logrorate.conf的全局變量,也是weekly

missingokrotate 10compressdelaycompresssize = 1000M # 大小到達size開始轉存 若是設置了size,會無視 daily, weekly,monthly 指令,因此size的優先級比較高notifemptycreate 664 www-data ymserversu rootdateext //這個參數很重要!就是切割後的日誌文件以當前日期爲格式結尾,如xxx.log-20131216這樣,若是註釋掉,切割出來是按數字遞增,即前面說的 xxx.log-1這種格式compress //是否經過gzip壓縮轉儲之後的日誌文件,如xxx.log-20131216.gz ;若是不須要壓縮,註釋掉就行}

而後去root的crontab配置一個0點執行的任務複製代碼

wwwadm@host:/etc/logrotate.d$ sudo crontab -l -u root0 0 * /usr/sbin/logrotate /etc/logrotate.d/web_roteate -fv >/tmp/logro.log 2>&1

由於logrotate的切割週期是weekly,每次切割都是根據上一個切割的時間來進行,若是距離上一次有一週時間,就會切割,可是咱們設置了crontab的天天切割,既不會進入/etc/cron.daily/的每日切割,也不會每週切割。這樣就能完美定製本身想要的切割日誌時間

## logrotate參數說明複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
複製代碼
當日志文件 >= log-size 的時候就轉儲。 如下爲合法格式:(其餘格式的單位大小寫沒有試過)
size = 5 或 size 5 (>= 5 個字節就轉儲)
size = 100k 或 size 100k
size = 100M 或 size 100M
** 若是設置了size,會無視 daily, weekly,monthly 指令,因此size的優先級比較高 ** 

**值得注意的一個配置是:copytruncate**複製代碼

區別是若是進程,好比nginx 使用了一個文件寫日誌,沒有copytruncate的話,切割日誌時, 把舊日誌log->log.1 ,而後建立新日誌log。這時候nginx 打開的文件描述符依然時log.1,由沒有信號通知nginx 要換日誌描述符,因此它會繼續向log.1寫日誌,這樣就不符合咱們的要求了。 由於咱們想切割日誌後,nginx 自動會向新的log 文件寫日誌,而不是舊的log.1文件

解決方法有兩個:

  1. 向上面的nginx 切割日誌配置,再postrotate裏面寫個腳本
postrotate  # 在logrotate轉儲以後須要執行的指令,例如從新啓動 (kill -HUP) 某個服務!必須獨立成行
        [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
    endscript複製代碼

這樣就是發信號給nginx ,讓nginx 關閉舊日誌文件描述符,從新打開新的日誌文件描述,並寫入日誌

  1. 使用copytruncate參數,向上面說的,配置了它之後,操做方式是把log 複製一份 成爲log.1,而後清空log的內容,使大小爲0,那此時log依然時原來的舊log,對進程(nginx)來講,依然打開的是原來的文件描述符,能夠繼續往裏面寫日誌,而不用發送信號給nginx

copytruncate這種方式操做的時候, 拷貝和清空之間有一個時間差,可能會丟失部分日誌數據。`

參考

[Linux下logrotate日誌輪詢操做梳理](http://www.cnblogs.com/kevingrace/p/6307298.html)

關於我

若是文章對你有收穫,能夠收藏轉發,這會給我一個大大鼓勵喲!另外能夠關注我公衆號【碼農富哥】 (coder2025),我會持續輸出原創的算法,計算機基礎文章!

相關文章
相關標籤/搜索