你真的搞懂logrotate了嗎?

logrotate機制&原理

centos系統中默認安裝logrotate,logrotate主配置文件:/etc/logrotate.conf,其中定義了系統默認的logrotate規則,當系統中安裝了RPM 軟件包時,使用include定義其子配置文件的位置:/etc/logrotate.d/*,include選項十分重要,一些應用把日誌轉儲參數存放在/etc/logrotate.d ,典型的應用有:apache,nginx,cron,syslog等,這樣,只要管理一個 /etc/logrotate.conf 文件就能夠了。
使用時配合crontab按期執行logrotate命令,cron的主配置文件/etc/anacrontab中定義了crontab的默認執行規則,其中系統自帶的每1天執行的cron計劃配置文件放在/etc/cron.daily/目錄下,在該目錄下的logrotate文件內容以下:node

#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi

該腳本天天定時執行一次,即系統默認的logrotate時間計劃。若是想更改系統默認的logrotate時間計劃,能夠將該文件挪走,而後在crontab中指定本身的時間計劃,如:nginx

#每兩天執行一次系統日誌切割
* * */2 * * /usr/sbin/logrotate -f /etc/logrotate.conf

logrotate實例解讀

關於logrotate的cron計劃在/etc/cron.daily/logrotate,與cron配合使用,春雨棄用系統自帶的cron計劃,制定cron以下:apache

cron計劃:
17 *   * * *  root    run-parts /etc/cron.hourly
47 23  * * *  root    run-parts /etc/cron.daily
47 6   * * 7  root    run-parts /etc/cron.weekly
52 6   1 * *  root    run-parts /etc/cron.monthly

即,在天天23:47執行/etc/cron.daily計劃下的操做,進行日誌切割,logrotate規則配置文件以下:centos

[root@control ~]$ ls /etc/logrotate.d/

系統日誌logrotate過程

  • 執行cron計劃
47 23  * * *  root    run-parts /etc/cron.daily
  • 執行/etc/cron.daily的logrotate文件
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
  • 執行/etc/logrotate.conf配置的規則,根據「include /etc/logrotate.d」參數執行/etc/logrotate.d/下的logrotate配置文件,系統日誌相關的是syslog:
/var/log/cron
/var/log/maillog
/var/log/secure
/var/log/messages
/var/log/spooler
{
    #每日切割
    daily
    #忽略執行過程當中的全部錯誤
    missingok
    #時間戳,默認是年月日;可使用dateformat參數自定義
    dateext
    #轉儲週期爲10天,十天前的日誌會被刪除
    rotate 10
    #不切割空日誌文件
    notifempty
    #一般prerotate和postrotate腳本爲每個輪轉的日誌運行,
    #sharedscripts的做用是使全部的日誌輪轉完成後再執行腳本
    sharedscripts
    #定義日誌切割完成後的操做,做用是從新定義進程日誌文件描述符,是日誌寫入新的日誌文件
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

項目日誌logrotate過程

nginx日誌logrotate過程

/usr/local/nginx/logs/*.log {
daily
dateext
rotate 10
missingok
# 不建立新日誌文件
nocreate
# notifempty
# compress  #壓縮切割後的日誌
sharedscripts
#發送USR1信號來通知Nginx從新打開日誌文件
postrotate
    /bin/kill -USR1 `cat /var/run/nginx.pid` || true
endscript
}

該過程與系統日誌切割的區別是對新生成的日誌文件的處理方式,由於程序日誌輸出所指向的位置是由文件的iNode號來識別的,因此nginx、uwsgi等程序的日誌在切割完成後須要執行postrotate指定的腳原本更新程序所指向的日誌文件inode。bash

uwsgi

/home/workspace/log/uwsgi/uwsgi.*log {
    # 每日輪詢
    daily
    # 舊日誌文件以更新日期命名
    dateext
    # 最多10個歸檔日誌,多餘10個,最先的日誌文件被刪除
    rotate 10
    # 在日誌輪循期間,任何錯誤將被忽略,例如「文件沒法找到」之類的錯誤。
    missingok
    # 不建立新日誌文件
    nocreate
    sharedscripts
    postrotate
         /bin/touch /home/workspace/scripts/uwsgi/touch_reopen_log
    endscript
}

關於postrotate

postrotate後面跟隨的是一個命令行,通常是用來從新生成日誌文件或者衝定義應用所指向的文件描述符(fd:file description),拿nginx和uwsgi爲例:post

nginx

  • 完成日誌切割後建立新的nginx日誌文件,此時該文件的fd發生改變
  • nginx中日誌輸出對應的文件fd未同步更新,nginx會向原fd對應的日誌文件寫數據
  • 「/bin/kill -USR1 cat /var/run/nginx.pid || true」,更新nginx默認日誌文件的fd到新建的日誌文件(該效果等同於reload)。

uwsgi

  • uwsgi不能經過reload方式建立本身的log文件
  • logrotate配置文件中使用參數create建立新的uwsgi日誌文件
  • touch-logreopen參數:當指定的文件被touch事後,會讓uwsgi重定向日誌輸出對應的文件fd,而且不會終止當前的服務(不是stop+start,而是reload的概念)
  • logrotate配置文件postrotate:「/bin/touch /home/workspace/scripts/uwsgi/touch_reopen_log」

日誌rotate方式

logrotate提供了兩種日誌rotate方式,兩種方式的區別在於新的日誌文件的處理方式。url

  • 一種就如上面nginx所述,在完成rotate以後建立新文件,而後更新程序的日誌文件描述符指向到新日誌文件(即將新日誌寫入新日誌文件) ;
  • 另外一種方式叫作copytruncate,該方式是先建立新文件存儲舊日誌,而後清空舊日誌文件(echo 「」 > old_logfile),此時文件的iNode號不會發生改變,新產生的日誌會繼續寫入舊的日誌文件中(能夠簡單的理解爲舊日誌內容作了一次備份),須要注意的是,該方法會有部分日誌丟失:日誌在拷貝完到清空文件這段時間內,程序輸出的日誌沒有備份就清空了。

綜上,優先選用第一種方法進行日誌切割。spa

copytruncate模式實例

/data/logs/*/*.log
{
    daily
    missingok
    dateext
    rotate 30
    notifempty
    copytruncate
}

關於/bin/kill -HUP

"/bin/kill -USR1 `cat /var/run/nginx.pid` || true"

看到這條命令很容易想到:操作系統

/bin/kill -HUP `cat /var/run/nginx.pid 2> /dev/null` 2> /dev/null || true

這兩條命令的大概含義是重載nginx服務,目的是從新生成nginx的日誌文件。命令行

>/dev/null 2>&1,/dev/zero

/dev/null

/dev/null:是設備自帶的一個控設備,能夠理解爲一個黑洞文件,寫入它的全部東西都將消失,一般被用於丟棄不須要的輸出流。

/dev/zero

在類Unix操做系統中,/dev/zero是一個特殊文件,當你讀到它時,它會提供無線的空字符,其中的一個典型用法是用它提供的字符流來覆蓋信息,另外一個常見用法是產生一個特定大小的空白文件(在臨時增長swap空間時有用到)。

2>&1

這個實際上是三個部分組成的:2,>&,1 。在/usr/include/unistd.h中,你能夠找到以下代碼:

#define STDIN_FILENO    0   #define STDOUT_FILENO   1   #define STDERR_FILENO   2

2表示stderr;1表示stdout;0表示stdin,而「&>」則表示把符號左邊的內容以符號右邊的形式輸出。

相關文章
相關標籤/搜索