?
Solved

Health monitor script for unix filesystems without use of any perl modules

Posted on 2008-01-25
20
Medium Priority
?
2,037 Views
Last Modified: 2011-10-19
Hi, Can some one post me or send me the perl script which can be used to monitor the diskspace of unix filesystems. Please note not to use any of the perl modules.
1. Please note that this perl script should send out a mail in case the unix filesystem diskspace reaches threshold
2. Should be able to provide the statistics such as disk free available, disk free used, Total disk freespace etc.
0
Comment
Question by:gravindra1977
  • 11
  • 6
  • 3
20 Comments
 
LVL 48

Expert Comment

by:Tintin
ID: 20747112
Why Perl?
Why no additional modules?
What Unix flavours will you be monitoring?
0
 

Author Comment

by:gravindra1977
ID: 20747197
Perl because it is the standard in our org and all the other scripts are written in perl.
I donot want use the FileSys::diskspace or Filesys:df. Perhaps if there are any standard modules which comes along with the perl installation, we could use them
Unix flavours that should be supported are HP UX, Solaris
0
 
LVL 48

Expert Comment

by:Tintin
ID: 20747775
I don't really understand why you don't want to use any additional modules, as the Sys::Filesystem module would be perfect for this job. Anyway.....


Are you monitoring just the local filesystems?  Then you could do something along the lines of:



#!/usr/bin/perl
use strict;
my $uname = `uname -s`;
chomp $uname;
 
if ($uname eq 'Linux' or $uname eq 'Solaris') {
  open DF, "df|" or die "Can not run df $!\n";
 
  while (<DF>) {
    next unless /\//;
    my ($dev,$total,$used,$free,$percent,$fs) = split;
    # Do whatever calculation you need based on the figures
  }
}

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 

Author Comment

by:gravindra1977
ID: 20751863
Ok thanks, Can you post me code using any of the modules?
0
 

Author Comment

by:gravindra1977
ID: 20776222
Hi,
Could anyone point me in right direction
I tried to install the Filesys::Diskspace module and I got an error, "An error occured. statvfs failed. Did you run h2ph?" It said skipped t/linuxbsd and validation failed.
I want the following logic to be written . Please provide me with complete code. I am new to perl scripting and just started to learn. Hence request you to please provide me with the complete code.
Help is greatly appreciated.

Argument to be passed will be an environment [ Either DEV,QA or PROD]

Logic:

check the environment passed as an argument
If environment passed is DEV
set unix-file-system to FSDEV
else if environment passed is QA
then unix-file-system to FSQA
else if environment passed is PROD
then unix-file-system is FSPRD
end if

Set threshold to 10%

Get the total space, total used and total unused disk space on the unix-file-system set above.
Calculate the % of unused space.
If it falls below threshold then
 send a mail /exit with non-zero
end if

Loop thru all the filesystems
Check the unused space for all the filesystems which are of uXX  i.e., /u01, /u02, /u03 [ Basically trying to get space of the filesystems where oracle is installed]
Log the unused space of these filesystems in a log file
If any of these falls below threshold,
  send a mail / exit with non-zero
end if

Thanks,
RAVI
0
 
LVL 39

Expert Comment

by:Adam314
ID: 20777986
Here is a version.  It uses parts from Tintin's code:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
 
my $sendmail = '/usr/bin/sendmail';
my $from     = 'me@company.com';
my $to       = 'you@company.com';
 
my %env_to_fs =
  (DEV  => 'FSDEV',
   QA   => 'FSQA',
   PROD => 'FSPRD',
   );
 
#Get argument, set $fs
my $fs_arg = shift;
die "Usage: $0 <Environment>\n" unless $fs_arg;
die "Invalid environment, it must be one of: " . join(", ", keys %env_to_fs) . "\n" unless exists($env_to_fs{$fs_arg});
my $fs = $env_to_fs{$fs_arg};
 
 
 
my $exitcode=0;
 
open DF, "df|" or die "Can not run df $!\n";
<DF>;   #Get header line
 
#Get all other lines
while (<DF>) {
	my ($dev,$total,$used,$free,$percent,$fs) = split /\s+/;
	if($dev =~ m!($fs|/u\d+)!) {
		if($free/$total < .1) {
			$exitcode=1;
			open(SM, "$sendmail -t") or die "Could not open sendmail: $!\n";
			print SM "From: $from\n";
			print SM "To: $to\n";
			print SM "Subject: Device $dev is low on space\n";
			print SM "\n";
			print SM "The device $dev is low on space:\n";
			print SM "  Total: $total\n";
			print SM "  Used : $used\n";
			print SM "  Free : $free\n";
			close(SM);
		}
	}
}
 
close(DF);
 
exit($exitcode);

Open in new window

0
 

Author Comment

by:gravindra1977
ID: 20782569
Thanks , this is fantastic. Do we need to install the perl module Data::Dumper for this and how/where is it been used in the above code?
0
 
LVL 39

Expert Comment

by:Adam314
ID: 20783004
The module is usually installed by default.  However, it isn't used in this script, and that line can be removed.

I left in in from a previous script, and forgot to remove that line.
0
 

Author Comment

by:gravindra1977
ID: 20783375
Wonderful !! This is exactly what I require. Can we also write all the info into a report file which would be in specific directory. Bascially this report should contain the all the data that we are capturing like diskspace total, allocated, free etc for FSPRD and other /uXX filesystems. At the end of program it should close this report file. Also can we put an log file which can capture all the errors that may be obtained during the run of the program. Again thanks very much for your input.
0
 

Author Comment

by:gravindra1977
ID: 20783436
Another thing is I am getting the following output if I print total, used and free
The filesystem is :  /u01
  Total: (/dev/vx/dsk/oradg/u01):21596644
  Used : blocks
  Free : 3254247
and hence it is coming as
Argument "(/dev/vx/dsk/oradg/u01):21596644" isn't numeric in division.
Illegal division by zero at df.pl line 33, <DF> line 10.

I put the following lines after
"if($dev =~ m!($fs|/u\d+)!) {"

print "The filesystem is :  $dev\n";
                print "  Total: $total\n";
                print "  Used : $used\n";
                print "  Free : $free\n";

and the output I am getting is as below:

The filesystem is :  /u01
  Total: (/dev/vx/dsk/oradg/u01):21596644
  Used : blocks
  Free : 3254247

Please advice. Probably split is not done properly, I guess. Please advice.

Thanks a lot again
0
 
LVL 39

Expert Comment

by:Adam314
ID: 20787371
What is the output from df?
(go to a terminal/prompt, type df, press return)
0
 

Author Comment

by:gravindra1977
ID: 20791099
Output from df is as follows: Also attached the file for the same.

/                  (/dev/vx/dsk/bootdg/rootvol): 3533744 blocks   417512 files
/proc              (/proc             ):       0 blocks    29421 files
/etc/mnttab        (mnttab            ):       0 blocks        0 files
/dev/fd            (fd                ):       0 blocks        0 files
/var               (/dev/vx/dsk/bootdg/var): 3843060 blocks   489235 files
/var/run           (swap              ):39591600 blocks  3219307 files
/dev/vx/dmp        (dmpfs             ):39591600 blocks  3219307 files
/dev/vx/rdmp       (dmpfs             ):39591600 blocks  3219307 files
/tmp               (swap              ):  960928 blocks  3219307 files
/redo002           (/dev/vx/dsk/orardodg02/redo002):104745016 blocks  7188431 fs
/u01               (/dev/vx/dsk/oradg/u01):21100702 blocks  3254641 files
/stage             (/dev/vx/dsk/oradg/stage):24403074 blocks  1793502 files
/redo001           (/dev/vx/dsk/orardodg01/redo001):104510852 blocks  7188416 fs
/u008              (/dev/vx/dsk/oradatdg02/u008):177416744 blocks 14376930 files
/arch001           (/dev/vx/dsk/oraarcdg01/arch001):224134440 blocks 28746140 fs
/uhcdba            (/dev/vx/dsk/oradg/uhcdba):57641054 blocks  7181513 files
/u006              (/dev/vx/dsk/oradatdg01/u006):168425668 blocks 14376890 files
/u007              (/dev/vx/dsk/oradatdg02/u007):16914724 blocks 14376720 files
/u003              (/dev/vx/dsk/oradatdg01/u003):91315850 blocks 14376878 files
/u005              (/dev/vx/dsk/oradatdg01/u005):182653128 blocks 14376909 files
/u004              (/dev/vx/dsk/oradatdg01/u004):115505694 blocks 14376872 files
/u009              (/dev/vx/dsk/oradatdg03/u009):53605372 blocks 14376936 files
/u010              (/dev/vx/dsk/oradatdg03/u010):87544968 blocks 14376923 files
/OAPDEV            (nasgw010pn:/vol/eagan15/oapdev):53315504 blocks 31712083 fis
/u011              (/dev/vx/dsk/orau011dg/u011):40284380 blocks 14376919 files
/u012              (/dev/vx/dsk/orau012dg/u012):12841628 blocks 14376924 files
/u013              (/dev/vx/dsk/orau013dg/u013):189903986 blocks 14376917 files
/u014              (/dev/vx/dsk/orau014dg/u014):202216442 blocks 14376934 files
/u015              (/dev/vx/dsk/orau015dg/u015):202640584 blocks 14376934 files
/INTERFACES_SIMS/SIMSDEV(nasgw010pn:/vol/eagan17/simsdev): 2097152 blocks 31320s
/uhtrels           (/dev/vx/dsk/rootdg/uhtrels): 4306766 blocks   362072 files
/prdctl            (/dev/vx/dsk/rootdg/prdctl): 1151956 blocks   291716 files
/home              (/dev/vx/dsk/bootdg/home): 1231912 blocks   517025 files

dbss8075-df.txt
0
 
LVL 39

Expert Comment

by:Adam314
ID: 20791641
I'm not familiar with that format for the output of df.  It looks like it is giving only the total size and total number of files.

Are you familiar with the df command?  Do you know of an option on your system to have it print any 2 of: total, used, free?

If not, post the man page from df.
(at a prompt:   man df > man_df.txt, then post the man_df.txt here)
0
 

Author Comment

by:gravindra1977
ID: 20791770
Please find file attached of man_df.txt
man-df.txt
0
 
LVL 39

Expert Comment

by:Adam314
ID: 20791908
It looks like you need:    df -k

In the script, on line 26, replace "df|" with "df -k|".

If that doesn't work, post the output from   df -k  at a prompt.
0
 

Author Comment

by:gravindra1977
ID: 20793558
It did not work. The ouput shown is as below

The filesystem is :  /dev/vx/dsk/bootdg/rootvol
  Total: 4138926
  Used : 2372054
  Free : 1725483
The filesystem is :  /proc
  Total: 0
  Used : 0
  Free : 0
Illegal division by zero at df.pl line 33, <DF> line 3.

/proc should not have gone thru if condition. I am not sure how it did pass through. Also I am attaching output of df -k from the prompt.
df-k.txt
0
 

Author Comment

by:gravindra1977
ID: 20794120
I tried to print all the filesystem, total, used, avail, capacity, mounted on using df -k and after the split correct values are coming in. Please see the attached output file. But even for the filesystem /proc and / , the if statement seems statisify and hence resulting in the error. Probably the if condition is incorrect. Can you please check that and let me know . Many thanks for your help.

I have added the code snippet as well. Please verify.
#!/usr/bin/perl
use strict;
use warnings;
 
my %env_to_fs =
  (DEV  => 'OAPDEV',
   QA   => 'OAPQA',
   PROD => 'OAPPRD',
   );
 
#Get argument, set $fs
my $env_arg = shift;
die "Usage: $0 <Environment>\n" unless $env_arg;
die "Invalid environment, it must be one of: " . join(", ", keys %env_to_fs) . "\n" unless exists($env_to_fs{$env_arg});
my $fs = $env_to_fs{$env_arg};
 
 
 
my $exitcode=0;
 
open DF, "df -k|" or die "Can not run df $!\n";
<DF>;   #Get header line
 
#Get all other lines
while (<DF>) {
	print;
	my ($dev,$total,$used,$free,$percent,$fs) = split /\s+/;
	print "DEV: $dev\n";
         print "TOTAL: $total\n";
	print "Used : $used\n";
	print "free : $free\n";
	print "percent: $percent\n";
	print "fs: $fs\n";
 
	#if($dev =~ m!($fs|/u\d+)!) {
	#	print "The filesystem is :  $dev\n";
	#	print "  Total: $total\n";
	#	print "  Used : $used\n";
	#	print "  Free : $free\n";
 
	#	if($free/$total < .1) 
	#	{
	#		$exitcode=1;
	#	}
	#}
}
close(DF);
exit($exitcode);

Open in new window

df-output.txt
0
 
LVL 39

Accepted Solution

by:
Adam314 earned 2000 total points
ID: 20798501
The problem is $fs is used twice, line 15 and line 27.  One of these needs to have a different name.
    Change the $fs in line 15 to $fs_arg
    Change the $fs in line 35 to $fs_arg
0
 

Author Closing Comment

by:gravindra1977
ID: 31425162
Excellent. This is exactly what I wanted and Adam provided me. Thanks again Adam.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
What do responsible coders do? They don't take detrimental shortcuts. They do take reasonable security precautions, create important automation, implement sufficient logging, fix things they break, and care about users.
Introduction to Processes
Starting up a Project

601 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question