對於線上業務而言,打印日誌是一個系統運行情況的全面體檢,日誌打得約詳細,越容易查找問題,可是機器磁盤是有限的,這時候很容易將磁盤撐爆。因此打印日誌多少要選取一個平衡,打印適量的日誌,只在關鍵環節,容易出錯的地方打印日誌便可。可是隨着業務量的提高,即便咱們控制了打印日誌的頻率,但日誌文件的容量也在大量擴大。若是咱們對日誌文件的處理方式不當,日誌文件將打到磁盤上線,新業務就再也刷不出來任何日誌了。linux
所以,咱們對日誌的處理通常分爲三個步驟:web
主流的日誌服務組件都是支持日誌文件時間切分的,以loabgck爲例,看一個典型的logback配置logback.xmlshell
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!--自定義變量--> <property name="LOG_NAME" value="MyApp"/> <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg,50是logger名稱最大長度:日誌消息,%n是換行符--> <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}- %msg%n"/> <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="UTF-8"> <!--%highlight(%-5level) %cyan表示高亮日誌等級,並使用藏青色打印logger部分--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}) - %msg%n</pattern> </encoder> </appender> <!-- 輸出格式 appender --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${catalina.base}/logs/${LOG_NAME}.log</file> <encoder charset="UTF-8"> <pattern>${LOG_PATTERN}</pattern> </encoder> <!--按照logback提供的時間切分策略分隔日誌文件--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${catalina.base}/logs/${LOG_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> </appender> <!-- error 日誌 appender --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${catalina.base}/logs/${LOG_NAME}_error.log</file> <!--過濾器,只有級別高於ERROR以上的纔會打印,級別包括:TRACE < DEBUG < INFO < WARN < ERROR--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> <encoder charset="UTF-8"> <pattern>${LOG_PATTERN}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${catalina.base}/logs/${LOG_NAME}_error.%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> </appender> <!--自定義包下面的日誌級別 name是包結構 level是級別 addtivity:是否向上級logger傳遞打印信息。默認是true--> <logger name="com.myApp" level="INFO" addtivity="true"> <appender ref="FILE"/> </logger> <!--默認的日誌級別,若是上面的logger沒有命中,則按照root的級別打印日誌,root是全部logger的父節點,若是addtivity是false,則不會拋到這裏--> <root level="ERROR"> <appender-ref ref="FILE"/> <appender-ref ref="ERROR_FILE"/> </root> </configuration>
經過上面的logback配置,當天的日誌會打印到myApp/logs/myApp.log與myApp/logs/myApp_error.log,分別對應的是info日誌與error日誌。當到達24點以後,昨天的日誌會重命名爲myApp/logs/myApp.2017-09-06.log與myApp/logs/myApp_error.2017-09-06.log。與此同時,當天的日誌會打印到myApp/logs/myApp.log中。bash
這樣就作到了按時間分割日誌文件,歷史日誌文件按照固定格式重命名。app
因爲線上機器都是linux操做系統,咱們可使用crontab腳本進行文件壓縮與刪除。less
操做流程分爲3步:webapp
做爲一個crontab腳本,就是充分發揮shell命令強度的時候了。顯然,這是一個shell腳本能夠完成的功能,直接看最終版。ui
#!/bin/bash # # # ZIPDATE=$(date +%F -d "-1 day"); DELDATE=$(date +%F -d "-10 day"); SECOND=$(echo $RANDOM | cut -c1-3) sleep $SECOND for i in `find /webapps/ -maxdepth 2 \( -type d -o -type l \) -name logs`; do find -L $i -maxdepth 1 -type f \( -name "*${ZIPDATE}*" -a ! -name "*.gz" \) -exec gzip {} \; find -L $i -maxdepth 1 -type f \( -name "*${DELDATE}*" -a -name "*.gz" \) -exec rm -f {} \; done
首先定義了三個變量,舉例:spa
ZIPDATE是前一天的日期yyyy-MM-dd格式:2017-09-06操作系統
DELDATE是要刪除的10天前的日期yyyy-MM-dd格式:2017-08-28
SECOND是隨即生成的3爲數,用來休眠定時腳本,避免多個腳本同時執行,形成cpu集中計算。。
下面的for循環是真正的處理邏輯。for i in `find /webapps/ -maxdepth 2 \( -type d -o -type l \) -name logs`;
do
…………
done
外層的邏輯是:查找/webapps/目錄下的最深層級是2的文件,由於不一樣的項目都會可能在同一臺機器的webapps目錄下,不一樣的項目下都會有logs目錄用來存放日誌文件。查詢條件是文件是文件夾類型或者連接類型,名字是logs。這樣咱們就找到了全部logs文件夾。
這時候看裏層邏輯:
find -L $i -maxdepth 1 -type f \( -name "*${ZIPDATE}*" -a ! -name "*.gz" \) -exec gzip {} \;
查找logs文件夾下,層級是1的即logs文件夾下的,名字包含昨天日期同時結尾不是.gz格式的文件,由於咱們的目標是壓縮爲gz格式,這裏避免重複壓縮。查找到這些文件以後,運行gzip命令進行壓縮。
這裏依賴的是find命令的-exec擴展功能。能夠參考find命令的手冊:
-exec command ;
Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ‘;’
is encountered. The string ‘{}’ is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in
arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a ‘\’) or quoted to protect them from
expansion by the shell. See the EXAMPLES section for examples of the use of the -exec option. The specified command is run once for each matched file.
The command is executed in the starting directory. There are unavoidable security problems surrounding use of the -exec action; you should use the
-execdir option instead.
-exec command {} +
This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the
end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that
xargs builds its command lines. Only one instance of ‘{}’ is allowed within the command. The command is executed in the starting directory.
一樣的,刪除n天前文件也是使用shell實現的。
find -L $i -maxdepth 1 -type f \( -name "*${DELDATE}*" -a -name "*.gz" \) -exec rm -f {} \;
cron服務是linux的內置服務,但它不會開機自動啓動。能夠用如下命令啓動和中止服務:
/sbin/service crond start
/sbin/service crond stop
/sbin/service crond restart
/sbin/service crond reload
以上1-4行分別爲啓動、中止、重啓服務和從新加載配置。
要把cron設爲在開機的時候自動啓動,在 /etc/rc.d/rc.local 腳本中加入 /sbin/service crond start
便可
查看當前用戶的crontab,輸入 crontab -l;
編輯crontab,輸入 crontab -e;
刪除crontab,輸入 crontab -r
這時候,加入咱們上面定時任務:
天天0點5分執行這個腳本,不過腳本內自己會隨機休眠100-999秒。
5 0 * * * sh /myTask/log_daily.sh 1>/dev/null
本文提供了一種處理線上日誌的方法,具體實現是經過logback進行按日期切分,ctontab定時壓縮與刪除。在這個思路下,實現按小時切分以及其餘的切分方案都是可行的,只要新文件名與crontab中定位的文件名一致便可。