目录

『日志备份与logrotate自实现』

日志备份与logrotate自实现

  1. 将源目录指定天数之前的老存档压缩,并保留指定天数之内的文件,可供直接查看。
  2. 将压缩后的移动到指定目的目录(并保持目录结构)
  3. 清理目的目录中文件时间在指定天数之前的文件(默认保留180天)。
  4. 记录脚本执行日志(并自动清理日志,默认保留脚本执行记录日志31天,按周生成)
    1. 但脚本写了2种方法:另一种是保留指定大小,当日志量输出小时,不影响按天生成。当日志量大时,可能会清除超额输出的日志。

#!/bin/sh
#author catsnyne@gmail.com<amos>

#You will be change the four parameters below.
#the directory to move and gzip
#samples: Don't add slash last
#SRC_DIR="/opt/tomcat/logs"
#DST_DIR="/nas/tomcat_logs_backup_180_days/tomcat_node1"
SRC_DIR="/opt/tomcat/logs"
DST_DIR="/nas/tomcat_logs_backup_180_days/tomcat_node1"
KEEPDATE="7"

#shell logs def
SHELL_LOG="/tmp/find_gzip_mv_tail.log"
SHELL_LOG_SIZE="10240K"
RM_DATE="180"
SHELL_LOGKEEPDATES="31"

function clean_logs() {
#u=1-7,U=1-53
    WEEK_OF_DAY=`date +%u`
    WWWW=$(( $WEEK_OF_DAY % 7 ))
    if [ $WWWW == 0 ]; then
        mv $SHELL_LOG $SHELL_LOG-`date "+%Y-%m-%d"`
        #echo -e "## Record Form date "$(date -d "`date` -7 day " +%Y-%m-%d)
        echo -e "## Record Form date time: "$(date  +"%Y-%m-%d %H:%M:%S") >> $SHELL_LOG
    fi
    #export SHELL_LOG="/tmp/find_gzip_mv_tail.log" ;echo ${SHELL_LOG##*/};
    find  `dirname $SHELL_LOG` -maxdepth 1 -type f -mtime +$SHELL_LOGKEEPDATES -name  ${SHELL_LOG##*/}-* | xargs rm -rvf {}
}

#move list
echo "##### Backup move Begin ########################################"  >> $SHELL_LOG
echo -e "## Record Form date time: "$(date  +%Y-%m-%d)" "$(date  +%H:%M:%S) >> $SHELL_LOG; echo -e "\n"$SRC_DIR" ---> "$DST_DIR"\n###"  >> $SHELL_LOG;
FOUNDFILENUM=`find $SRC_DIR -type f -mtime +$KEEPDATE | xargs ls -alh {} 2>/dev/null | cat | awk 'END{print NR}'`
if [ $FOUNDFILENUM -gt 0 ];then
    tail -c $SHELL_LOG_SIZE $SHELL_LOG > $SHELL_LOG.temp
    yes | mv $SHELL_LOG.temp $SHELL_LOG
    echo "There are "$FOUNDFILENUM" files found to be backup ... " >> $SHELL_LOG
    find $SRC_DIR -type f -mtime +$KEEPDATE | xargs ls -alh {} 2>/dev/null >> $SHELL_LOG
    find $SRC_DIR -type f -mtime +$KEEPDATE ! -name *.gz -exec gzip {} \;
    echo "### rsync move list "  >> $SHELL_LOG
    /usr/bin/rsync -azvt -b --suffix=.old  --include="*.gz"  --include="*/"  --exclude="*"  $SRC_DIR  $DST_DIR  >> $SHELL_LOG
    #/usr/bin/rsync -azvt -b --suffix=.old  --remove-source-files  --include="*.gz"  --include="*/"  --exclude="*"  $SRC_DIR  $DST_DIR  >> $SHELL_LOG
    echo -e "### rsync exec successfully "  >> $SHELL_LOG
else
    echo -e "++++Nothing Found to be backup, but always will be clear old backup files \n"  >> $SHELL_LOG
fi

echo -e "##### clean old file list before "$RM_DATE" days #" >> $SHELL_LOG
find $SRC_DIR -type f -mtime +$RM_DATE | xargs rm -vrf {} 1>> $SHELL_LOG  2>/dev/null 
echo "##### Bakup or Move Successfully End #################################"  >> $SHELL_LOG
echo -e "^_^ \n\n\n"  >> $SHELL_LOG
clean_logs

涉及命令

目录与文件名获取

dir_file

basename 获取文件名 dirname 获取目录名 readlink 获取文件绝对路径

dirname的用处是: 输出已经去除了尾部的”/”字符部分的名称;如果名称中不包含”/”, 则显示”.”(表示当前目录)。

$ basename /tmp/find_gzip_mv_tail.log
find_gzip_mv_tail.log
$ readlink -f deploy-small.sh
/home/centos/tmp/706/deploy-small.sh
$ readlink -f deploy-small.sh
/home/centos/tmp/706/deploy-small.sh
$ dirname deploy-small.sh
.
$ dirname /home/centos/tmp/706/deploy-small.sh 
/home/centos/tmp/706
把两个命令结合起来,就可以获取shell运行的目录

$ dirname $(readlink -f deploy-small.sh)
/home/centos/tmp/706
或者

$ readlink -f $(dirname deploy-small.sh)
/home/centos/tmp/706
在shell script 中的具体应用
先获取路径,再获取绝对路径

#!/usr/bin/env bash
DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
echo $DIR

#参数解释:
BASH_SOURCE[0] 等价于 BASH_SOURCE, 取得当前执行的shell文件所在的路径及文件名。
readlink -f "$0" 用readlink命令我们可以直接获取$0参数的全路径文件名. $0: 获取当前脚本的名称

#其他表现形式:

DIR=$(readlink -f "$(dirname "$0")")    
DIR=$(dirname $(readlink -f "$0"))

另一种文件名和目录输出

[root@centos76 ]# export var="/tmp/tmp/find_gzip_mv_tail.log.2020"
[root@centos76 ]# echo ${var##*/}
find_gzip_mv_tail.log.2020
[root@centos76 ]# echo ${var##*.}
2020
[root@centos76 ]# echo ${var#*.}
log.2020
[root@centos76 ]# echo ${var%/*}
/tmp/tmp
[root@centos76 ]# echo ${var%%.*}
/tmp/tmp/find_gzip_mv_tail

其实${}并不是专门为提取文件名或目录名的,它的使用是变量的提取和替换等等操作,它可以提取非常多的内容,并不一定是上面五个例子中的'/'或'.'。也就是说,上面的使用方法只是它使用的一个特例。

看到上面的这些命令,可能会让人感到非常难以理解和记忆,其实不然,它们都是有规律的。

#:表示从左边算起第一个
%:表示从右边算起第一个
##:表示从左边算起最后一个
%%:表示从右边算起最后一个
换句话来说,#总是表示左边算起,%总是表示右边算起。
*:表示要删除的内容,对于#和##的情况,它位于指定的字符(例子中的'/'和'.')的左边,表于删除指定字符及其左边的内容;对于%和的情况,它位于指定的字符(例子中的'/'和'.')的右边,表示删除指定字符及其右边的内容。这里的'*'的位置不能互换,即不能把*号放在#或##的右边,反之亦然。 例如:${varx*}表示找出从右边算起最后一个字符x,并删除字符x及其右边的字符。

看到这里,就可以知道,其实该命令的用途非常广泛,上面只是指针文件名和目录名的命名特性来进行提取的一些特例而已。

find查找

find /tmp -maxdepth 1 -name 'xxxx'
gzip 默认压缩时,保留输出gz文件的时间戳(可利用的良好特性)。

date日期

日期运算

$ date -d "2012-04-10 -1 day " +%Y-%m-%d
2012-04-09

$ date -d "2012-04-10 +1 day " +%Y-%m-%d
2012-04-11

$ date -d "-1 week " +%Y-%m-%d
2012-04-15

$ date -d "+1 week " +%Y-%m-%d
2012-04-29

$ date -d "+1 month " +%Y-%m-%d
2012-05-22

$ date -d "-1 month " +%Y-%m-%d
2012-03-22

$ date -d "-1 year " +%Y-%m-%d
2011-04-22

$ date -d "+1 year " +%Y-%m-%d
2013-04-22

日期求余取模

备忘脚本
date取得分钟数
$(()) 运算


#execute every 5 minutes
a=`date +%M`
b=$(( $a % 5 ))
if [ $b = 0 ] ; then 
       echo "execute it"
else
       echo "Not execute"
fi

时间戳运算

#时间加减:将基础的时间转变为时间戳,然后,需要增加或者改变时间,变成 秒。
如:1990-01-01 01:01:01  加上 1小时 20分
处理方法:

a.将基础时间转为时间戳
time1=$(date +%s -d '1990-01-01 01:01:01')
echo $time1
631126861 【时间戳】 

b.将增加时间变成秒
[root@localhost ~]# time2=$((1*60*60+20*60))
[root@localhost ~]# echo $time2
4800

c.两个时间相加,计算出结果时间
time1=$(($time1+$time2))
time1=$(date +%Y-%m-%d\ %H:%M:%S -d "1970-01-01 UTC $time1 seconds");
echo $time1
1990-01-01 02:21:01

#时间差计算方法
如:2010-01-01 与 2009-01-01 11:11:11 时间差
原理:同样转成时间戳,然后计算天,时,分,秒
time1=$(($(date +%s -d '2010-01-01') - $(date +%s -d '2009-01-01 11:11:11')));
echo time1
将time1 / 60 秒,就变成分了。

#补充说明:
shell 单括号运算符号:
a=$(date);
等同于:a=`date`;

 

双括号运算符:

a=$((1+2));

echo $a;

等同于:

a=`expr 1 + 2`

rsync同步

了解这个remove-source-files参数,其它的参考附录

Appendix & Refer