0

I need a bash script to monitor directory size change. The directory is a NFS file system with multiple users (500-600) who have sub-directories with vastly differing sizes. E.G /home/nfs/xxx/ccc etc. I need to be able to monitor, log and report for certain users that have directory sizes greater than e.g. 10GB or 20GB or indeed exceeded these sizes. This will need to be logged and the appropriate user sent a "friendly" email. I do not want to use utilities and/or tools to do this, rather with a bash script. This script would run on an ad-hoc basis.

Any help much appreciated.

MT

My efforts to date -

#!/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

cas
  • 78,579
Teddy
  • 1
  • This site is not a free script writing service. Post what you have researched, tried on your own and where you are stuck, then we will help. – Panki Aug 05 '22 at 08:34
  • Unfortunately, I am not a script person. I was merely asking for some assistance. – Teddy Aug 05 '22 at 08:55
  • Nobody is born "a script person". – Panki Aug 05 '22 at 09:00
  • Very helpful of you. – Teddy Aug 05 '22 at 09:02
  • I suggest you research the quota system. No need for scripts, complicated or otherwise. – Bib Aug 05 '22 at 09:11
  • I would prefer to accomplish all of this with just normal bash commands. No utilities/tools. – Teddy Aug 05 '22 at 09:16
  • 1
    Why? Seriously why bother when the tools are already there for you? You just seem to be needlessly creating work for yourself. Those scripts are going to create unnecessary loading on the system. – Bib Aug 05 '22 at 09:20
  • I understand what you are saying. This "solution" requires that I use pure bash/Linux methods with no tools/utilities. I am a Mainframer and am not familiar with bash at all. I have no choice in the matter. Cannot be more specific. – Teddy Aug 05 '22 at 09:44
  • I could accomplish similiar using REXX and assembler, alas I am not on a Mainframe at the moment. – Teddy Aug 05 '22 at 11:02
  • My efforts to date: – Teddy Aug 05 '22 at 11:03
  • @Teddy You should talk with the person who requires that the solution be pure bash, especially since you're using other tools like du, sort, and awk. Quotas are a standard tool and is the best solution for the job. Do you use assembler for every task on the mainframe or are you allowed to use other tools there? – doneal24 Aug 05 '22 at 12:16
  • Why don't you just enable user quotas on the NFS server? – Kusalananda Aug 09 '22 at 15:44

2 Answers2

0
#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)
Yunus
  • 1,684
0

There are some flaws with your script, some of them quite serious:

  1. Never parse the output of ls. See Why not parse ls (and what to do instead)?

    It wasn't even necessary, your "for i in ls ; do du -sh $i ; done > /tmp/mail.1" doesn't need a loop, and would have been better written as:

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

    or even:

     du -sch */ | sort -gk 1 | tail -n 1 > /tmp/mail.1
    
  2. You should almost always double-quote your variable expansions (including shell parameters like $1, $2, etc)...while there are some circumstances where you might not want to do that (e.g. you actually want the shell's usual word-splitting to occur), that is exceptionally rare and usually the exact opposite of what you want and need to do. In short: a good rule of thumb is "always quote unless you know exactly why you don't want to in this particular instance".

    See Why does my shell script choke on whitespace or other special characters?, $VAR vs ${VAR} and to quote or not to quote, Security implications of forgetting to quote a variable in bash/POSIX shells, and When is double-quoting necessary?.

    BTW, use double-quotes when you want variable interpolation to occur and single-quotes for fixed strings. Double-quotes will expand any variables etc inside them. Single-quotes won't. e.g. '$foo' is the literal string $foo, while "$foo" is the contents of a variable called $foo.

  3. While it's not actually required, it is best practice to use all-lowercase or Mixed Case variable names for your own variables, just to ensure that they won't conflict with any environment variables used by the shell or other programs (which are almost always ALL-CAPS - e.g. the $HOSTNAME environment variable you're using - that's automatically sometime fairly early during the bootup process and exported to the environment so all child processes inherit it).

  4. Since you're just trying to find the single "offender" using the most disk space (and how much space they're using), you don't even need to use a temporary file to do that. You could just do something like this:

    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

    But instead of doing this, you would be better off iterating over the output of du -sch, checking the size for each directory, and sending an email to the owner if it exceeds 10 or 20GB - the largest directory may be less than your 10-20GB limit. Note that a directory's name isn't necessarily the same as the owner's username - it's common for a user's home dir to have the same name as the user but it isn't always the case. Don't parse the output of ls to get a directory's owner - use stat instead.

    The above script fragment is just an example of how you could do this if you wanted to, it is certainly not a recommendation to actually do it this way.


BTW, you should probably be using the existing quota tools rather than writing your own. They not only have scripts to mail usage reports, they also allow you to set quota limits for each user and/or group which are enforced by the kernel. If you're using Linux, these will almost certainly be available as package for your distro - e.g. on Debian, they're in the quota package so you can install them with sudo apt-get install quota.

There's a pretty good basic tutorial to installing and using quota at Linux Quota - installation and configuration on Ubuntu and Debian - the installation method would be different for other distros (e.g. use yum or dnf on Fedora instead of apt) but configuration and usage would be the same. Arch Linux's wiki also has a good tutorial at Disk quota

Quota should probably be installed and configured on your NFS file server, rather than on your NFS client machine.

cas
  • 78,579