Linux系統中有日誌切割的工具logrotate,它能夠按照咱們的預期按時間或者大小來切割和歸檔老的日誌,它還能夠壓縮切割後的日誌,也能夠定義老日誌保留的時間。shell
本案例的需求是用shell腳原本實現相似logrotate的功能,具體要求以下:bash
1)要處理的日誌路徑:/data/logs/1.logide
2)天天0點0分切割日誌函數
3)老日誌保留一週工具
4)歸檔後的日誌名字爲:1.log.1,1.log.2,... ,1.log.7post
5)假設日誌歸檔後,新日誌能夠自動生成spa
知識點一:logrotate日誌
先聲明,本案例腳本並不會引用該部分知識點,在這裏僅作簡單介紹,下面經過一段配置解釋其含義。ip
/var/log/messages { //日誌的路徑 rotate 5 //保留5份歸檔後的日誌 weekly //一週切割一次 postrotate //定義切割日以後,要執行的指令 /usr/bin/killall -HUP syslogd //重載syslogd服務,這樣會生成新的/var/log/messages文件 endscript //表示執行shell命令到此結束 } "/var/log/httpd/access.log" /var/log/httpd/error.log { //同時寫多個日誌的路徑 rotate 5 mail www@my.org //把歸檔後的日誌發送給該郵箱 size 100k //當日志文件達到100k時開始作切割 sharedscripts //對於第一行定義的全部日誌來講,如下的shell命令(/usr/bin/killall -HUP httpd)只運行一次,而不是每切割一個日誌就執行一次。 postrotate /usr/bin/killall -HUP httpd endscript } /var/log/news/* { //支持*通配 monthly //一個月切割一第二天志 rotate 2 //保留2個歸檔日誌 olddir /var/log/news/old //將切割後的日誌保存到這個目錄下面 missingok //若是日誌文件丟失,不報錯 postrotate kill -HUP 'cat /var/run/inn.pid' endscript nocompress //歸檔後的日誌不壓縮,與其相對的參數是compress }
知識點二:shell中的exit、break和continueit
1)exit
在shell腳本中使用exit,則直接退出當前腳本,exit後續的全部指令都再也不執行,示例腳本exit.sh:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then exit 1 fi echo $i done echo aaaaa
執行腳本,結果以下:
# sh exit.sh 1 1 2 2 3
exit後面能夠跟一個數字,表示該腳本的返回值,執行完腳本後,執行echo $?能夠打印腳本的返回值。
# echo $? 1
2)break
在shell腳本的循環中,可使用break跳出循環體,示例腳本break.sh:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then break fi echo $i done echo aaaaa
執行腳本,結果以下:
# sh break.sh 1 1 2 2 3 aaaaa
說明:當$i爲3時,遇到break指令,此時會跳出整個循環,從而執行echo aaaaa指令。
3)continue
和break相似,continue的做用是結束本次循環,繼續下一次循環,而不會結束整個循環體,示例腳本continue.sh:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then continue fi echo $i done echo aaaaa
執行腳本,結果以下:
# sh continue.sh 1 1 2 2 3 4 4 5 5 aaaaa
說明:當$i=3時,遇到continue指令,此時結束本次循環,即continue後面的指令echo $i再也不執行,繼續後續循環,即i=4。
本案例參考腳本
#!/bin/bash #日誌切割歸檔,按天切割,1.log變1.log.1, 1.log.1變1.log.2, ... #做者: #日期: logdir=/data/logs/ #定義函數,若是一個文件存在,則刪除 function e_df() { if [ -f $1 ] then rm -f $1 fi } cd $logdir #從7到2,依次遍歷循環 for i in `seq 7 -1 2` do #$i2比$i小1 i2=$[$i-1] #首先判斷1.log.7是否存在,若存在則刪除 e_df 1.log.$i #當1.log.6存在,則把1.log.6更名爲1.log.7,依次類推 if [ -f 1.log.$i2 ] then mv 1.log.$i2 1.log.$i fi done #因爲1.log後面無後綴,因此不能走上面的for循環,只能另外拿出來處理 e_df 1.log.1 mv 1.log 1.log.1 ##說明:這個腳本寫完後,放到任務計劃裏,天天0點0分執行。
需求擴展
如今的需求是,日誌按大小來切割,好比當日志大於等於100M時,則須要處理,處理後的日誌須要壓縮,而且延遲一天,即1.log.1不用壓縮,其餘須要壓縮。
#!/bin/bash #日誌切割歸檔,按日誌大小切割(100M),1.log變1.log.1, 1.log.1變1.log.2, ... #做者: #日期: logdir=/data/logs/ #技術1.log大小 size=`du -sk $logdir/1.log |awk '{print $1}` #若是1.log小於100M,則退出腳本 if [ $size -lt 10240 ] then exit 0 fi #定義函數,若是一個文件存在,則刪除 function e_df() { if [ -f $1 ] then rm -f $1 fi } cd $logdir #若是1.log.1存在,則先把它壓縮爲1.log.1.gz,這樣下面的for循環纔不會出錯 if [ -f 1.log.1 ] then gzip 1.log.1 fi #因爲1.log.1已經被壓縮爲1.log.gz,因此能夠直接將1.log更名爲1.log.1 mv 1.log 1.log.1 #從7到2,倒序循環 for i in `seq 7 -1 2` do #$i2比$i小1 i2=$[$i-1] #首先判斷1.log.7.gz是否存在,若存在則刪除 e_df 1.log.$i.gz #當1.log.6.gz存在,則把1.log.6.gz更名爲1.log.7.gz,依次類推 if [ -f 1.log.$i2.gz ] then mv 1.log.$i2.gz 1.log.$i.gz fi done ##說明:因爲咱們須要按照日誌大小切割,因此這個腳本寫完後,須要每分鐘執行一次。