Shell script to watch the disk space

by n00b_Programmer on July 13, 2006 · 39 comments

df displays the amount of disk space available on the file system containing each file name argument. If no file name is given, the space available on all currently mounted file systems is shown. Read man page of df if you are new to df command.

Steps

=> Find disk space using df

=> Filter out filesystem and find out the percentage of space using grep

=> Write a shell script

Step # 1: First get disk space:

$ df -H

Output:

Filesystem             Size   Used  Avail Use% Mounted on
/dev/hdb1               20G    14G   5.5G  71% /
tmpfs                  394M   4.1k   394M   1% /dev/shm
/dev/hdb5               29G    27G   654M  98% /nas/www

Step # 2: Next filter out filesystem and find out the percentage of space

$ df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 }'

Output:

71% /dev/hdb1
98% /dev/hdb5

Step # 3: Write a shell script

Above command displays field 5 and 1 of df command. Now all you need to do is write a script to see if the percentage of space is >= 90% (download script):

#!/bin/sh
df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 }' | while read output;
do
  echo $output
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $output | awk '{ print $2 }' )
  if [ $usep -ge 90 ]; then
    echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date)" |
     mail -s "Alert: Almost out of disk space $usep%" you@somewhere.com
  fi
done

Setup Cron job

Save and install script as cronjob. Copy script to /etc/cron.daily/ (script downolad link)
# cp diskAlert /etc/cron.daily/
# chmod +x /etc/cron.daily/diskAlert

OR install as cronjob:
crontab -e

Write cronjob as per your requirement
10 0 * * * /path/to/diskAlert

Updated script version

Tony contributed and updated my script - You can exclude selected filesystem in case you don't want monitor all filesystems.

#!/bin/sh
# set -x
# Shell script to monitor or watch the disk space
# It will send an email to $ADMIN, if the (free available) percentage of space is >= 90%.
# -------------------------------------------------------------------------
# Set admin email so that you can get email.
ADMIN="root"
# set alert level 90% is default
ALERT=90
# Exclude list of unwanted monitoring, if several partions then use "|" to separate the partitions.
# An example: EXCLUDE_LIST="/dev/hdd1|/dev/hdc5"
EXCLUDE_LIST="/auto/ripper"
#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#
function main_prog() {
while read output;
do
#echo $output
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1)
  partition=$(echo $output | awk '{print $2}')
  if [ $usep -ge $ALERT ] ; then
     echo "Running out of space \"$partition ($usep%)\" on server $(hostname), $(date)" | \
     mail -s "Alert: Almost out of disk space $usep%" $ADMIN
  fi
done
}
if [ "$EXCLUDE_LIST" != "" ] ; then
  df -H | grep -vE "^Filesystem|tmpfs|cdrom|${EXCLUDE_LIST}" | awk '{print $5 " " $6}' | main_prog
else
  df -H | grep -vE "^Filesystem|tmpfs|cdrom" | awk '{print $5 " " $6}' | main_prog
fi

Featured Articles:

Share this with other sys admins!
Facebook it - Tweet it - Print it -

We're here to help you make the most of sysadmin work. So, subscribe!

{ 39 comments… read them below or add one }

1 Per Lindahl March 29, 2007

I noticed that on devices that have very long path in some cases there might be a line break appended to the output and that will in turn create an error when the script is run like:

line 22: [: -ge: unary operator expected

To remove the line break just append “-P” to the “df” command.

example:
df -HlP

(P) = adds posix compliance to the output.

Errors that occured: df -H
/dev/mapper/volume00-pgvol
50G 31G 19G 62% /localhome/postgresql

with -P
/dev/mapper/volume00-pgvol 50G 31G 19G 62% /localhome/postgresql

Also if you only have one type of filesystem that you need to monitor then add “-t ext3″ will only show EXT3 filesystems.

Hope it helps.
Regards,
Per L

Reply

2 nixcraft March 30, 2007

Per Lindahl,

Thanks for sharing your tip!

Reply

3 Trula May 6, 2007

Please show me if I need to get disk file last week or 10 days ago, what do I need to do?
Thank you ~ Trula

Reply

4 Mehmet Buyukozer May 19, 2007

For my case:

df -h | grep d30 | awk ‘{ print $5 ” ” $1 }’ | while read output;

worked better. Thanks for shell script, life saver one.

Reply

5 sorabh harit July 10, 2007

HI

thanks for script but i am getting following error
on my solaris 9 servrer after executing the scipt.

syntax error at line 5: `usep=$’ unexpected

Regards

Sorabh harit

Reply

6 Niek August 17, 2007

@sorabh harit:
That is because you run a “real” Bourne shell, which doesn’t understand the syntax on that line.

Also, there is a fair bit of double code at the end, and use of a function isn’t really necessary.

I’ve put up a modified version on my site:
http://www.qwertyboy.org/files/diskspace.txt

Niek.

Reply

7 Rohan September 13, 2007

Can you please tell me how to find disk usage for a particular user only…!

Reply

8 Derek Murphy November 14, 2007

I tried using this script but I’m getting a syntax error, trying to run this on linux(redhat as 4) any thoughts?

-bash-3.00$ ./diskscript.sh
13% /dev/cciss/c0d0p2
17% /dev/cciss/c0d0p1
1% /dev/cciss/c0d0p5
./diskscript.sh: line 4: syntax error near unexpected token `do’
./diskscript.sh: line 4: `do’

#!/bin/sh
#df -H | grep -vE ‘^Filesystem|tmpfs|cdrom’ | awk ‘{ print $5 ” ” $1 }’ | while read output;
df -F ext3 -k | grep -vE ‘^Filesystem|tmpfs|cdrom’ | awk ‘{print $5 ” ” $1}’
do
echo $output
usep=$(echo $output | awk ‘{ print $1}’ | cut -d’%’ -f1 )
partition=$(echo $output | awk ‘{ print $2 }’ )
if [ $usep -ge 90 ]; then
echo “Running out of space \”$partition ($usep%)\” on $(hostname) as on $(date)” |
mail -s “Alert: Almost out of disk space $usep%” derek@iona.com
fi
done

Reply

9 Hari December 2, 2007

while executing the below script i am getting the following:

Script:

#!/bin/sh
df -H | grep -vE ‘^Filesystem’ | awk ‘{ print $5 ” ” $1 }’ | while read output;
do
echo $output
usep=$(echo $output | awk ‘{ print $1}’ | cut -d’%’ -f1 )
partition=$(echo $output | awk ‘{ print $2 }’ )
if [ $usep -ge 50 ]; then
echo “Running out of space \”$partition ($usep%)\” on $(hostname) as on $(date)” |
mail -s “Alert: Almost out of disk space $usep%” Hari-Krishna.Reddy@in.standardchartered.com
fi
done

Error:

sh diskAlert.sh
/dev/mapper/rootvg-rootvol
diskAlert.sh: line 7: [: /dev/mapper/rootvg-rootvol: integer expression expected
/ 4.2G
diskAlert.sh: line 7: [: /: integer expression expected
14% /dev/sda1
0% none
/dev/mapper/rootvg-homevol
diskAlert.sh: line 7: [: /dev/mapper/rootvg-homevol: integer expression expected
/home 2.1G
diskAlert.sh: line 7: [: /home: integer expression expected
/dev/mapper/rootvg-sharedvol
diskAlert.sh: line 7: [: /dev/mapper/rootvg-sharedvol: integer expression expected
/shared 6.3G
diskAlert.sh: line 7: [: /shared: integer expression expected
/dev/mapper/rootvg-varvol
diskAlert.sh: line 7: [: /dev/mapper/rootvg-varvol: integer expression expected
/var 2.1G
diskAlert.sh: line 7: [: /var: integer expression expected

can any one help me on this.

Reply

10 Ambika January 25, 2008

i want the disk space scripts where it should send the mail in the .lst file

Reply

11 david July 22, 2008

i am able to run the shell script properly but if i put it in a crontab its not working fine
can anyone plz suggest me in this

thnks
david

Reply

12 jack September 1, 2008

Can you send your crontab scripts?

Reply

13 Prasanna October 8, 2008

Hi

I have to select 10% of the files from a 1 million records file at random. Could anyone help me with a shell script?
thanks and regards
Prasanna

Reply

14 adgar marks January 21, 2009

I am using Gentoo and i get the following error:

./freespace.sh: line 25: [: Ben: integer expression expected

Once i do “echo $output”, i get an empty line and i dont know what wasi suppose to expect from $output.

I hope someone could help me a bit

thansk

Reply

15 jack May 5, 2009

hello..

what if your both partitions will run out of space? you will receive 2 mails. if you have more partitions, then you will receive more mails… how you do to receive all messages in one mail?

Reply

16 Neo June 12, 2009

Hi,

I have typed in df -h, all my files were display. I have found that my log file is full, file name /lsx/log sitting at 100%, then I typed in the command du -akd |sort -rn | more to sort from big to small, I found that /fb was the biggest and tried to clean up with then command cat /dev/null > fb, but didn’t clean up any of the files. Please advice me how to clean up log files when full.

Regards,
Neo

Reply

17 rebelteam July 12, 2009
#!/bin/sh
ADMIN="usuario@domain.com"
ALERT1=95
ALERT2=80
ALERT3=70
# Exemplu: EXCLUDE_LIST="/dev/hdd1|/dev/hdc5"
EXCLUDE_LIST="/dev/sr0"
#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#
function main_prog() {
while read output;
do
echo $output
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1)
  partition=$(echo $output | awk '{print $2}')
    if [ $usep -ge $ALERT1 ] ; then
     echo "Queda menos de  `expr 100 - $usep` % en la particion: $partition del servidor ServerName, \
$(date +%d-%b-%Y)" | \
     mail -s "Alerta alta prioridad: Informacion tamaño disco: $usep %" $ADMIN
   fi
   if [ $usep -ge $ALERT2 ] ; then
     echo "Queda menos de  `expr 100 - $usep` % en la particion: $partition del servidor ServerName, \
$(date +%d-%b-%Y)" | \
     mail -s "Alerta media prioridad: Informacion tamaño disco: $usep %" $ADMIN
  fi
    if [ $usep -ge $ALERT3 ] ; then
#     espacio= expr 100 - $ALERT3"
     echo "Queda menos de  `expr 100 - $usep` % en la particion: $partition del servidor ServerName, \
$(date +%d-%b-%Y)" | \
     mail -s "Alerta baja priridad: Informacion tamaño disco: $usep %" $ADMIN
  fi
done
}
if [ "$EXCLUDE_LIST" != "" ] ; then
  df -H | grep -vE "^Filesystem|tmpfs|cdrom|${EXCLUDE_LIST}" | awk '{print $5 " " $6}' | main_prog
else
  df -H | grep -vE "^Filesystem|tmpfs|cdrom" | awk '{print $5 " " $6}' | main_prog
fi

Reply

18 kiran November 12, 2009

syntax error at line 5: `usep=$’ unexpected

Hi iam getting hte same error. And unable to acces your URL provided forthe updated code..Can you please help me insortiugn this

Reply

19 rocky February 9, 2010

@@rebelteam

I got error while running you script on Solaris 10 box , any idea

-bash-3.00$ ./test
./test: line 24: [: :: integer expression expected
./test: line 29: [: :: integer expression expected
./test: line 24: [: :: integer expression expected
./test: line 29: [: :: integer expression expected

#!/usr/bin/bash

#admin email account
ADMIN="test@test.com"

# set usage alert threshold
THRESHOLD=10

#hostname
HOSTNAME=$(hostname)

#mail client
MAIL=/usr/bin/mail

# store all disk info here
EMAIL=""

for line in $(df -kh | egrep '^/dev/' | awk '{ print $6 "_:_" $5 }')
do

part=$(echo "$line" | awk -F"_:_" '{ print $1 }')
part_usage=$(echo "$line" | awk -F"_:_" '{ print $2 }' | cut -d'%' -f1 )

if [ $part_usage -ge $THRESHOLD -a -z "$EMAIL" ];
then
EMAIL=”$(date): Running out of diskspace on $HOSTNAME\n”
EMAIL=”$EMAIL\n$part ($part_usage%) >= (Threshold = $THRESHOLD%)”

elif [ $part_usage -ge $THRESHOLD ];
then
EMAIL=”$EMAIL\n$part ($part_usage%) >= (Threshold = $THRESHOLD%)”
fi

Reply

20 llattan May 14, 2010

The script doesn’t work when:

1) there is a filesystem with “$” (nfs mounted coming from windows hidden shares)

i.e //10.10.10.10/back$

2) the name of a filesystem is large and the percentage of use appears in another line

i.e.
//10.10.10.10/verylongnamefilesystem
78140128 45746488 32393640 59% /mnt/

Regards.

Reply

21 Ramírez May 17, 2010

I’ve made my own bash script for watching free space. Its main feature is that it runs with X and uses pop-ups for warning the user. Please see http://galinux.myftp.org/hdfree/

Reply

22 victor August 12, 2010

when I run script on solair 10. It errors
# ./Diskalert.sh
./Diskalert.sh: syntax error at line 21: `usep=$’ unexpected

Please help me?
Thank you very much

Best regards,

Reply

23 broxigar August 18, 2010

When I try to run the updated script, on a Ubuntu server, I get an syntax error: “(” unexpected at “function main_prog() {”

What is wrong here?

Reply

24 Brad November 1, 2010

None of the scripts here work on RHEL5.5.

All of them give errors….

Reply

25 Rajesh Thakur November 11, 2010

hi,
i have multiple servers and i am running this script from single server where ssh keys fro all servers are added…
issue: when i run it it throws me multiple mails on the id i specified in the script, if i have 12 linux remote servers thn it will throw 12 mails…i want to get details in one mail..

does anyone has idea abt it please….it will be agreat assistance.

Best wishes,
Rajesh Thakur

Reply

26 Evert Mouw November 18, 2010

@broxigar and others:

The syntax error “syntax error: “(” unexpected at “function main_prog() {”” can be solved by using bash instead of sh as script interpreter. So, after the shebang, use /bin/bash or /usr/bin/bash

Reply

27 souvik November 18, 2010

hi,

the above scripts have been really helpful but can u give me a generalized way of extracting the necessary mount points in different servers. i am avoiding the way to hard code the mount point.

Thanks..

Reply

28 swarajsingh March 8, 2011
#! /bin/sh
clear;
#echo "enter erver no gibe the serer names u want to checkthe space inside";
 a=xldn2094dap;
 b=xldn2095dap;
c=xldn1844dap;
d=xldn1845dap;
e=xldn1599vdap;
 f=xldn1600vdap;
 echo "for server $a"
  ssh -q $a  "df -k /sbclocal";     #df -k /sbcloca--sbclocal is folder where we spaces r checked
echo "               "
 echo "for server $b"
ssh -q $b  "df -k /sbclocal";
echo "            ";
 echo "for server $c"
  ssh -q $c  "df -k /sbclocal";
echo "           ";
 echo "for server $d"
   ssh -q $d  "df -k /sbclocal";
echo "                   ";
echo "for server $e"
 ssh -q $e  "df -k /sbclocal";
exit;

Reply

29 charles April 1, 2011

Very nice, with some minor changes it works beautifully!!!
Thanks for helping out the coding-handicapped!

Reply

30 Sri April 11, 2011

hi
iam getting the below for my shell script for space alert on linus server
/home/oracle/dba/scripts > ./space_alert.sh
./space_alert.sh: line 15: [: /dbbackup: integer expression expected

after that i have user df -HP command to append it .. but iam not able to get the ouput through mail
#!/bin/bash

SENT_TO="dba-support@marlabs.com"
LOGFILE=/home/oracle/dba/scripts/log/disk_alert.log
ALERT=10
EXCLUDE_LIST="/dbbackup"
if [ -f ${LOGFILE} ]; then
rm $LOGFILE
fi

df -HP | grep -vE ‘^Filesystem|tmpfs|cdrom|product|mapper’ | awk ‘{ print $5 ” ” $6 }’ | while read output;
do
usep=$(echo $output | awk ‘{ print $1}’ | cut -d’%’ -f1 )
partition=$(echo $output | awk ‘{ print $2 }’ )
if [ $usep -ge $ALERT ]; then
if [ ! -f ${LOGFILE} ]; then
touch $LOGFILE
fi
echo “Running out of space on $partition ($usep%) on $(hostname) as on $(date)” >> ${LOGFILE}
echo “” >> ${LOGFILE}
fi
done

if [ -f ${LOGFILE} ]; then
/bin/mail -s “space_alert.sh – $(hostname) – Almost out of disk space” $SENT_TO < ${LOGFILE}
fi

#rm $LOGFILE

Please help on this

thanks

Reply

31 hypersmil April 20, 2011

there are some issues with this script

- it won’t work with non english output from df

Dateisystem             Size   Used  Avail Use% Eingehängt auf
/dev/sda1              9,9G   3,3G   6,1G  35% /
none                    17G   213k    17G   1% /dev
none                    17G      0    17G   0% /dev/shm
none                    17G   103k    17G   1% /var/run
none                    17G      0    17G   0% /var/lock
none                   9,9G   3,3G   6,1G  35% /var/lib/ureadahead/debugfs
/dev/sda2               64G    17G    48G  26% /usr/local
/dev/md0               147G    43G   105G  29% /mnt
/dev/sde1              400G   203G   198G  51% /mnt/usbdisk

change

    grep -vE "^Filesystem|tmpfs|cdrom"

to

    grep -vE "^Dateisystem|tmpfs|cdrom"

or you could change it to

  grep -vE "^[^/]|tmpfs|cdrom"

to remove all lines not starting with a / which would also remove mounted network shares (sshfs, nfs etc.)

additionally you could change the df command to

  df -hP fuse.sshfs -x nfs

to remove mounted network devices

another problem arises from the use of “sh” instead of bash –
it won’t work -
change the first line to

#!/bin/bash

to improve the error reporting you could also add the hostname to the subject line

mail -s "Alert: $(hostname) almost out of disk space $usep%" $ADMIN

Reply

32 Stefan June 8, 2011

One reason for “integer expression expected”-errors is that if “$usep” is empty the test fails. Just test if “$usep” is empty and do nothing if so:

if [ ! "$usep" == "" ] ; then
if [ $usep -ge $ALERT ] ; then
echo “Running out of space \”$partition ($usep%)\” on server $(hostname), $(date)” | \
mail -s “Alert: $(hostname) almost out of disk space $usep%” $ADMIN
fi
fi

Reply

33 Stefan June 8, 2011

to remove non-local drives it would be better so use the “-l” option of df (substitute “df -H” with “df -lH”).

Reply

34 BABU June 17, 2011

Please provide me rhe query for solaris and HP-UX and IBM-AIX

Very urgent please

Reply

35 Juan Nicolas July 8, 2011

Great script, very simple and works like a charm. i have a question tho, could someone help me to make this script to run a gzip command and monitor the pid in order to start another gzip after the first pid ends? Is it possible to do that, well, in scripts all is possible :)

I need to run 2 gzips on differents directories but can’t run them at the same time since this will eat my cpu and the disk IO will be very high. I need to start one and then the other. Thanks in advance

Reply

36 romsieze July 28, 2011

OP- You rock. You saved my arse this time around…..

Reply

37 pk August 28, 2011

I need to know the the usage of particular filesystem on 10 days back. Is it possible to use two or more df option in single line? If yes then how can we use twp grep statement in single line? Thanks in advance !!

I used below line:df -H | grep d30 | awk ‘{print $5 ” ” $1}’ | main_prog

But it is not sending any email.

Reply

38 stainless January 8, 2012

Ok this is the slightly modified version, tested and working on different versions of linux …Enjoy!

#!/bin/bash

> alert.txt

HOST=$(hostname)

THRES=20

COUNT=1

df -HP | grep -vE ‘Filesystem|tmpfs’ | awk ‘{ print $5 ” ” $6 }’ |
while read space;

do

DISK=$(echo $space | cut -d “%” -f1)
DRIVENAME=$(echo $space | cut -d ” ” -f2)

if [ "$DISK" -ge "$THRES" ]

then

echo You have used “$DISK”% on drive “$DRIVENAME” on server “$HOST” >>alert.txt

fi

done
echo alert.txt | mail -s “Disk space Alert on server $HOST” root

Reply

39 Amer Siddique January 9, 2012

This script is working fine

#!/bin/sh
df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $6 }' | while read output;
do
  echo $output
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
  echo $usep
  partition=$(echo $output | awk '{ print $2 }' )
  if [ $usep -ge 90 ]; then
    echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date) :  $usep%" |
     mail -s "Alert: Critical Almost out of disk space $partition $usep%"
Someone@email.com  fi
 if [ $usep -ge 85 ]; then
    echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date) :  $usep%" |
     mail -s "Alert: Warning Almost out of disk space $partition $usep%" amer.siddique@bskyb.com
  fi
done

Reply

Leave a Comment

You can use these HTML tags and attributes for your code and commands: <strong> <em> <ol> <li> <u> <ul> <blockquote> <pre> <a href="" title="">




Previous post:

Next post: