linux自动清理磁盘日志的一种方案

一. 起因

集群环境,挂载到/目录下的磁盘空间普遍较小.
即使在有监控的情况下,也很容易出现磁盘空间占用过高.
甚至磁盘写满导致节点故障的场景:No space left on device

如下图:
在这里插入图片描述

主要痛点有两点:

  1. 磁盘问题发现处理往往不够及时,风险很大
  2. 人工清理磁盘费时费力,应该把精力投入到更有意义的事情上去

因此决定开发一套自动清理磁盘空间的机制,减少运维操作,并降低生产风险

二. 方案

经分析发现:

  1. 核心数据盘空间足够,只有挂载根目录为/的磁盘资源紧张
  2. 磁盘空间紧张的罪魁祸首在于/var/log(用于存放集群各个服务的日志)目录过于臃肿,且增量数据较大
  3. 其它的目录存在一些关键文件.不能随意清理

所以在我们的业务场景下,自动清理/var/log目录下的文件是最好的解决方案

清理策略如下:(默认策略)

  1. 定期自动清理(12小时清理一次 crontab)
  2. 磁盘空间占用超过70%才进行清理
  3. 清理超过150M的大文件(但最近3天内修改过的文件不清理,否则可能影响问题定位)
  4. 清理最近15天没有修改过的日志文件

三.代码

包含两个脚本:
clear_log.sh : 主要用于清理日志的脚本分发,以及crontab的配置(通过ssh)
clear_host_log.sh:用于在各个节点上按照二. 方案中提供的策略清理日志

clear_log.sh脚本

#!/bin/bash

log_path=~/emr/logs
log_file=$log_path"/clear_log.log"
script_path=~/emr/script
time=`date +%Y-%m-%d\ %H:%M:%S`

check_path() {
    if [ ! -d "$log_path" ];then
        echo "Create log directory!"
        mkdir -p "$log_path"
        echo "$time Create log file" >> $log_file
    fi
    if [ ! -d "$script_path" ];then
        echo "Create script directory!"
        mkdir -p "$script_path"

    fi
}
# 我这里的/etc/hosts文件格式类似如下: ip hostname.***.com hostname  中间以空格分割,所以这里采用该方案解析
check_host() {
    echo "$time download clear_host_log.sh" >> $log_file
    hosts=$(cat /etc/hosts | cut -d ' ' -f 2)
    for host in $hosts
    do
        ssh $host -p $ssh_port "mkdir -p $script_path"
        ssh $host -p $ssh_port "mkdir -p $log_path"
        ssh $host -p $ssh_port "rm -rf $script_path/clear_host_log.sh"
        scp -P $ssh_port clear_host_log.sh root@$host:$script_path/
        ssh $host -p $ssh_port "chmod +x $script_path/clear_host_log.sh"
        ssh $host -p $ssh_port "crontab -l > /tmp/crontab.conf && echo '* */12 * * * sh -x $script_path/clear_host_log.sh 70 150 15 >> $log_path/clear_host_log.log' >> /tmp/crontab.conf && crontab /tmp/crontab.conf && rm -f /tmp/crontab.conf"
    done
}

main() {
    # script parameters
    # Parameter Description: Param1: github branch, param2: github username, param3: github token, param4: date (format :yyyymmdd)
    ssh_port=$1
    echo "Script parameters is: " $@
    if [ $# -lt 1 ];then
        echo "Wrong number of parameters. Please check"
        exit 1
    fi
    check_path
    check_host

}
main $@

clear_host_log.sh脚本代码

#!/bin/bash

log_path=~/emr/logs
log_file=$log_path"/clear_host_log.log"
time=`date +%Y-%m-%d\ %H:%M:%S`

check_path() {
    if [ ! -d "$log_path" ];then
        echo "Create log directory!"
        mkdir -p "$log_path"
        echo "$time Create log file" >> $log_file
    fi
}
clear_log() {
    # 获取输出倒数第二列,也就是磁盘占用百分比(不包含百分号)
    percent=`df -k | grep -w / |awk '{print int($5)}'`
    # 磁盘占比超过设定阈值时才进行清理
    if [ "$percent" -gt "$threshold" ];then
        echo "$time begin clear disk log" >> $log_file
        # 1. 第一种场景: 清理最后变更时间距今超过3天的大文件(这是为了防止清理到正在用的日志文件,导致生产定位问题失败)
        files=`find /var/log -size +150`
        for file in $files
        do
            time_difference $file 3
        done
        # 2. 第二种场景: 清理最后变更时间距今超过指定时间的文件
        traverse_directory "/var/log"
    fi
}

# 递归遍历linux目录下的文件
traverse_directory(){
    dir=$1
    files=`ls -a $dir`
    for file in $files
    do
        if [ -d $dir/$file ]
        then
            if [[ $file != '.' && $file != '..' ]]
            then
                traverse_directory $dir/$file
            fi
        else
            time_difference $dir"/"$file $days
        fi
    done
}
# 对比时间差异,并清空在配置时间范围内没有更改的文件
time_difference() {
    timestamp=`date +%s`
    filepath=$1
    if [ -f $filepath ];then
        file_timestamp=`stat -c %Y $filepath`
        time_diff=$[$timestamp - $file_timestamp]
        seconds=`expr 60 \* 60 \* 24 \* $2`
        if [ $time_diff -gt $seconds ];then
             echo "$time begin clear file $filepath" >> $log_file
             echo "" > $filepath
        fi
    fi
}

main() {
    # script parameters
    # 参数说明 参数1: 磁盘空间占比超过多少时清理 参数2: 清理多大的文件(M) 参数3: 清理多久之前的文件(天)
    threshold=$1
    filesize=$2
    days=$3
    echo "Script parameters is: " $@
    if [ -z $threshold ];then
        threshold=70
    fi
    if [ -z $filesize ];then
        filesize=150
    fi
    if [ -z $days ];then
        filesize=15
    fi
    check_path
    clear_log


}
main $@

四. 执行

首先将clear_log.sh ,clear_host_log.sh两个脚本上传到集群的主节点下(可以免密ssh到其它节点)
首次清理需要执行下述命令
该命令执行结束后,会将清理日志脚本分发到集群各个节点,并配置定时调度

# Param1: ssh端口号,具体根据实际环境呢
sh -x clear_log.sh  $ssh_port

执行完上述命令后,集群中的各个节点会每隔12小时,在磁盘空间占用超过70%的情况下,
清理/var/log目录下超过150M的日志文件.以及最近15天没有进行任何修改的日志文件

也可以再各个节点上执行以下脚本手动清理:

# 参数1,当磁盘空间占比超过多少的时候进行清理,不传为70%
# 参数2,清理超过多少M的日志文件,不传为150M(最近3天的大文件不会被清除)
# 参数3,清理多久之前的日志,不传为15天
sh -x  ~/emr/script/clear_host_log.sh $1 $2 $3

执行结束之后,可以在~/emr/logs/clear_host_log.log文件中查看有哪些日志被清理
如下图:
在这里插入图片描述
查看相关的日志文件,可以发现内容已经被成功清空,磁盘空间得到释放

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
清理Linux系统磁盘空间的方法有多种。一种方法是通过查找并删除大文件来释放磁盘空间。 以下是一种常见的方法: 1. 使用命令`df -h`显示当前磁盘使用情况,找到占用较多空间的文件系统。 2. 使用命令`cd /`切换到要清理文件的路径下。 3. 使用命令`find . -type f -size +300M`查找大于300M的文件。这将列出所有满足条件的文件。 4. 根据需要,可以使用命令`rm -f 文件路径`来删除不再需要的大文件。请注意,在删除文件之前,请确保这些文件是可以安全删除的,并且不会影响系统或应用程序的正常运行。 另外,如果有日志文件占用了较大的空间,可以使用命令`echo '' > 日志文件路径`来清空日志文件的内容,而不是直接删除该文件。 请注意,在清理文件时要谨慎操作,确保不会删除系统或应用程序所需的重要文件。另外,还可以清理/home/用户目录下的下载文件或已安装的安装包等用户无用文件,以进一步释放磁盘空间。 总结: 1. 使用命令`df -h`查看磁盘使用情况。 2. 使用命令`cd /`切换到要清理文件的路径。 3. 使用命令`find . -type f -size +300M`查找大于300M的文件。 4. 根据需要,使用命令`rm -f 文件路径`删除大文件。 5. 使用命令`echo '' > 日志文件路径`清空日志文件的内容。 6. 谨慎操作,避免删除系统或应用程序所需的重要文件。 7. 清理/home/用户目录下的下载文件或已安装的安装包等用户无用文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值