Perl script to monitor disk space and send an email

by on February 21, 2007 · 35 comments· LAST UPDATED May 5, 2008

in , ,

Here is a quick question by one of our regular reader :

How to write a perl script that can monitor my disk space under UNIX or Linux and send me an email alert?

There is a nice perl system routine called Perl df or Filesys::DiskSpace. This routine displays information on a file system such as its type, the amount of disk space occupied, the total disk space and the number of inodes etc.

Task: Install Filesys::DiskSpace

First you need to install this perl module using apt-get or from cpan (Comprehensive Perl Archive Network).
$ sudo apt-get install libfilesys-diskspace-perl

Perl script code to monitor disk space

Now write a perl script called df.pl:
$ vi df.pl
Append following code:

#!/usr/bin/perl
use strict;
use warnings;
use Filesys::DiskSpace;
 
# file system /home or /dev/sda5
my $dir = "/home";
 
# get data for /home fs
my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;
 
# calculate free space in %
my $df_free = (($avail) / ($avail+$used)) * 100.0;
 
# display message
my $out = sprintf("Disk space on $dir == %0.2f\n",$df_free);
print $out;
 

Save and close the file. Run this script as follows:
$ chmod +x df.pl
$ ./df.pl

Output:

Disk space on /home == 75.35

So /home has 75.35% free disk space. Next logical step is to compare this number to limit so that you can send an email if only 10% free disk space is left on /home file system. Here is the code with

#!/usr/bin/perl
use strict;
use warnings;
use Filesys::DiskSpace;
 
my $dir = "/home";
 
# warning level 10%
my $warning_level=10;
 
my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;
my $df_free = (($avail) / ($avail+$used)) * 100.0;
 
# compare free disk space with warning level 
if ($df_free < $warning_level) {
my $out = sprintf("Send an Email - Disk space on $dir => %0.2f%% (WARNING Low Disk Space)\n",$df_free);
print $out;
}
else
{
my $out = sprintf("Disk space on $dir => %0.2f%% (OK)\n",$df_free);
print $out;
}

Run script as follows:
$ ./df.pl
Output:

Send an Email - Disk space on /home => 3.99% (WARNING Low Disk Space)

Here is final code that send an email alert ( download):

#!/usr/bin/perl
# Available under BSD License. See url for more info:
# http://www.cyberciti.biz/tips/howto-write-perl-script-to-monitor-disk-space.html
use strict;
use warnings;
use Filesys::DiskSpace;
 
# file system to monitor
my $dir = "/home";
 
# warning level
my $warning_level=10;
 
# email setup
my $to='admin@yourdomain.com';
my $from='webmaster@YOURDOMAIN.COM';
my $subject='Low Disk Space';
 
# get df
my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;
 
# calculate 
my $df_free = (($avail) / ($avail+$used)) * 100.0;
 
# compare 
if ($df_free < $warning_level) {
my $out = sprintf("WARNING Low Disk Space on $dir : %0.2f%% ()\n",$df_free);
 
# send email using UNIX/Linux sendmail
open(MAIL, "|/usr/sbin/sendmail -t");
 
## Mail Header
print MAIL "To: $to\\n";
print MAIL "From: $from\\n";
print MAIL "Subject: $subject\\n";
 
## Mail Body
print MAIL $out;
 
close(MAIL);
}
 

You can run this script as a cron job:
@hourly /path/to/df.pl

Recommended readings

=> Read man page of this module by typing following command:
$ man filesys::diskspace

=> CPAN filesys::diskspace webpage

=> Sending mail with Perl mail script and How do I send html email from Perl?

=> Shell script to monitor or watch the disk space



If you would like to be kept up to date with our posts, you can follow us on Twitter, Facebook, Google+, or even by subscribing to our RSS Feed.


{ 34 comments… read them below or add one }

1 Thomas February 26, 2007 at 12:56 pm

Nice script.

I though had to change the sendmail part to:

## Mail Header
print MAIL “To: $to\n”;
print MAIL “From: $from\n”;
print MAIL “Subject: $subject\n”;

to get sendmail working correctly.

Reply

2 nixcraft February 26, 2007 at 1:48 pm

Thomas,

Opps stupid xhtml was causing problem. Post has been updated

Appreciate your post.

Reply

3 Thomas February 26, 2007 at 1:50 pm

No prb. Nothing beats a good script ;ø)

Reply

4 Markus February 27, 2007 at 10:05 am

You could also you Monit [1] to monitor disk space and several other services/daemons.

[1] http://www.tildeslash.com/monit/

Reply

5 Buchan Milne February 27, 2007 at 4:20 pm

IMHO, it would be better to implement a server monitoring system, which will also allow monitoring of other metrics, such as CPU utilisation, memory use, network port counts, log messages, network traffic, network checks, and more.

I use hobbit for this, which supports all of this out-the-box, and with no configuration required to have the memory, cpu utilisation, disk usage graphs working.

Reply

6 Peter Boosten February 27, 2007 at 5:01 pm

Although your perl script is nice, you could do it with a standard shell script as well:

for fs in `df -k|awk '{print $1}'|sed -n "2,14 p"`; do
   x="`df -kl | grep $fs | awk '{ print $5 }'| sed -e 's/%//'`"
   y="75"
   if [ $fs != "kernfs" ]; then
     if [ $fs != "procfs" ]; then
       if [ "${x}" -gt "${y}" ]; then
         message="File System `df -k |grep $fs |a
wk '{print $6\",\"$5}'` Full"
         echo $message | mail -s "`hostname` - Fi
le System Full Warning" root
       fi
     fi
   fi
done

Reply

7 nixcraft February 27, 2007 at 6:33 pm

@Markus / Buchan

I do agree with all of you monit is much better but one of our loyal and regular reader wanted perl script.

@Pete
Thanks for a shell script.

Appreciate all of your posts.

Reply

8 trupti April 26, 2007 at 8:07 am

hi, can you please help me to write a perl script to read emails?

Reply

9 Pushpa May 24, 2007 at 7:31 pm

I am installing the Filesys::diskspace module and when I do make test I get the error as
———————————————-
t/linux-ext2…..Can’t use an undefined variable as ARRAY reference at t/linux-ext2.t line26
——————————————–

Anyone has encountered this problem previously..can you please tell me what the problem is

Reply

10 Hrvoje July 29, 2007 at 5:58 pm

I get this error

“Cannot use df on this machine (untested or unsupported). ”

everything installed (moudles etc..)

can some one help me?

thank you!

Reply

11 Paolo Saudin August 17, 2007 at 7:20 am

I get “statfs failed on /home (new filesystem type?) .. ” error. Any idea?
Thanks!

Reply

12 John September 7, 2007 at 4:31 pm

I am getting an error “An error occured. statvfs failed. Did you run h2ph?” Any idea?

Reply

13 Icapan September 20, 2007 at 12:23 pm

How we can make tests that we don’t send multiple e-mails? I’ve done that in shell scripts by setting up /tmp/mail_sent file and checking if it exists. After I logged onto a machine and free up some disk, I would remove the lock file.
My Perl is a bit rusty, so can anyone write the enhancement?

Reply

14 Icapan September 21, 2007 at 2:46 pm

Well, for multiple e-mails, here it is:

## Mail Body
if (-e "/tmp/sms_sent")
{
print "already sent";
}
else
{
print MAIL $out;
system ("touch /tmp/sms_sent");
}

Reply

15 Renante June 26, 2008 at 10:04 am

Hi!

I tried running the script on my mac os x leopard 10.5.3 machine and it says “Cannot use df on this machine (untested or unsupported).”

What should I do? Sorry I’m quite a newbie into this thing.

Reply

16 David December 22, 2008 at 2:21 am

For RPM based Linux systems like CentOS and Fedora, install the perl-Filesys-DiskSpace package with:
# yum install perl-Filesys-DiskSpace

Reply

17 RC January 12, 2009 at 10:04 pm

Hi

I am a newbie to perl programming. Can somebody explain the following line? I understood rest of the program except for this bit. How are we getting this array out of the df command?

my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;

Thanks for your help!

Reply

18 Satya October 6, 2010 at 2:09 am

Hi RC,
I have just basic knowledge of UNIX Cmd and now want to write Unix PErl Script.
.which book I can refer to go with.

Thanks,

Reply

19 Ken February 17, 2009 at 8:29 pm

the df command there is part of the perl library FileSys::DiskSpace and not the normal df command available from the OS. This script is short and sweet but in my opinion, overly dependant on external libraries. The whole thing could have been written thusly..

#!/usr/bin/perl
use strict;
use warnings;
# file system to monitor
my $target = shift;
# warning level
my $warning_level=10;
# email setup
my $to='whomever@whatever.com';
my $from='root@whereever.com';
my $subject='Low Disk Space Warning';
# get df
my ($fs_dev, $fs_type, $size, $used, $avail, $use, $mount) = split(" ", `df -PT $target | tail +2`);
# calculate
my $df_free = (($avail) / ($avail+$used)) * 100.0;
# compare
if ($df_free < $warning_level) {
my $out = sprintf("WARNING Low Disk Space on $target : %0.2f%% ()\n",$df_free);
# send email using UNIX/Linux sendmail
open(MAIL, "|/usr/sbin/sendmail -t");
## Mail Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n";
## Mail Body
print MAIL $out;
close(MAIL);
}

Reply

20 Neru April 10, 2009 at 2:00 pm

Guys, my script is slightly different, basically i’m wanna count files in a directory and after certain amount of files, the script should send me alert.

I’ve two problems with the current.

1. I’m recieving emails but without body message
2. I’m getting following error while execute this script:

Useless use of private variable in void context at ./VMCount.pl line 38.

However there is nothing wrong with line# 38, as i hve “}” on this line

any comments?

Reply

21 domaniqs November 27, 2009 at 10:06 am

Hello,
would enyone tell me why do I get such an error during execution of Kens script:
—————————————–
Use of uninitialized value in concatenation (.) or string at ./new_df.pl line 17.
tail: cannot open `+2′ for reading: No such file or directory
Use of uninitialized value in addition (+) at ./new_df.pl line 20.
Use of uninitialized value in addition (+) at ./new_df.pl line 20.
Use of uninitialized value in division (/) at ./new_df.pl line 20.
Illegal division by zero at ./new_df.pl line 20.
——————————————
It happens also during execution of original script from article above:
——————————————
Illegal division by zero at ./df.pl line 26.
——————————————
both errors are about the same line:
my $df_free = (($avail) / ($avail+$used)) * 100.0;
I have perl-Filesys-DiskSpace installed in my system.
I do not understand what it is complaining about
Any ideas?

Reply

22 DiskTracy February 15, 2010 at 9:03 pm

Dear Peter,

> Although your perl script is nice, you could do it with a standard shell script as well:

for fs in `df -k|awk ‘{print $1}’|sed -n “2,14 p”`; do
x=”`df -kl | grep $fs | awk ‘{ print $5 }’| sed -e ‘s/%//’`”

done

Why do You use pipe snakes, like df -k|awk ‘{print $1}’|sed -n “2,14 p” and df -kl | grep $fs | awk ‘{ print $5 }’| sed -e ‘s/%//’??? If You start awk why do You need a grep and sed? On the other hand if You have n disks You call df (n+1) times instead of once.

Good byte!

Reply

23 chinnu March 1, 2010 at 10:39 am

HI
I am newnie in perl programming..
I am getting this error “An error occured. statvfs failed. Did you run h2ph?”
Could anyone help what is this error mean? and how to solve it?

Thanks

Reply

24 Shan April 1, 2010 at 4:35 am

Hi ,

I am a newbie in perl….can any body tell how to use the same script when i am using windows -XP?

Thanks in advance

Reply

25 Fitri June 23, 2010 at 9:07 am

sorry I’m new in hardware programing.
can I use vb6 / .net programing to monitor disk space and send an email under Linux ?

Reply

26 Satya October 6, 2010 at 2:05 am

Hi All,
I am very new to Unix. Just got a new assignment where I need to write Unix Perl Script.
Can some one segues me which book can help to know Perl script for beginner.
Please help..with link also.

Thanks

Reply

27 Marek February 17, 2011 at 3:24 pm

I got this on CentOS 5.5 64-bit:

./df.pl
Illegal division by zero at ./df.pl line 23.

Reply

28 jawg02 February 24, 2011 at 6:13 pm

Cant get this script to run. Can anyone help?

running on Solaris 10

Makefile.PL and make complete successfully
make test spits out errors

# make test
PERL_DL_NONLAZY=1 /usr/bin/perl “-MExtUtils::Command::MM” “-e” “test_harness(0, ‘blib/lib’, ‘blib/arch’)” t/*.t
t/1st…………ok
t/freebsd-ufs….skipped
all skipped: no reason given
t/linux-ext2…..skipped
all skipped: no reason given
t/linux-vfat…..skipped
all skipped: no reason given
t/solaris-ufs….An error occured. statvfs failed. Did you run h2ph?
FAILED before any test output arrived
Failed Test Stat Wstat Total Fail Failed List of Failed
—————————————————————–
t/solaris-ufs.t ?? ?? % ??
3 tests skipped.
Failed 1/5 test scripts, 80.00% okay. 8/9 subtests failed, 11.11% okay.
*** Error code 29
make: Fatal error: Command failed for target `test_dynamic’

running h2ph hangs after ‘redefine’ message
# h2ph -r -l
require ‘_h2ph_pre.ph’;
no warnings ‘redefine’; // hangs here

I added require ‘_h2ph_pre.ph’; to the h2ph and re-ran with the same result.

What’s up with this?
Solaris 10

Reply

29 jawg02 February 24, 2011 at 8:04 pm

resolved using different arguments:

h2ph * sys/*

Reply

30 Andre November 8, 2011 at 12:47 am

Thanks for the script. I tweaked it so that it would monitor multiple folders. I also added a “–test” command line option to send out a test email. Here it is:

#!/usr/bin/perl
# Available under BSD License. See url for more info:
# http://www.cyberciti.biz/tips/howto-write-perl-script-to-monitor-disk-space.html
# Pass in command line parameter "--test" to perform an email test.
use strict;
use warnings;
use Filesys::DiskSpace;
# ---------------------------
# Configuration section
# ---------------------------
# default warning level
my $default_warning_level=10;
# email setup
my $to='admin@yourdomain.com';
my $from='webmaster@YOURDOMAIN.COM';
my $subject='Low Disk Space';
# folders to check
sub perform_checks {
    &check_free_space("/", 30);
    &check_free_space("/mnt/data");
    &check_free_space("/mnt/storage");
    &check_free_space("/mnt/backup", 20);
}
# ---------------------------
# Main script
# ---------------------------
my $out = "";
# Check free space for folder and add to email message if it is below warning level.
# Parameters:
#   folder_to_check - The path of the filesystem to check.
#   warning_level - If the free disk space percentage is below this level,
#                   an email is sent.  If this parameter is omitted, the
#                   default level will be used.
sub check_free_space {
    my ($dir, $warning_level) = @_;
    # set warning level to default if not specified
    if(!defined($warning_level)) {
        $warning_level = $default_warning_level;
    }
    # get df
    my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;
    # calculate
    my $df_free = ($avail / ($avail + $used)) * 100.0;
    # compare
    if (($df_free < $warning_level) || (defined($ARGV[0]) && ($ARGV[0] eq "--test"))) {
        # append to email
        $out .= sprintf("WARNING Low Disk Space on $dir : %0.2f%% ()\n",$df_free);
    }
}
&perform_checks;
# check if there are warnings to email
if($out ne "") {
    # send email using UNIX/Linux sendmail
    open(MAIL, "|/usr/sbin/sendmail -t");
    ## Mail Header
    print MAIL "To: $to\n";
    print MAIL "From: $from\n";
    print MAIL "Subject: $subject\n";
    ## Mail Body
    print MAIL $out;
}
close(MAIL);

Reply

31 paulcano November 24, 2011 at 1:02 am

I am getting this issue on 64-bit RHEL and CentOS:

Illegal division by zero at ./df.pl line 23.

Line 23 is
my $df_free = (($avail) / ($avail+$used)) * 100.0;

Reply

32 Dave November 15, 2012 at 6:35 pm

Try this works for me:
my ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = split(” “, `df -PT $dir | tail -n +2`);

Reply

33 John June 4, 2012 at 3:34 am

Very much thanks for this nice script. I will use it for my homework.

Reply

34 vamsi August 10, 2012 at 5:57 am

i want to concatenate $_ and $var in to $new in perl ,but it is not concatenating why?
$new = “$_”.”\/$var”;
@arr1= `ls -a $new`;

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="">
What is 6 + 11 ?
Please leave these two fields as-is:
Solve the simple math so we know that you are a human and not a bot.

Tagged as: , , , , , , , , , , , , ,

Previous post:

Next post: