Linux日志定時(shí)輪詢流程詳解
logrotate介紹
對于Linux系統(tǒng)安全來說,日志文件是極其重要的工具。日志文件包含了關(guān)于系統(tǒng)中發(fā)生的事件的有用信息,在排障過程中或者系統(tǒng)性能分析時(shí)經(jīng)常被用到。當(dāng)日志文件不斷增長的時(shí)候,就需要定時(shí)切割,否則,寫日志的速度和性能也會(huì)下降,更不便于我們歸檔,查詢。
所以便有了使用logrotate的時(shí)候 ,logrotate是個(gè)十分有用的工具,它可以自動(dòng)對日志進(jìn)行截?cái)?或輪循)、壓縮以及刪除舊的日志文件。例如,你可以設(shè)置logrotate,讓/var/log/foo日志文件每30天輪循,并刪除超過6個(gè)月的日志。配置完后,logrotate的運(yùn)作完全自動(dòng)化,不必進(jìn)行任何進(jìn)一步的人為干預(yù)。
logrotate配置文件位置
Linux系統(tǒng)默認(rèn)安裝logrotate工具,它默認(rèn)的配置文件在:
- /etc/logrotate.conf
- /etc/logrotate.d/
logrotate.conf 才主要的配置文件,logrotate.d 是一個(gè)目錄,該目錄里的所有文件都會(huì)被主動(dòng)的讀入/etc/logrotate.conf中執(zhí)行。
另外,如果 /etc/logrotate.d/ 里面的文件中沒有設(shè)定一些細(xì)節(jié),則會(huì)以/etc/logrotate.conf這個(gè)文件的設(shè)定來作為默認(rèn)值。
實(shí)際運(yùn)行時(shí),Logrotate會(huì)調(diào)用配置文件/etc/logrotate.conf。
可以在/etc/logrotate.d目錄里放置自定義好的配置文件,用來覆蓋Logrotate的缺省值。
定時(shí)輪循機(jī)制
Logrotate是基于CRON來運(yùn)行的,其腳本是/etc/cron.daily/logrotate,日志輪轉(zhuǎn)是系統(tǒng)自動(dòng)完成的。
logrotate這個(gè)任務(wù)默認(rèn)放在cron的每日定時(shí)任務(wù)cron.daily下面 /etc/cron.daily/logrotate/etc/目錄下面還有cron.weekly/, cron.hourly/, cron.monthly/ 的目錄都是可以放定時(shí)任務(wù)的
- [/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
這里實(shí)際操作輪詢的命令***一行
- /usr/sbin/logrotate /etc/logrotate.conf
定義好了每日執(zhí)行任務(wù)的腳本cron.daily/logrotate ,再查看crontab的內(nèi)容,里面設(shè)置好了對應(yīng)的cron.xxly
執(zhí)行時(shí)間
- [/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/ 下面的任務(wù)都是每天6:25 執(zhí)行
- /etc/cron.weekly/ 下面的任務(wù)都是每周日 6:47 執(zhí)行
- /etc/cron.monthly/ 下面的任務(wù)都是每月1號 6:52 執(zhí)行
如果等不及cron自動(dòng)執(zhí)行日志輪轉(zhuǎn),想手動(dòng)強(qiáng)制切割日志,需要加-f參數(shù);
不過正式執(zhí)行前***通過Debug選項(xiàng)來驗(yàn)證一下(-d參數(shù)),這對調(diào)試也很重要
- # /usr/sbin/logrotate -f /etc/logrotate.d/nginx // 未到時(shí)間或者未到切割條件,強(qiáng)制切割
- # /usr/sbin/logrotate -d -f /etc/logrotate.d/nginx // 輸出切割debug信息
那么至此,我們就知道logrotate是如何實(shí)現(xiàn)自動(dòng)切割日志的
logrotate配置案例
nginx 常用日志切割配置
- /data/log/nginx/*.log /data/log/nginx/*/*.log { # 對匹配上的日志文件進(jìn)行切割
- weekly # 每周切割
- missingok # 在日志輪循期間,任何錯(cuò)誤將被忽略,例如“文件無法找到”之類的錯(cuò)誤。
- rotate 6 # 保留 6 個(gè)備份
- compress # 壓縮
- delaycompress # delaycompress 和 compress 一起使用時(shí),轉(zhuǎn)儲(chǔ)的日志文件到下一次轉(zhuǎn)儲(chǔ)時(shí)才壓縮
- notifempty # 如果是空文件的話,不轉(zhuǎn)儲(chǔ)
- create 0644 www-data ymserver # mode owner group 轉(zhuǎn)儲(chǔ)文件,使用指定的文件模式創(chuàng)建新的日志文件
- sharedscripts # 下面詳細(xì)說
- prerotate # 在logrotate轉(zhuǎn)儲(chǔ)之前需要執(zhí)行的指令,例如修改文件的屬性等動(dòng)作;必須獨(dú)立成行
- if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
- run-parts /etc/logrotate.d/httpd-prerotate; \
- fi \
- endscript
- postrotate # 在logrotate轉(zhuǎn)儲(chǔ)之后需要執(zhí)行的指令,例如重新啟動(dòng) (kill -HUP) 某個(gè)服務(wù)!必須獨(dú)立成行
- [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
- endscript
- su root ymserver # 輪訓(xùn)日志時(shí)切換設(shè)置的用戶/用戶組來執(zhí)行(默認(rèn)是root),如果設(shè)置的user/group 沒有權(quán)限去讓文件容用 create 選項(xiàng)指定的擁有者 ,會(huì)觸發(fā)錯(cuò)誤。
- }
如果要配置一個(gè)每日0點(diǎn)執(zhí)行切割任務(wù),怎么做到?我們的logrotate默認(rèn)每天執(zhí)行時(shí)間已經(jīng)寫到了/etc/cron.daily/目錄下面,而這個(gè)目錄下面的任務(wù)執(zhí)行時(shí)間上面也說了,在/etc/crontab里面定義了時(shí)6:25。我之前就有個(gè)這樣的需求,看看下面的配置
- /data/log/owan_web/chn_download_stat/chn_app_rec.log {
- copytruncate
- # weekly 注釋了 但是會(huì)繼承/etc/logrorate.conf的全局變量,也是weekly
- missingok
- rotate 10
- compress
- delaycompress
- size=1000M # 大小到達(dá)size開始轉(zhuǎn)存
- notifempty
- create 664 www-data ymserver
- su root
- dateext //這個(gè)參數(shù)很重要!就是切割后的日志文件以當(dāng)前日期為格式結(jié)尾,如xxx.log-20131216這樣,如果注釋掉,切割出來是按數(shù)字遞增,即前面說的 xxx.log-1這種格式
- compress //是否通過gzip壓縮轉(zhuǎn)儲(chǔ)以后的日志文件,如xxx.log-20131216.gz ;如果不需要壓縮,注釋掉就行
- }
然后去root的crontab配置一個(gè)0點(diǎn)執(zhí)行的任務(wù)
- 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
因?yàn)閘ogrotate的切割周期是weekly,每次切割都是根據(jù)上一個(gè)切割的時(shí)間來進(jìn)行,如果距離上一次有一周時(shí)間,就會(huì)切割,但是我們設(shè)置了crontab的每天切割,既不會(huì)進(jìn)入/etc/cron.daily/的每日切割,也不會(huì)每周切割。這樣就能***定制自己想要的切割日志時(shí)間
logrotate參數(shù)說明
compress 通過gzip 壓縮轉(zhuǎn)儲(chǔ)以后的日志 nocompress 不做gzip壓縮處理 create mode owner group 輪轉(zhuǎn)時(shí)指定創(chuàng)建新文件的屬性,如create 0777 nobody nobody nocreate 不建立新的日志文件 delaycompress 和compress 一起使用時(shí),轉(zhuǎn)儲(chǔ)的日志文件到下一次轉(zhuǎn)儲(chǔ)時(shí)才壓縮 nodelaycompress 覆蓋 delaycompress 選項(xiàng),轉(zhuǎn)儲(chǔ)同時(shí)壓縮。 missingok 如果日志丟失,不報(bào)錯(cuò)繼續(xù)滾動(dòng)下一個(gè)日志 ifempty 即使日志文件為空文件也做輪轉(zhuǎn),這個(gè)是logrotate的缺省選項(xiàng)。 notifempty 當(dāng)日志文件為空時(shí),不進(jìn)行輪轉(zhuǎn) mail address 把轉(zhuǎn)儲(chǔ)的日志文件發(fā)送到指定的E-mail 地址 olddir directory 轉(zhuǎn)儲(chǔ)后的日志文件放入指定的目錄,必須和當(dāng)前日志文件在同一個(gè)文件系統(tǒng) noolddir 轉(zhuǎn)儲(chǔ)后的日志文件和當(dāng)前日志文件放在同一個(gè)目錄下 sharedscripts 運(yùn)行postrotate腳本,作用是在所有日志都輪轉(zhuǎn)后統(tǒng)一執(zhí)行一次腳本。如果沒有配置這個(gè),那么每個(gè)日志輪轉(zhuǎn)后都會(huì)執(zhí)行一次腳本 prerotate 在logrotate轉(zhuǎn)儲(chǔ)之前需要執(zhí)行的指令,例如修改文件的屬性等動(dòng)作;必須獨(dú)立成行 postrotate 在logrotate轉(zhuǎn)儲(chǔ)之后需要執(zhí)行的指令,例如重新啟動(dòng) (kill -HUP) 某個(gè)服務(wù)!必須獨(dú)立成行 daily 指定轉(zhuǎn)儲(chǔ)周期為每天 weekly 指定轉(zhuǎn)儲(chǔ)周期為每周 monthly 指定轉(zhuǎn)儲(chǔ)周期為每月 rotate count 指定日志文件刪除之前轉(zhuǎn)儲(chǔ)的次數(shù),0 指沒有備份,5 指保留5 個(gè)備份 dateext 使用當(dāng)期日期作為命名格式 dateformat .%s 配合dateext使用,緊跟在下一行出現(xiàn),定義文件切割后的文件名,必須配合dateext使用,只支持 %Y %m%d %s 這四個(gè)參數(shù) size(或minsize) log-size 當(dāng)日志文件到達(dá)指定的大小時(shí)才轉(zhuǎn)儲(chǔ),log-size能指定bytes(缺省)及KB (sizek)或MB(sizem). 當(dāng)日志文件 >= log-size 的時(shí)候就轉(zhuǎn)儲(chǔ)。 以下為合法格式:(其他格式的單位大小寫沒有試過) size = 5 或 size 5 (>= 5 個(gè)字節(jié)就轉(zhuǎn)儲(chǔ)) size = 100k 或 size 100k size = 100M 或 size 100M
值得注意的一個(gè)配置是:copytruncate
copytruncate 如果沒有這個(gè)選項(xiàng)的話,操作方式:是將原log日志文件,移動(dòng)成類似log.1的舊文件, 然后創(chuàng)建一個(gè)新的文件。 如果設(shè)置了,操作方式:拷貝原日志文件,并且將其變成大小為0的文件。
區(qū)別是如果進(jìn)程,比如nginx 使用了一個(gè)文件寫日志,沒有copytruncate的話,切割日志時(shí), 把舊日志log->log.1 ,然后創(chuàng)建新日志log。這時(shí)候nginx 打開的文件描述符依然時(shí)log.1,由沒有信號通知nginx 要換日志描述符,所以它會(huì)繼續(xù)向log.1寫日志,這樣就不符合我們的要求了。 因?yàn)槲覀兿肭懈钊罩竞螅琻ginx 自動(dòng)會(huì)向新的log 文件寫日志,而不是舊的log.1文件
解決方法有兩個(gè):
1.向上面的nginx 切割日志配置,再postrotate里面寫個(gè)腳本
- postrotate # 在logrotate轉(zhuǎn)儲(chǔ)之后需要執(zhí)行的指令,例如重新啟動(dòng) (kill -HUP) 某個(gè)服務(wù)!必須獨(dú)立成行
- [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
- endscript
這樣就是發(fā)信號給nginx ,讓nginx 關(guān)閉舊日志文件描述符,重新打開新的日志文件描述,并寫入日志
2.使用copytruncate參數(shù),向上面說的,配置了它以后,操作方式是把log 復(fù)制一份 成為log.1,然后清空log的內(nèi)容,使大小為0,那此時(shí)log依然時(shí)原來的舊log,對進(jìn)程(nginx)來說,依然打開的是原來的文件描述符,可以繼續(xù)往里面寫日志,而不用發(fā)送信號給nginx
copytruncate這種方式操作的時(shí)候, 拷貝和清空之間有一個(gè)時(shí)間差,可能會(huì)丟失部分日志數(shù)據(jù)。
nocopytruncate 備份日志文件不過不截?cái)?/p>
參考