UNIX Get An Alert When Disk Is Full

by on August 13, 2009 · 27 comments· LAST UPDATED August 26, 2009

in , ,

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
TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 27 comments… read them below or add one }

1 Dariusz21p August 13, 2009 at 10:18 am

I think Linux desktop lack alarm in notification area about disks getting full just like you do in M$

Reply

2 manvstech November 29, 2011 at 10:07 pm

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.”

Reply

3 Shoaibi August 13, 2009 at 10:35 am

good one, though i use nagios, great tool.

Reply

4 nixCraft August 13, 2009 at 10:51 am

nagios is good if you’ve large number of servers or workstation. For a single laptop, desktop or a small number of server script will save the time.

YMMV.

Reply

5 Vitor Castro August 13, 2009 at 11:26 am

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.

Reply

6 petrescs August 13, 2009 at 1:35 pm

I think zenity (for Gnome) or kdialog (KDE) could be used to pop-up an info box, instead (or additionally) to sending an email.

Reply

7 nixCraft August 13, 2009 at 1:44 pm

@petrescs,

The FAQ has been updated.

Reply

8 Jaysunn August 13, 2009 at 3:54 pm

COOOOOl!!!

I was unaware of zenity. Very sweet.

Jaysunn

Reply

9 Carmen August 13, 2009 at 5:27 pm

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.

Reply

10 petrescs August 13, 2009 at 5:53 pm

@Carmen: there’s no /usr in your case, just / (that is, root)
Try df -P / | grep / | awk ‘{ print $5}’ | sed ‘s/%//g’ instead

Reply

11 Carmen August 13, 2009 at 7:13 pm

Thank you!!
That was very useful.

Reply

12 Jeroen August 14, 2009 at 2:07 pm

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

Reply

13 nixCraft August 14, 2009 at 2:37 pm

This line should be corrected

FSfreecomhdd="/media/FREECOM HDD"

HDD is not a valid mount point, use full path like /usr /home /www

FSfreecomhdd="/media/FREECOM / /home /www"

Reply

14 Jeroen August 14, 2009 at 3:06 pm

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

Reply

15 petrescs August 14, 2009 at 3:16 pm

@Jeroen: have not tried this, but it can help you https://help.ubuntu.com/community/RenameUSBDrive

Reply

16 Jeroen August 14, 2009 at 3:50 pm

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

Reply

17 Jeroen August 14, 2009 at 5:49 pm

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

Reply

18 petrescs August 14, 2009 at 6:15 pm

@Jeroen: Try add “DISPLAY=:0.0″ (those are zero, not lowercase O, and no quotes) as first line in your user crontab.

Reply

19 Bash August 14, 2009 at 6:55 pm

You can get rid of sed like so:

echo “${output[11]/\%/}”

Reply

20 nixCraft August 14, 2009 at 7:41 pm

@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

Reply

21 Jeroen August 14, 2009 at 8:35 pm

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

Reply

22 Shantanu Oak August 15, 2009 at 6:00 am

How about twittering the alert?
# Twit the disk status alert away
[ $CURRENT -gt $THRESHOLD ] && curl –basic –user username:password –data status=”$FS file system usage $CURRENT” http://twitter.com/statuses/update.xml

Reply

23 Jeroen August 15, 2009 at 10:20 pm

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

Reply

24 Mark Shields November 13, 2011 at 5:37 pm

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 "%"

Reply

25 Randall Oveson March 6, 2012 at 9:07 pm

Thanks for the script, works great!

Reply

26 aj November 19, 2012 at 3:16 pm

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” ak@mountsaintvincent.edu

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

Reply

27 Joe Bazin November 23, 2013 at 9:01 pm

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.

Reply

Leave a Comment

Tagged as: , , , , , , , , , , , , , ,

Previous Faq:

Next Faq: