我是靠谱客的博主 耍酷人生,最近开发中收集的这篇文章主要介绍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文件中查看有哪些日志被清理
如下图:
在这里插入图片描述
查看相关的日志文件,可以发现内容已经被成功清空,磁盘空间得到释放

最后

以上就是耍酷人生为你收集整理的linux自动清理磁盘日志的一种方案一. 起因二. 方案三.代码四. 执行的全部内容,希望文章能够帮你解决linux自动清理磁盘日志的一种方案一. 起因二. 方案三.代码四. 执行所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部