案例十七、归档老日志
作者:互联网
Linux系统中有日志切割的工具logrotate,它可以按照我们的预期按时间或者大小来切割和归档老的日志,它还可以压缩切割后的日志,也可以定义老日志保留的时间。
本案例的需求是用shell脚本来实现类似logrotate的功能,具体要求如下:
1)要处理的日志路径:/data/logs/1.log
2)每天0点0分切割日志
3)老日志保留一周
4)归档后的日志名字为:1.log.1,1.log.2,... ,1.log.7
5)假设日志归档后,新日志可以自动生成
知识点一:logrotate
先声明,本案例脚本并不会引用该部分知识点,在这里仅做简单介绍,下面通过一段配置解释其含义。
/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和continue
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 ##说明:由于我们需要按照日志大小切割,所以这个脚本写完后,需要每分钟执行一次。
标签:log.1,脚本,十七,log,echo,归档,日志,切割 来源: https://blog.51cto.com/13576245/2430643