Monitor UNIX / Linux Server Disk Space with Shell Script

in Categories Monitoring last updated April 10, 2008

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

Share this on:

43 comment

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

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

      1. 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"
  2. 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
    
  3. 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?

    1. 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 < $DISKS
      
  4. 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..

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

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

  7. 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 }’

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

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

Leave a Comment