Introduction: Simple Script to Monitor Linux Disk Usage

I wanted to have a simple means of monitoring my hard disk usage on my Linux server which has a single partition. After some work, I developed a system which e-mailed me every week the percentage of disk partition which had been used. I know there are a lot of packages out there that do this, but I wanted to develop something which I could control and had a very low processing overhead; enter Bash, SSMTP and Cron.

Step 1: Overview

I needed to do the following:

1) Write a script which could manipulate the Linux command df -h which shows the free disk usage. By manipulate, I mean show only selected lines.

2) E-mail the output to myself.

3) Set it up as a scheduled job on my server.

4) Optionally, incorporate it within my monitoring system.

Step 2: Writing the Monitoring Script

Firstly, let's look at the df-h command. By logging onto my server through the terminal editor putty, I was able to examine the output of this command.

df -h
Filesystem Size Used Avail Use% Mounted on

rootfs 9.9G 1.9G 7.5G 20% /

udev 10M 0 10M 0% /dev

tmpfs 197M 156K 197M 1% /run

/dev/vda1 9.9G 1.9G 7.5G 20% /

tmpfs 5.0M 0 5.0M 0% /run/lock

tmpfs 393M 0 393M 0% /run/shm

The important thing for me was the first line because this gave the total usage of the whole partition. This would obviously be different if there were more partitions but it shows the principle.

Next, I wanted to just use those first two lines. I wrote a script /bin/test_array_cmd and made it executable using chmod 755

The contents of the script are as follows:

#!/bin/bash

#write the output of df-h into an array
readarray -t array <<< "$(df -h)"

#print out 1st 2 elements of array

echo "${array[0]}"

echo "${array[1]}"

#print out whole array - for illustration only - uncomment the following line if you need it

#printf -- "%s\n" "${array[@]}"

I tested the script using the dot notation.

/bin# ./test_array_cmd
Filesystem Size Used Avail Use% Mounted on

rootfs 9.9G 1.9G 7.5G 20% /

This shows me that I have used 20% on my hard drive.

Step 3: Creating an Email Task and Scheduled Job

I had previously installed SSMTP and MailUtils on my server and so was able to send emails from the Linux command line. Initially I tested the output from the commad line as follows:

./test_array_cmd | mail -s 'ByblosBlooms usage' myemailaddress@mydomain.com

Byblosblooms is the name of my test site. -s defines the subject line of the email. I received the e-mail I expected in a few seconds.

Next, I had to set up a scheduled job to send me this information on a weekly basis. I invoked crontab -e and added the following line:

# m h dom mon dow command
0 5 * * 1 sudo /bin/test_array_cmd| mail -s 'ByblosBlooms usage'
myemailaddress@mydomain.com

The syntax means that at 5 a.m. (5) on Monday (1) i execute the script and email it to myself.

Step 4: Next Steps

I have considered modifying the script and taking element 1 of the array, "${array[1]}" rootfs 9.9G 1.9G 7.5G 20% / so that I could then send the %utilisation value, in this case 20%, to my cloud monitoring system and report on it when it exceeds a predefined target.

To do this, one way requires a more advanced knowledge of Bash and to illustrate this, consider a modification (modifications in bold ) of my original script

#!/bin/bash

readarray -t array <<< "$(df -h)"

#print out 1st 2 elements of array

echo "${array[0]}"

echo "${array[1]}"

#print out whole array

#printf -- "%s\n" "${array[@]}"

#find out the position of the % sign

var=$(echo "${array[1]}"| grep -aob '%' | grep -oE '[0-9]+')

#extract sub string with % sign

echo "$var" # returns position of % in string

echo "${array[1]:$var-3:4}" # returns 20%

#remove the %sign so that we only have a numeric value

echo "${array[1]:$var-3:4}" | tr --delete '%G' # returns 20

To explain this, the line var=$(echo "${array[1]}"| grep -aob '%' | grep -oE '[0-9]+') assigns to the variable var the position of the % character in element 1 of the array, rootfs 9.9G 1.9G 7.5G 20% /

So, using the variable var, we can extract "20%" as a substring using:

echo "${array[1]:$var-3:4}"

$var-3:4 means that we start at 3 positions before the position of the %sign - i.e. at the space after 7.5 G, (7.5G 20%) Then we take 4 characters from that position which gives us 20%. (with a space before it), Note that if the %space used was less than 10 % then we would return G5%. (7.5G 8%) from We have to allow for also removing the G.

The last line of the script deletes the % sign and G in case we want to process it further an integer. To do this we add the tr command to the previous line

echo "${array[1]:$var-3:4}" | tr --delete '%G'

Of course, you won't use all of these commands in your own script, just those which are suited for your application.

To conclude, the output of my modified script looks like this

./test_array_cmd
Filesystem Size Used Avail Use% Mounted on

rootfs 9.9G 1.9G 7.5G 20% /

20%

20