我需要一个 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
您的脚本存在一些缺陷,其中一些非常严重:
绝不解析 的输出
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
您几乎应该总是双引号变量扩展(包括 shell 参数,如
$1
、$2
等)...虽然在某些情况下您可能不想这样做(例如您实际上想shell 通常会发生分词),这种情况非常罕见,而且通常与您想要和需要做的完全相反。简而言之:一个好的经验法则是“总是引用,除非你确切知道为什么在这种特定情况下不想引用”。看为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?,$VAR 与 ${VAR} 以及引用或不引用,忘记在 bash/POSIX shell 中引用变量的安全隐患, 和什么时候需要双引号?。
顺便说一句,当您想要进行变量插值时,请使用双引号,对于固定字符串,请使用单引号。双引号将扩展其中的任何变量等。单引号则不会。例如
'$foo'
是文字字符串$foo
,"$foo"
而是内容一个名为 的变量$foo
。虽然实际上不是必需的,但最佳实践是为您自己的变量使用全小写或混合大小写的变量名称,只是为了确保它们不会与 shell 或其他程序使用的任何环境变量(几乎总是全部大写 - 例如
$HOSTNAME
您正在使用的环境变量 - 在启动过程中相当早的某个时间会自动导出到环境,以便所有子进程继承它)。由于您只是想找到使用最多磁盘空间(以及他们使用了多少空间)的单个“罪犯”,因此您甚至不需要使用临时文件来做到这一点。你可以这样做:
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 上使用yum
或dnf
代替apt
),但配置和用法是相同的。 Arch Linux 的 wiki 也有一个很好的教程:磁盘配额
配额可能应该在 NFS 文件服务器上安装和配置,而不是在 NFS 客户端计算机上。