Monitor UNIX / Linux Server Disk Space with Shell Script

Shell script to monitor or watch the disk space and send an email alert if the (free avilable) percentage of space is >= 90%

#!/bin/sh
# Shell script to monitor or watch the disk space
# It will send an email to $ADMIN, if the (free avilable) percentage 
# of space is >= 90% 
# -------------------------------------------------------------------------
# Copyright (c) 2005 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# ----------------------------------------------------------------------
# Linux shell script to watch disk space (should work on other UNIX oses )
# SEE URL: http://www.cyberciti.biz/tips/shell-script-to-watch-the-disk-space.html
# set admin email so that you can get email
ADMIN="me@somewher.com"
# set alert level 90% is default
ALERT=90
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 $ALERT ]; then
    echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date)" | 
     mail -s "Alert: Almost out of disk space $usep" $ADMIN
  fi
done
🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source, and DevOps topics via:
Category List of Unix and Linux commands
Disk space analyzers df ncdu pydf
File Management cat tree
Firewall Alpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilities NetHogs dig host ip nmap
OpenVPN CentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Manager apk apt
Processes Management bg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searching grep whereis which
User Information groups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPN Alpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
44 comments… add one
  • Gouthami Nov 4, 2020 @ 10:37

    I am looking for a script should be finding the quota soft and hard limits and also send out an email

  • sahana Feb 10, 2017 @ 9:36

    Hi All ,
    Good script , I also have a requirement to clear old logs created before one month from say today to clear space if the alert is reached . Please help me ..

  • Learning DBA Oct 3, 2016 @ 12:01

    I am getting an error

    Syntax error: “fi” unexpected

    Please Help!!!

  • Rocky Islam Jul 2, 2015 @ 10:09

    i’m new in scripting … using this command i didn’t get any mail ….. help me

  • omprakash Dec 6, 2013 @ 7:44

    i want 5 mail alert instead of many alert when disk space reached max limit .

  • Leszek Nov 11, 2013 @ 15:50

    Hi,

    Thanks for the script. It’s doing it’s job nicely but I’m a little surprised nobody complained about an error it returns if You don’t cut off the first line of df output:

    ./monitor.sh: 22: [: Illegal number: dost.

    I had to change line 19 to:

    df -H | grep -vE ‘^Filesystem|tmpfs|cdrom’ | tail -n+2 | awk ‘{ print $5 ” ” $1 }’ | while read output;

  • Scriptiee Jul 11, 2013 @ 7:42

    Brilliant little script, will put it to good use! Thanks guys

  • Yamaranews Mar 30, 2013 @ 8:13

    Its very helful
    Thank you

  • KC Apr 27, 2012 @ 13:04

    Thanks, VIVEK and BEN. Very nice script and the quick correction, thanks a lot.

  • Andre Oct 19, 2011 @ 8:24

    Just answered my own question after a few days of figuring out bash regex. Are there any other more elegant ways?

    # set alert level 95% is default
    ALERT=95
    # The current variable takes from a file which gives the prior saved value of usage
    current=`cat /tmp/currentUsage`

    df -PH | grep -vE ‘^Filesystem|tmpfs|cdrom’ | awk ‘{ print $5 ” ” $1 }’ | while read output;
    do
    usep=$(echo $output | awk ‘{ print $1}’ | cut -d’%’ -f1)
    partition=$(echo $output | awk ‘{ print $2 }’ )

    # If current usage is greater than ALERT and is greater the prior value then send a mail.

    if [ $usep -ge $ALERT ] && [ $usep -gt $current ]; then
    echo “Running out of space \”$partition ($usep%)\” on $(hostname) as on $(date)” |
    mail -s “Alert: Almost out of disk space $partition $usep%” $ADMIN

    # establish the new current value
    echo $output | awk ‘{ print $1}’ | cut -d’%’ -f1 > /tmp/currentUsage
    fi
    done

  • Andre Oct 18, 2011 @ 1:48

    Hi,

    Right now, I have setup a cronjob to run this script hourly.
    Does anyone know how to stop the email to be sent out if the previous quota level is the same as the current one?

    i.e.: An email is sent once it hits the 95% threshold; however at the next hour if the level is still at 95%, no email is sent till it hits 96% or more.

  • Dinesh Jul 6, 2011 @ 7:25

    Hi,

    I am new to scripting.
    I have run this and working perfectly.
    Just want 2 modifications.

    If i want to check for more than one server using same script.
    And i want single mail instead of many.

    Please Help. :)

  • Anon Apr 20, 2011 @ 16:18

    I have tried the script and it does not appear to work.

    I set the limit to “35”, as I wanted to test it out and the highest percentage usage was 38%. I changed the E-Mail address to what I want to use and then ran the script. The script has not sent me an E-Mail after 10 minutes of running it.

    I tried the “-P” that was mentioned in several comments without luck.

    The server that this script is currently running on is a basic Ubuntu 9.04 server and has only had SSH installed.

  • Anonymous Mar 24, 2011 @ 14:59

    Thanks UWAYO.
    -P option worked with the script. Nice and simple script..

  • Ben Oct 19, 2010 @ 14:11

    you should also use the -P option of df “df -P -H”
    (-P for POSIX compatibility so you dont get into trouble when your diskname ist to long like /dev/mapper/VolGroup00-LogVol00)
    also df -i (for inodes) is highly recommended to use, because you easily forget to check for inodes if you have free space but cant create a file =)

    • nicole Jan 17, 2011 @ 4:53

      Hi, i’m a newbie, and i’ve been asked to create a script that will monitor different directories in different systems e.g.:

      /home of system1 – 60%
      /models of system2 – 70%
      /bikes of system3 – 80%

      and any of the above meet their respective threshold, will send an email to me
      informing that that particular directory is on limit.

      fyi, i have a server than can ssh to all of this directories/systems.

      hoping for your quick response.

  • UWAYO Jacques Sep 8, 2010 @ 18:32

    i get the below error what could be the problem

    but i dont receive anything
    #!/bin/bash
    # script to send simple email
    # email subject
    SUBJECT=”SET-EMAIL-SUBJECT”
    # Email To ?
    EMAIL=”myemail@gmail.com”
    # Email text/message
    EMAILMESSAGE=”/tmp/tutorials/emailmessage.txt”
    echo “This is an email message test”> $EMAILMESSAGE
    echo “This is email text” >>$EMAILMESSAGE
    # send an email using /bin/mail
    /bin/mail -s “$SUBJECT” “$EMAIL” < $EMAILMESSAGE

  • charles May 28, 2010 @ 19:31

    this script seems to run but I never get an email. I tested with a simple email from the server and it came through fine. Here’s the output I get when I debug the script with bash -x (I’m a linux newbie):

    + ADMIN=me@mydomain.org
    + ALERT=20
    + df -H
    + grep /
    + grep -vE ‘^Filesystem|tmpfs|cdrom’
    + awk ‘{ print $5 ” ” $1 }’
    + read output
    ++ awk ‘{ print $1}’
    ++ cut -d% -f1
    ++ echo 54% /dev/vzfs
    + usep=54
    ++ echo 54% /dev/vzfs
    ++ awk ‘{ print $2 }’
    + partition=/dev/vzfs
    + ‘[‘ 54 -ge 20 ‘]’
    ++ hostname
    + mail -s ‘Alert: Almost out of disk space 54’ me@mydomain.org
    ++ date
    + echo ‘Running out of space “/dev/vzfs (54%)” on ip-72-XXX-XX-XYZ.ip.secureserver.net as on Fri May 28 12:28:55 PDT 2010’
    + read output

    • Charles May 28, 2010 @ 20:11

      Actually just found out it works fine. My email was down temporarily! Thanks!

  • erdenebat Nov 4, 2009 @ 7:18

    very good!! it’s my was finding script.

    • John Mathew Mar 24, 2010 @ 6:00

      Hi,

      I have the following script;

      #!/bin/ksh
      ADMIN=”me@somewhere.com”
      # set alert level 90% is default
      ALERT=80
      df | grep -E “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 $ALERT ]; then
      echo “Running out of space \”$partition ($usep%)\” on $(hostname) as on $(date)” |
      mail -s “Alert: Almost out of disk space $usep” $ADMIN
      fi
      done

      While I run the script it gives the following error, please help me. I have named the file as x.ksh and also let me know how to run the script.
      Thanks.

      • d0rk Jul 27, 2011 @ 23:46

        you are using the korn shell, which has many differences from bash. first off, to use parameter substitution in that shell you need:

        echo -e "string with backslash \n"
  • Stephen Adams Jun 15, 2009 @ 0:03

    Hi there,

    Nice script. I modified it in the following way for my company

    #!/bin/bash
    
    #admin email account
    ADMIN="admin@company.com"
    
    # set usage alert threshold
    THRESHOLD=40
    
    #hostname
    HOSTNAME=$(hostname)
    
    #mail client
    MAIL=/usr/bin/mail
    
    # store all disk info here
    EMAIL=""
    
    for line in $(df -hP | 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
    done 
    
    if [ -n "$EMAIL" ];
    then 
    	echo -e "$EMAIL" | $MAIL -s "Alert: Partition(s) almost out of diskspace on $HOSTNAME" "$ADMIN"
    fi
    
    • 🐧 Vivek Gite Jun 15, 2009 @ 5:37

      Thanks for sharing the code. I’ve updated your post with pre tags.

  • john May 5, 2009 @ 14:34

    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?

    • 🐧 Vivek Gite May 6, 2009 @ 19:14

      You can modify script as follows:

      #!/bin/bash
      ADMIN="me@somewher.com"
      # set alert level 90% is default
      ALERT=90
      # store all disk info here
      DISKS="/tmp/out.df.$$"
      echo "Running out of space on $(hostname) as on $(date)" > $DISKS
      echo "" >> $DISKS
      EMAIL=0
      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 $ALERT ]; then
      	echo "*** $partition ($usep%) ***" >>$DISKS
      	EMAIL=1
        fi
      done
      
      [ "$EMAIL" == "1" ] && mail -s "Alert: Almost out of disk space $usep" $ADMIN 
      						
  • Todd Allis Mar 25, 2009 @ 23:50

    Thanks! I needed to change it to “df -HP” (Thanks, John Adams!), but then it worked fine. I incorporated it into an existing email notification script.

  • John Adams Mar 10, 2009 @ 18:38

    I had a similar problem with a file system checker that I wrote.
    I found that if I did a “df -P” then the LVM filesystem output would be on a single line and I could parse it. It seems the LVM filesystem names can be rather large and end up on two lines, causing confusion to the grep command..

    • Bill Mar 11, 2010 @ 22:51

      Thanks for the LVM fixed, been searching about for that answer!

  • dharjee Mar 10, 2009 @ 14:36

    Hello

    if I ran this script on my server it showed this error:
    ./diskspace: line 23: [: /dev/mapper/system-Xraid_5.4TB: integer expression expected
    ./diskspace: line 23: [: /xraid: integer expression expected

    Please any suggestion?

    Thanx

  • hudipirlo Feb 18, 2009 @ 2:59

    hi vivik

    if this script is run on the system lvm eror occurred, example

    gareng:~ # df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/sda3 31G 2.6G 29G 9% /
    tmpfs 4.0G 8.0K 4.0G 1% /dev/shm
    /dev/sda1 134M 41M 93M 31% /boot
    /dev/mapper/vgu01-lvu01
    274G 91G 183G 34% /u01
    /dev/mapper/vghome-lvhome
    20G 288M 19G 2% /home
    /dev/mapper/vgusr-lvusr
    20G 6.6G 13G 35% /usr
    /dev/mapper/vgtmp-lvtmp
    15G 35M 15G 1% /tmp
    /dev/sdc1 30G 15G 14G 52% /source
    /dev/sdc2 491G 162G 305G 35% /oradb

    i run scripts

    gareng:~ # sh coba.sh
    coba.sh: line 11: [: /dev/mapper/vgu01-lvu01: integer expression expected
    coba.sh: line 11: [: /u01: integer expression expected
    coba.sh: line 11: [: /dev/mapper/vghome-lvhome: integer expression expected
    coba.sh: line 11: [: /home: integer expression expected
    coba.sh: line 11: [: /dev/mapper/vgusr-lvusr: integer expression expected
    coba.sh: line 11: [: /usr: integer expression expected
    coba.sh: line 11: [: /dev/mapper/vgtmp-lvtmp: integer expression expected
    coba.sh: line 11: [: /tmp: integer expression expected

    i need your help

    thanks

    hudipirlo

    • d0rk Jul 27, 2011 @ 23:43

      you cannot run this with sh … you need bash as it is a BASH script.

  • vbavbalist Feb 12, 2009 @ 8:15

    How to exact use/put this script? Can you explain please . Using Redhat enterprise

  • wah Feb 12, 2009 @ 8:04

    well done ^_^

  • Tomeu Sastre Jan 22, 2009 @ 10:52

    Magnificent script.

    I’ve seen that it has a little “bug”, because it throws an error because when doing the loop it finds a non numeric value due the header of the df command.

    To resolve it I added this command to the line
    grep / (that makes tot “grep” all that have the “/” symbols, that are relatet to volumens

    and the results is :
    df -H | grep / | grep -vE ‘^Filesystem|tmpfs|cdrom’ | awk ‘{ print $5 ” ” $1 }’

  • Carl Jan 21, 2009 @ 21:12

    I need help with this can anyone help
    1) Create a subdirectory in /tmp and move multiple file(s) specified in the script argument to that directory.
    2) Compress each of these files by calling a compression program.
    3) Move the file(s) back to the original directory (after checking if under the disk quota).
    4) Use a foreach loop to do this for each file one at a time.
    4) Perform error checking

  • FD Jan 18, 2009 @ 6:35

    The script looks simple and nice… but how to do run it on redhat? do I just put on specific folder? Cron job? please let me know..

  • Caterpillar Jan 16, 2009 @ 10:49

    Super!!

  • xiaofu Nov 25, 2008 @ 9:35

    well done!

  • adhitya christiawan nurprasetyo [dit] Nov 12, 2008 @ 2:17

    my server using another port of ssh,
    can you tell me where to modify the script?
    thank you…

  • JC Oct 15, 2008 @ 8:01

    Thanks for this excellent script !

    I would just perform a “df -HP” so it would be safer : -P for Posix display to avoid bugs with the awk.

    Cheers

  • vivek Jul 31, 2008 @ 21:43

    What kind of issues you are having with regex?

  • Eddie Jul 30, 2008 @ 14:08

    Excellent, thanks!

    I am trying to write one to monitor my Raid but having some issues with the regular expressions. Any ideas?

    Cheers

  • Amit Jun 18, 2008 @ 13:42

    Good Script

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.