1. 程式人生 > >Linux 日誌定時輪詢流程詳解

Linux 日誌定時輪詢流程詳解

logrotate介紹

對於Linux系統安全來說,日誌檔案是極其重要的工具。日誌檔案包含了關於系統中發生的事件的有用資訊,在排障過程中或者系統性能分析時經常被用到。當日志文件不斷增長的時候,就需要定時切割,否則,寫日誌的速度和效能也會下降,更不便於我們歸檔,查詢。

所以便有了使用logrotate的時候 ,logrotate是個十分有用的工具,它可以自動對日誌進行截斷(或輪循)、壓縮以及刪除舊的日誌檔案。例如,你可以設定logrotate,讓/var/log/foo日誌檔案每30天輪循,並刪除超過6個月的日誌。配置完後,logrotate的運作完全自動化,不必進行任何進一步的人為干預。

logrotate配置檔案位置

Linux系統預設安裝logrotate工具,它預設的配置檔案在:

12 /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/ 的目錄都是可以放定時任務的

123456789101112131415 [/etc]$cat/etc/cron.daily/logrotate#!/bin/sh# Clean non existent log file entries from status filecd/var/lib/logrotatetest-estatus||touch statushead-1status>status.cleansed's/"//g'status|whileread logfile datedo[-e"$logfile"]&&echo"\"$logfile\" $date"done>>status.cleanmv status.clean statustest-x/usr/sbin/logrotate||exit0/usr/sbin/logrotate/etc/logrotate.conf

這裡實際操作輪詢的命令最後一行
/usr/sbin/logrotate /etc/logrotate.conf

定義好了每日執行任務的指令碼cron.daily/logrotate ,再檢視crontab的內容,裡面設定好了對應的cron.xxly

執行時間

123456789 [/etc]$vim/etc/crontabSHELL=/bin/shPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin# m h dom mon dow user    command17****root    cd/&&run-parts--report/etc/cron.hourly256***root    test-x/usr/sbin/anacron||(cd/&&run-parts--report/etc/cron.daily)476**7root    test-x/usr/sbin/anacron||(cd/&&run-parts--report/etc/cron.weekly)5261**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引數),這對除錯也很重要

12 # /usr/sbin/logrotate -f /etc/logrotate.d/nginx  // 未到時間或者未到切割條件,強制切割# /usr/sbin/logrotate -d -f /etc/logrotate.d/nginx // 輸出切割debug資訊

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

logrotate配置案例

nginx 常用日誌切割配置

12345678910111213141516171819 /data/log/nginx/*.log /data/log/nginx/*/*.log{# 對匹配上的日誌檔案進行切割weekly# 每週切割missingok# 在日誌輪循期間,任何錯誤將被忽略,例如“檔案無法找到”之類的錯誤。rotate6# 保留 6 個備份compress# 壓縮delaycompress# delaycompress 和 compress 一起使用時,轉儲的日誌檔案到下一次轉儲時才壓縮notifempty# 如果是空檔案的話,不轉儲create0644www-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。我之前就有個這樣的需求,看看下面的配置

1234567891011121314 /data/log/owan_web/chn_download_stat/chn_app_rec.log{copytruncate# weekly 註釋了 但是會繼承/etc/logrorate.conf的全域性變數,也是weeklymissingokrotate10compressdelaycompresssize=1000M# 大小到達size開始轉存notifemptycreate664www-data ymserversu rootdateext//這個引數很重要!就是切割後的日誌檔案以當前日期為格式結尾,如xxx.log-20131216這樣,如果註釋掉,切割出來是按數字遞增,即前面說的 xxx.log-1這種格式compress//是否通過gzip壓縮轉儲以後的日誌檔案,如xxx.log-20131216.gz ;如果不需要壓縮,註釋掉就行}

然後去root的crontab配置一個0點執行的任務

12 wwwadm@host:/etc/logrotate.d$sudo crontab-l-uroot00***/usr/sbin/logrotate/etc/logrotate.d/web_roteate-fv>/tmp/logro.log2>&1

因為logrotate的切割週期是weekly,每次切割都是根據上一個切割的時間來進行,如果距離上一次有一週時間,就會切割,但是我們設定了crontab的每天切割,既不會進入/etc/cron.daily/的每日切割,也不會每週切割。這樣就能完美定製自己想要的切割日誌時間

logrotate引數說明

1234567891011121314151617181920212223242526 compress通過gzip壓縮轉儲以後的日誌nocompress不做gzip壓縮處理create mode owner group輪轉時指定建立新檔案的屬性,如create0777nobody nobodynocreate不建立新的日誌檔案delaycompresscompress一起使用時,轉儲的日誌檔案到下一次轉儲時才壓縮nodelaycompress覆蓋delaycompress選項,轉儲同時壓縮。missingok如果日誌丟失,不報錯繼續滾動下一個日誌ifempty即使日誌檔案為空檔案也做輪轉,這個是logrotate的預設選項。notifempty當日志文件為空時,不進行輪轉mail address把轉儲的日誌檔案傳送到指定的E-mail地址olddir directory轉儲後的日誌檔案放入指定的目錄,必須和當前日誌檔案在同一個檔案系統noolddir轉儲後的日誌檔案和當前日誌檔案放在同一個目錄下sharedscripts執行postrotate指令碼,作用是在所有日誌都輪轉後統一執行一次指令碼。如果沒有配置這個,那麼每個日誌輪轉後都會執行一次指令碼prerotatelogrotate轉儲之前需要執行的指令,例如修改檔案的屬性等動作;必須獨立成行postrotatelogrotate轉儲之後需要執行的指令,例如重新啟動(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=5size5>=5個位元組就轉儲)size=100ksize100ksize=100Msize100M

值得注意的一個配置是: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裡面寫個指令碼

123 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 備份日誌檔案不過不截斷

參考