UNIX Get An Alert When Disk Is Full

Posted on in Categories , , , , , , , , , , , , , last updated August 26, 2009

I want to get an alert when my disk is full under UNIX and Mac OS X? How do I set a a specified threshold and run the script via cron?

The df command report file system disk space usage including the amount of disk space available on the file system containing each file name argument. Disk space is shown in 1K blocks by default, unless the environment variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.

Use df command and pass the -P option which make df output POSIX compliant (i.e. 512-byte blocks rather than the default. Note that this overrides the BLOCKSIZE specification from the environment).
# df -P /
OR
# df -P /usr
Sample Outputs:

Filesystem    512-blocks     Used     Avail Capacity  Mounted on
/dev/aacd0s1e  162491344 21988048 127503992    15%    /usr

You can now simply grep /usr file system and print out used capacity:
# df -P /usr | grep /usr | awk '{ print $5}' | sed 's/%//g'
15
Or assign value to a variable:
# output=$(df -P /usr | grep /usr | awk '{ print $5}' | sed 's/%//g')
# echo $output

Under BASH or KornShell you can use arrays indexed by a numerical expression to make code small:
# output=($(df -P /))
# echo "${output[11]}"

A Sample Shell Script

#!/bin/bash
# Tested Under FreeBSD and OS X
FS="/usr"
THRESHOLD=90
OUTPUT=($(LC_ALL=C df -P ${FS}))
CURRENT=$(echo ${OUTPUT[11]} | sed 's/%//')
[ $CURRENT -gt $THRESHOLD ] && echo "$FS file system usage $CURRENT" | mail -s "$FS file system" you@example.com

You need to modify syntax, if you are using KSH or TCSH / CSH instead of BASH. Save this script and run as a cron job:
@daily /path/to/your.df.script.sh

GUI Notification

Display warning dialog using /usr/bin/zenity

#!/bin/bash
# Tested Under FreeBSD and OS X
FS="/usr"
THRESHOLD=90
OUTPUT=($(LC_ALL=C df -P ${FS}))
CURRENT=$(echo ${OUTPUT[11]} | sed 's/%//')
[ $CURRENT -gt $THRESHOLD ] && /usr/bin/zenity  --warning  --text="The disk $FS ($CURRENT% used) is almost full. Delete some files or add a new disk." --title="df Warning"
DF GUI Warning Notification
DF GUI Warning Notification

Finally update your cronjob as follows (you need to use DISPLAY variable to display output window):

36 19 * * *  DISPLAY=:0.0 /path/to/script.sh

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on Twitter, Facebook, Google+.

28 comment

    1. Easy fix, change the last line of the script from:
      /usr/bin/zenity –warning –text=”The disk $FS ($CURRENT% used) is almost full. Delete some files or add a new disk.” –title=”df Warning”
      to
      /usr/bin/zenity –notification –text=”The disk $FS ($CURRENT% used) is almost full. Delete some files or add a new disk.”

  1. Vivtek he’s right!

    Nagios only make sense when you have a LAN.

    That ‘s a good idea use that script but you can also send the output to the STDOUT with some blink text, for example.

    I did something like that a few years ago.

  2. Hello,
    I tried to use this script in my Ubuntu.
    First,
    # df -P /usr

    S.ficheros Bloques de 1024 Usado Libre Ocupado Montado en

    /dev/sda4 12399800 9341132 2433740 80% /

    # df -P /usr | grep /usr | awk ‘{ print $5}’ | sed ‘s/%//g’
    no answer…, and I was waiting for an output: 80
    What is wrong with that?

    Thanks in advance, I’m learning from you how to make scripts.

  3. Hello there,

    Now when I change this to the following ( note the space between the “M” and the “H” in “/media/FREECOM HDD”:

    #!/bin/bash
    # Tested Under FreeBSD and OS X
    
    # File systems ( partitions )
    FSfreecomhdd="/media/FREECOM HDD"
    
    # Everything above 85 will be given a yellow card for warning
    THRESHOLD=85
    
    # Check given file systems for size
    for FS in $FSfreecomhdd ; do
    	echo $FS
    	OUTPUT=($(LC_ALL=C df -P $FS))
    	CURRENT=$(echo ${OUTPUT[11]} | sed 's/%//')
    	[ $CURRENT -gt $THRESHOLD ] && /usr/bin/zenity  --warning  --text="The disk ${OUTPUT[12]} ($CURRENT% used) is almost full. Delete some files." --title="df Warning"
    done

    it does not work anymore.

    Output will be :
    df: `/media/FREECOM’: No such file or directory
    df: no file systems processed
    ./check_partitions_sizes_simple.sh: line 15: [: -gt: unary operator expected
    df: `HDD’: No such file or directory
    df: no file systems processed
    ./check_partitions_sizes_simple.sh: line 15: [: -gt: unary operator expected

    With or without the escape character like FSfreecomhdd=”/media/FREECOM\ HDD” does not mather.

    The “df – P” will treat it as 2 strings which is obviously not my purpose.

    Is there another way to escape the space so that df will accept and treat this as 1 string in stead of 2 ??

    Thanks in advance,

    Jeroen

    p.s. great website for shell programming and linux things !!!

  4. Hai Vivek

    Thanks for the quick response on my email. Yes this mount point is automatically made for the usb drive under Fedora 8 at rebooting time. I suppose the usb drive is FAT32 formatted and given as label this name. I will find a way to give the usb drive a correct name without the spaces. Then it will be mounted correctly at startup. I suppose another way is to mount this usb drive manually under /media/freecomhdd for example.

    Thanks,

    Jeroen

  5. Hey petrescs,

    Yes this is great. I was banging my head on this because I relabelled an usb disk before. But then there was no data on it so I put a fat filesystem on it with the correct label. This usb drive has lots of data on it so I am a little bit more carefull with it. I did not know Gnome was able to do this but I am just checking this out with gParted and I it did the job oke.

    Thanks, great call,

    Jeroen

  6. Hello,

    I used also the method of relabelling with mlabel and this works great and much faster then with gparted. I added an entry in the crontab but when this job runs it cannot display the warnings. I get this in the mail :
    (zenity:21175): Gtk-WARNING **: cannot open display:
    /media/FREECOM_HDD932

    Is this something from Fedora 8 with crontab ??

    This was my entry :
    36 19 * * * /home/paula/shells/check_partitions_sizes.sh

    Regards,

    Jeroen

  7. @Jeroen

    You need to run it as follows /etc/profile.d/run.cron.gui.sh:

    #!/bin/sh
    # replace vivek with actual username, see xhost man page ;)
    /usr/bin/xhost +si:localuser:vivek

    Set permissions:

    chmod +x /etc/profile.d/run.cron.gui.sh

    Finally update your cronjob:

    36 19 * * *  DISPLAY=:0.0 /home/paula/shells/check_partitions_sizes.sh

    OR assuming that you are always on 0.0

    36 19 * * *  DISPLAY=:0.0 && /home/paula/shells/check_partitions_sizes.sh

    HTH

  8. Woooohhhhh, I just wanted to react on this response : petrescs 08.14.09 at 6:15 pm
    That was a great one and did the trick….

    Vivek : I will try this tomorrow….its getting late here…

    Thanks every one,

    Jeroen

  9. Hai Vivek and petrescs,

    The updating of the user cronjob worked fine so I changed my user crontab with the “DISPLAY=:0.0” . I am not sure what the extra value is of the /etc/profile.d/run.cron.gui.sh. With or without it my shell script starts and finishes and produces ( as far as I can see ) the same results.

    This “DISPLAY=:0.0” added to the cronjob solved for me other problems that output could not be showed on the display and gui applications could not be executed.

    Thank you @petrescs and @vivek for the answers to my questions. They were very helpful.

    Jeroen

  10. No need to use grep and awk together, at least not in the context you’re using it. And sed is a bit of an overkill; use tr instead.

    df -P /usr | awk '/\/usr/{ printf $5}' | tr -d "%"
  11. Hello,
    I using this scripts and i am getting this following error

    # vi full.ksh
    “full.ksh” 7 lines, 377 characters
    #!/bin/ksh
    set -x
    # Tested Under FreeBSD and OS X
    FS=”/usr”
    THRESHOLD=90
    OUTPUT=($(LC_ALL=C df -P ${FS}))
    CURRENT=$(echo ${OUTPUT[11]} | sed ‘s/%//’)
    [ $CURRENT -gt $THRESHOLD ] && /usr/bin/zenity –warning –text=”The disk $FS ($CURRENT% used) is almost full. Delete some files or add a new disk.” — ti
    tle=”df Warning” | mail -s “$FS file system” [email protected]

    # sh full.ksh
    FS=/usr
    THRESHOLD=90
    full.ksh: syntax error at line 6: `OUTPUT=’ unexpected

  12. I am looking for shell script which can be scheduled as cronjob under root to do the following on server named abcz on AIX platform.

    The script should capture the unsuccessful login attempts for user ID joebazin & oracle with the details -ip address, attempt time and number of attempts.

Leave a Comment