监控目录大小变化的脚本

监控目录大小变化的脚本

我需要一个 bash 脚本来监视目录大小的变化。该目录是一个 NFS 文件系统,具有多个用户 (500-600),这些用户的子目录大小差异很大。例如 /home/nfs/xxx/ccc 等。我需要能够监视、记录和报告目录大小大于 10GB 或 20GB 或确实超过这些大小的某些用户。这需要记录下来,并且适当的用户发送了一封“友好”的电子邮件。我不想使用实用程序和/或工具来执行此操作,而是使用 bash 脚本。该脚本将临时运行。

非常感谢任何帮助。

公吨

迄今为止我的努力 -

#!/bin/bash

set -x
DISK="/cluster/vvvvvvv1/nfs-home/zzz" # Verzeichnis
CURRENT=$(df -h | grep ${DISK} | awk {'print $4'}) # get disk usage from monitored disk
MAX="70%" # max nn% disk usage
DOMAIN="naz.ch"


# Max Exceeded now find the largest offender
cd $DISK
for i in `ls` ; do du -sh $i ; done > /tmp/mail.1
sort -gk 1 /tmp/mail.1 | tail -1 | awk -F " " '{print $2}' > /tmp/mail.offender
OFFENDER=`cat /tmp/mail.offender`
echo $OFFENDER
du -sh $DISK/$OFFENDER > /tmp/mail.over70
mail -s "$HOSTNAME $DISK Alert!" "$OFFENDER@$DOMAIN"  < /tmp/mail.over70

# check if current disk usage is greater than or equal to max usage.
if [ ${CURRENT} ]; then
  if [ ${CURRENT%?} -ge ${MAX%?} ]; then
    # if it is greater than or equal to max usage we call our max_exceeded function and send mail
    echo "Max usage (${MAX}) exceeded. The /home disk usage is it at ${CURRENT}. Sending email."
     max_exceeded
  fi
fi

# init #
# main

#CLEANUP 

答案1

#assuming that your users are subfolders to same parent

disk=/home/disk # which contains users dirs user-{1..999}
limit='75%' 
current=$(df -k ${disk} | tail -1| awk '{print $5}')
max=10000000000 #in kilobytes (10G)

if [[ ${current//%/} -gt ${limit//%/} ]];then
    echo disk limit has been exceeded ${disk}
    # do your magick here
fi

find ${disk} -type f -exec du -k {} + | sort -nr | while read s f;do
    if test ${s} -gt ${max};then
        fsplt=(${f//\// }) # '/x/y/z' to 'x y z' as array
        echo "file size exceeded limits | user:${fsplt[2]} file:${f}";
        # do whatever here with file and user;
    else
        break; #cuz the list is sorted all remainning are smaller files
    fi
done

# you can customize find option to find only bigger than X size (optional)

答案2

您的脚本存在一些缺陷,其中一些非常严重:

  1. 绝不解析 的输出ls。看为什么不是解析ls(以及该怎么做)?

    甚至没有必要,您的“for i in ls; do du -sh $i ; did > /tmp/mail.1”不需要循环,最好写为:

      du -sch */ > /tmp/mail.1
    

    甚至:

     du -sch */ | sort -gk 1 | tail -n 1 > /tmp/mail.1
    
  2. 您几乎应该总是双引号变量扩展(包括 shell 参数,如$1$2等)...虽然在某些情况下您可能不想这样做(例如您实际上shell 通常会发生分词),这种情况非常罕见,而且通常与您想要和需要做的完全相反。简而言之:一个好的经验法则是“总是引用,除非你确切知道为什么在这种特定情况下不想引用”。

    为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?,$VAR 与 ${VAR} 以及引用或不引用,忘记在 bash/POSIX shell 中引用变量的安全隐患, 和什么时候需要双引号?

    顺便说一句,当您想要进行变量插值时,请使用双引号,对于固定字符串,请使用单引号。双引号将扩展其中的任何变量等。单引号则不会。例如'$foo'是文字字符串$foo"$foo"而是内容一个名为 的变量$foo

  3. 虽然实际上不是必需的,但最佳实践是为您自己的变量使用全小写或混合大小写的变量名称,只是为了确保它们不会与 shell 或其他程序使用的任何环境变量(几乎总是全部大写 - 例如$HOSTNAME您正在使用的环境变量 - 在启动过程中相当早的某个时间会自动导出到环境,以便所有子进程继承它)。

  4. 由于您只是想找到使用最多磁盘空间(以及他们使用了多少空间)的单个“罪犯”,因此您甚至不需要使用临时文件来做到这一点。你可以这样做:

    disk="/cluster/vvvvvvv1/nfs-home/zzz"
    subject="$HOSTNAME $disk Alert!"
    domain='naz.ch'
    
    read -r size offender < <(du -sch */ | sort -gk 1 | tail -n 1 |
                                awk -F'[[:space:]]+|/' '{print $1, $2}')
    
    if [ -n "$offender" ] ; then
      cat <<__EOF__ | mail -s "$subject" "$offender@$domain"
        Your current disk usage is $size.  Please compress or delete
        any unnecessary files or directories.
    __EOF__
    fi
    

    但与其这样做,您最好迭代 的输出du -sch,检查每个目录的大小,如果超过 10 或 20GB,则向所有者发送电子邮件 - 最大的目录可能小于您的 10-20GB 限制。请注意,目录的名称不一定与所有者的用户名相同 - 用户的主目录通常与用户具有相同的名称,但情况并非总是如此。 解析 的输出ls以获取目录的所有者 - 请改用stat

    上面的脚本片段只是一个示例,说明如果您愿意,可以如何执行此操作,当然不建议实际这样做。


顺便说一句,您可能应该使用现有的配额工具而不是自己编写。它们不仅具有用于邮寄使用情况报告的脚本,还允许您为每个用户和/或组设置由内核强制执行的配额限制。如果您使用的是 Linux,这些几乎肯定会作为您的发行版的软件包提供 - 例如在 Debian 上,它们位于quota软件包中,因此您可以使用sudo apt-get install quota.

有一个非常好的安装和使用基本quota教程Linux 配额 - Ubuntu 和 Debian 上的安装和配置- 对于其他发行版,安装方法可能会有所不同(例如,在 Fedora 上使用yumdnf代替apt),但配置和用法是相同的。 Arch Linux 的 wiki 也有一个很好的教程:磁盘配额

配额可能应该在 NFS 文件服务器上安装和配置,而不是在 NFS 客户端计算机上。

相关内容