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
- Email this to a friend
- Printable version
- Rss Feed
- Last Updated: May/5/2008

{ 1 trackback }
{ 19 comments… read them below or add one }
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.
Thomas,
Opps stupid xhtml was causing problem. Post has been updated
Appreciate your post.
No prb. Nothing beats a good script ;ø)
You could also you Monit [1] to monitor disk space and several other services/daemons.
[1] http://www.tildeslash.com/monit/
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.
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@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.
hi, can you please help me to write a perl script to read emails?
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
I get this error
“Cannot use df on this machine (untested or unsupported). ”
everything installed (moudles etc..)
can some one help me?
thank you!
I get “statfs failed on /home (new filesystem type?) .. ” error. Any idea?
Thanks!
I am getting an error “An error occured. statvfs failed. Did you run h2ph?” Any idea?
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?
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");
}
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.
For RPM based Linux systems like CentOS and Fedora, install the perl-Filesys-DiskSpace package with:
# yum install perl-Filesys-DiskSpace
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!
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); }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?