案例十7、歸檔老日誌

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

##說明:因爲咱們須要按照日誌大小切割,因此這個腳本寫完後,須要每分鐘執行一次。
相關文章
相關標籤/搜索