Bash scripts examples : Check filesystem space

bash shell

Introduction

Here is a new chapter of the “Bash script examples” series.

In this chapter I will be covering one of the main system administrator task : Monitoring server available space. The script shown here is definitely not a “bullet-proof_portable_to_any_system” script, I see it more as a good base to build your own.

This script is mainly checking space of every mounted filesystems (matching a given fs type, e.g : ext2 or fuseblk) or a custom filesystem (-d option) and if the used space is larger than the threshold, then a warning message is sent (it is actually sent to stdin in this code : I commented the mail part). You can also get the the 5 biggest files/dirs (-S option) or a custom number (-s option) .

Please keep in mind that the servers I am working with are NOT connected to the internet : security may not be at its best here.

I use this script almost as it is here at my job, so feel free to copy it customize it, or add new thought in the comment section.

This script might looks a bit too much but for what it seems to be doing, but when you check the available options, and the way you can use them, it is a quite good space monitoring solution, put this in a cron and you are done !

 

More “bash scripts examples” posts

 

TODO :

  1. A real error management : I started with the ErrorPrintandlog() function but it does not work as for now.

 

Comments are very welcome, i really love learning new stuff, and smart coding.

1 The Code

#! /bin/bash

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Company name - Division name - Project name
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# HallOfTips - 09/05/2012 - SpaceChk.bash - v1.0
# ---------------------------------
# This script check the used space for [all|given] filesystem(s).
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#####################################
##### TODO
#####################################

# Add error management: error code variables ; script option analysis (there must be NO options) ; existing checkup for files & dir  --> DONE : NEED TESTS

#####################################
##### VARIABLES
#####################################

# Generals variables
ADMIN="Email_1"					# The email addresses to which the mail is sent
HostName=$(hostname)
TmpDir="/tmp"
TmpFile="${TmpDir}/SpaceChk_EMAIL_${HostName}_$(date +%Y-%m-%d)_$$"
ErrorLog="${TmpDir}/SpaceChk_ERROR_${HostName}_$(date +%Y-%m-%d)_$$"
Error="2"
F_Error="66"
E_OPTERROR="3"

# Specific variables
ThresHold="70"          			# The "threshold" against which filesystems used space is tested (below this threshold nothing happened)
HeadValue="5"   				# The number of biggest dirs to be printed
Valid_types_pattern="(ext(2|3|4)|fuseblk)" 	# These are the filesystems that will be tested : it must be built as ONE "ERE" pattern

#####################################
##### USAGE
#####################################

# usage & examples
Usage() {
  cat <<- EOF
    Usage: $(basename $0) [-h] [-S] [-s [1-10]] [-d MOUNT_POINT]

    Options:
    -h		Print this message (help)
    -S		Sort and print the "5" biggest directories
    -s "n"		Same as "-S" but with a custom "n" biggest direct (where 1<n<10)
    -d directory	Check only the filesystem to which belongs the directory given as argument

    Examples:
    - check all mounted filesystems :
    $(basename $0)

    - check all mounted filesystems AND get the "5" (default) biggest directories :
    $(basename $0) -S

    - check all mounted filesystems AND get the "9" biggest directories :
    $(basename $0) -s 9

    - check only a specific mounted filesystems :
    $(basename $0) -d /data

    - check only a specific mounted filesystems plus the "8" biggest directories :
    $(basename $0) -s 8 -d /home/users
EOF
  exit $E_OPTERROR
}

#####################################
##### OPTION MANAGEMENT
#####################################

# Process options analysis
while getopts ":hSs:d:" Option ; do

  case $Option in 
    s ) Sort_Flag="1"
	HeadValue="${OPTARG}"
        if [[ ! "${OPTARG}" =~ ^(1|2|3|4|5|6|7|8|9|10)$ ]] ; then # if the $OPTARG is NOT an number between 1 and 10 (inclusive) : EXIT + Usage
	      Usage && exit "${E_OPTERROR}"
        fi
    ;;
    d ) Directory_flag="1"
	if [[ ! -d "${OPTARG}" ]] ; then
	  echo "Invalid argument : ${OPTARG/%\//} must be a valid directory" >&2 && Usage && exit "${E_OPTERROR}" # this handle the "invalid option" case
	else
	  CheckedDir="${OPTARG/%\//}"
	fi
    ;;
    h ) Usage && exit "${E_OPTERROR}"
    ;;
    S ) Sort_Flag="1"
    ;;
    \? ) echo "Invalid option: -${OPTARG}" >&2 && Usage && exit "${E_OPTERROR}" # this handle the "invalid option" case
    ;;
    : ) echo "Option -${OPTARG} requires an argument" >&2 && Usage && exit "${E_OPTERROR}" # this handle the "invalid parameter for this option" case
    ;;
  esac
done

#####################################
##### FUNCTIONS
#####################################

# The cleaning function cleans everything after the script is terminated, either for regular termination or interruption. It is called by the trap command
Cleaning () {
 echo "Cleaning before exiting..."
 rm -f ${TmpFile}
 exit 0
}

# This is the function that print AND log any errors occurring during $0 execution: print $1 on screen AND print $2 (the message) in $ErrorLog)
ErrorPrintandlog () {
if [[ "${1}" = "${F_Error}" ]] ; then
  echo  "=> FATAL_ERROR : ${2}
  (see ${ErrorLog} for more infos)" && echo "${2}" >&2 && exit ${F_Error}
elif [[ "${1}" = "${Error}" ]] ; then
  echo  "=> ERROR (see ${ErrorLog} for more infos)" && echo "${2}" >&2
fi
# >> ${ErrorLog} 
}

# This checks if used "files and/or dirs" exists or not (to avoid very long operations, such as "du" on root dir...)
Controls () {
for t in "$@" ; do
   if [[ ! -d "${t}" ]] && [[ ! -e "${t}" ]] ; then
     ErrorPrintandlog "${F_Error}" "${t} does not exist!"
   fi
done
}

# The following function checks the "used size" for the given Filesystem mount point and return "${SpaceWarnCode}" if the threshold crossed
FSChck () {

  df -TP $CheckedDir| grep -E "${Valid_types_pattern}" |
  while read dev type total_size used_size free_space percent mount_p ; do
    Controls "${mount_p}"
    if [[ "${percent%\%}" -gt "${ThresHold}" ]] ; then
      RETURN="${SpaceWarnCode}"  # return ${SpaceWarnCode} if space usage is beyond ThresHold
      echo "WARNING : ${mount_p} (${dev}) on ${HostName} is filled up to ${percent} ..."
      if [[ ! -z "${Sort_Flag}" ]] ; then
      Classt "${mount_p}"
      fi
    #   EMAIL=$(cat ${TmpFile})
    fi
  done 

 return $RETURN
}

# Print and format the ${HeadValue} biggest dir from ${CheckedDir}
Classt () {
  CheckedDir="$1"
  count=1
  echo ""
  echo "Here is the ${HeadValue} biggest directories located in ${CheckedDir}:"
  echo ""
  du -a --max-depth=1 --one-file-system --exclude='*/proc/*' ${CheckedDir}/ |
  sort -rn |
  sed "1d" |
  head -"${HeadValue}" |
  while read size dirrr ; do
      size="$(( size / 1000000 ))"
      echo "N°${count} : ${dirrr} is ${size} Go"
      ((count++))
  done
  echo ""
}

# This is the sending email function
SendMail() {

echo ${EMAIL}
# nc -v mailhost 25 1>/dev/null << EOF
# ehlo ${HOSTNAME}
# mail from: ${HOSTNAME}
# #rcpt to: $ADMIN
# #rcpt to: $ADMIN2
# rcpt to: $ADMIN3
# data
# From: ${HOSTNAME}
# #To: $ADMIN
# #To: $ADMIN2
# To: $ADMIN3
# Subject: Critical size on ${HOSTNAME}
# ${EMAIL}
# .
# quit
# EOF
}

#####################################
##### MAIN
#####################################

# Set the trap command that will call the Cleaning function in any termination cases
# trap "Cleaning" SIGHUP SIGINT SIGKILL

Controls
FSChck
SendMail

 

 

2 The output

WARNING : /home on ServerTest is filled up to 91% ...

Here is the 5 biggest directories located in /home/users:

N°1 : /home/users/user4 is 120 Go
N°2 : /home/users/admincc is 18 Go
N°3 : /home/users/user12 is 10 Go
N°4 : /home/users/user33 is 9 Go
N°5 : /home/users/user0 is 9 Go

3 thoughts on “Bash scripts examples : Check filesystem space

  1. Francis

    Hello !
    – Areyou sure the “Usage() .. ” function must end by an “exit …” ? Perhaps a “return …” is safer ?
    Francis

    1. Pier Post author

      Hi Francis,
      It’s been à long time since i wrote this script … Exiting is the wanted behaviour un this case which is why i used à ‘exit’ instead of à ‘return’.
      Thanks for your comment francis, bonnes fêtes!

  2. Pingback: Disk Usage I need to create a script sends an email message to the user specified on

Leave a Reply to Pier Cancel reply

Your email address will not be published. Required fields are marked *

This site supports SyntaxHighlighter via WP SyntaxHighlighter. It can highlight your code.
How to highlight your code: Paste your code in the comment form, select it and then click the language link button below. This will wrap your code in a <pre> tag and format it when submitted.