Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Unix disk space reports

by halxd2 (Monk)
on Dec 15, 2000 at 02:15 UTC ( #46730=CUFP: print w/ replies, xml ) Need Help??

My supervisor needed to know how much space was on each of our servers. I knew what I needed was the df-k from each server, but that can be a lot of stuff. Welcome to Perl. So here's the quicky df-k grinder
#!/usr/local/bin/perl # # This is a unix disk space report generator. It takes df -k's and sp +its out # one report that gives each host's name, the total drive space, t +otal free # space available, and the percentage of free space on the system. + This is # total space, not separated by drive. Swap space not counted, nor + are NFS # mounted file systems. It supports Solaris and Linux, but not AIX +. To use # each host must have a separate file named for the host (df -k > +HOSTNAME) # as that is the way it will be called from the command line. I ca +n login # NIS and just create some of the files. I can log in as root on s +ome # non-NIS machines and use mail (dk -k > HOSTNAME; cat HOSTNAME | +mail hck) # have several systems that do not have mail access, but I can sft +p. I put # all the files in one directory and call the script ./disk.pl hos +ts/* # Calling the hosts by name from the command line also allows me t +o get a # report of just one host, or a selection of hosts. # #A typical df -k looks like this: ############################################################# #Filesystem 1k-blocks Used Available Use% Mounted on #/dev/dsk/c0t0d0s0 8061757 6306497 1674643 79% / #/dev/dsk/c0t0d0s1 380815 121164 221570 35% /var #swap 534400 216 534184 0% /tmp #nfs.home.edu:/mounts/pluto4/vol4/u04 # 43505106 39604270 3465785 92% /u04 #nfs.home.edu:/export/sun4/SunOS5.7/usr/x11 # 69607865 54714403 14197384 79% /usr/x11 #nfs.home.edu:/export/sun4/SunOS5.7/usr/misc # 69607865 54714403 14197384 79% /usr/misc #nfs.home.edu:/mounts/pluto4/vol4/u04/hck # 43505106 39604270 3465785 92% /home/hck #/vol/dev/dsk/c0t2d0/sol_8_sparc_2 # 115408 115408 0 100% /cdrom/sol_8_ +sparc_2 #mail.home.edu:/var/mail # 51998176 34547199 16930996 67% /var/mail #nfs.home.edu:/export/sun4/SunOS5.7/usr/perl-5.6 # 41562853 38366501 2780724 93% /usr/perl-5.6 #nfs.home.edu:/export/sun4/SunOS5.7/usr/gnu # 69607865 54714403 14197384 79% /usr/gnu ############################################################# #So we know some things about it fast. The only lines of interest are +the ones # that start with "/" CDROM drives stick out, but could be edited out + if # needed. NFS drives match the != /\// so they're gone. Headers from +mail get # wild, but they match != /\// also. Blank lines are the same. The fi +elds we # care about are the second and fourth. So we grab them and dump the +rest! # use strict; use diagnostics; my $host; my $line; #make a tmp file to read from open WRITEIT, ">report"; #All relevant hosts have been put on the command line (maybe hosts/*) #This will generate our data file. I like to see the raw data sometime +s. while($host = pop @ARGV) { chomp $host; open (READIT, "<$host") || die "\n can\'t open the host file: $!\n" +; print WRITEIT "start of $host\n"; while($line = <READIT>) { if($line !~ /^\/.*/){next;} if($line =~ /^\/proc.*/){next;}#Proc is not of interest $line =~ s/^([^ ]*) *([^ ]*) *[^ ]* *([^ ]*) *[^ ]* (.*)/$2 $3/; print WRITEIT "$line"; } print WRITEIT "end of $host\n"; close READIT; } close WRITEIT; #Now read the data and spit out a report. open READIT, "<report"; open WRITEIT, ">space"; my @numbers = qw(0 0); #numbers from the data file line my @space = qw(0 0); #space derived from numbers while($line = <READIT>) { chomp $line; #If this is the beginning of a host report, get the host name # and make the first entry. Then clear the space variables. if($line =~ /^start of.*/) { $line =~ s/start of (.*)/$1/; $host = $line; $host =~ s/hosts\/(.*)/$1/; print WRITEIT "Space report for $host\n"; @numbers = qw(0 0); @space = qw(0 0); next; } #if this is disk line grab the numbers and add them to the totals if($line =~ /^[0-9].*/) { @numbers = split " ", $line; $space[0] = $space[0] + $numbers[0]; $space[1] = $space[1] + $numbers[1]; next; } #if this the end of a host report, write the totals with a percenta +ge if($line =~ /^end of.*/) { my $percentage = $space[1] / $space[0]; #OK so this is a cheap way to format a number, but I didn't want + to # change print statements for one line. $percentage =~ s/..(..).*/$1%/; print WRITEIT "Total space on $host = $space[0]\n"; print WRITEIT "Total space available $host = $space[1]\n"; print WRITEIT "Percentage of free space is $percentage\n"; print WRITEIT "\n\n"; } }

Comment on Unix disk space reports
Download Code
Re: Unix disk space reports
by mr_leisure (Beadle) on Dec 21, 2000 at 18:42 UTC
    And if you are looking for a graphical representation of df -k running on your specified directory and looping on your specified timescale, using Perl::TK, check my little program out... Cheers ML
    ------------------------------------------------------------ DISKCHECK.pl ---------------------------- #!/usr/bin/perl # # Simple Diskcheck GUI, running my ds.pl diskcheck script. This GUI d +isplays the results of a diskcheck loop. # # Usage : diskcheck.pl # # # You will need to be running ds.pl -dir=DIRECTORY -time=LOOPTIME at t +he same time as running the GUI. # # # use Tk; use Net::Telnet(); # open filehandle to log file, in this case, ds.txt open (LOG, "tail -f ds.txt|") || "Could not open logfile!\n"; # create main GUI window my $mw = MainWindow->new(); $mw->Label(-text => "DiskCheck Utility for PerlMonk.org Folks")->pack +; # label that window my $menubar = $mw->Frame(-relief => "ridge", -borderwidth => 2)->pack (-anchor => "nw", -fill => "x"); # cr +eate menubar and its properties my $filemenu = $menubar->Menubutton(-text =>"File", -underline => 1)->pack (-side => "left"); # add first menu but +ton : File $filemenu->separator(); # add line separator on menu $filemenu->command(-label => "Save Current Log to DSlog.txt" -command => \&save_yn); # add button : Save log to file $filemenu->separator(); # add line separator on menu $filemenu->command(-label =>"Quit", -command => \&really_quit); # add button : Quit my $optmenu = $menubar->Menubutton(-text => "Options", -underline =>1)->pack (-side => "left"); # add new menu button + : Options $optmenu->separator(); # add line separator on menu $optmenu->command(-label => "Clear Logs", -command => \&clear_log); # add button : Clear Logs $optmenu->separator(); # add line separator my $helpmenu = $menubar->Menubutton(-text => "Help", -underline => 1)->pack (-side => "left"); # add Help menu $helpmenu->separator(); # add line separator to menu $helpmenu->command(-label => "About DiskCheck", -underline =>1, -command => \&help_about); # add about button +pointing to help_about subroutine my $text = $mw->Listbox(-relief => "sunken", -width => 50, -height => +30, -background => "white"); # add main data box my $scroll = $mw->Scrollbar(-command => ["yview", $text]); # add r +ight scrollbar $text->configure(-yscrollcommand => ["set", $scroll]); $text->pack(-side => "left", -fill => "both", -expand => "yes"); $scroll->pack(-side => "right", -fill => "y"); $mw->fileevent(LOG, 'readable', [\&insert_text]); MainLoop; sub insert_text { my $curline; if ($curline = <LOG>) { $text->insert('end', $curline); $text->yview('moveto', 100); } else { $mw->fileevent(LOG, 'readable', ""); } } sub clear_log { $text->delete(0, 'end'); } sub save_log { my @current_log = $text->get(0, 'end'); open (LOG2, ">>DSlog.txt"); print LOG2 @current_log; close (LOG2); exit; } sub save_yn { if (! Exists($sftl)) { my $sftl = $filemenu->Toplevel(); $sftl->title("Alert!"); $sftl->Label(-text => "Save to DSlog.txt? \nWARNING : Destinat +ion file will be overwritten!")->pack; $sftl->Button(-text => "Yes", -command => \&save_log, -command => sub {$sftl->withdraw}) +->pack(-expand => "yes", -side=>"left"); $sftl->Button(-text => "No", -command => sub { $sftl->withdraw })->pack(-expand => "yes +", -side => "right"); } else { $sftl->deiconify(); $sftl->raise(); } } sub not_complete { if (! Exists($omtl)) { my $omtl = $optmenu->Toplevel(); $omtl->title("Alert!"); $omtl->Label(-text =>"This Section Not Complete!")->pack; $omtl->Button(-text => "Ok", -command => sub { $omtl->withdraw })->pack(-expand => "yes +"); } else { $omtl->deiconify(); $omtl->raise(); } } sub help_about { if (! Exists($hmtl)) { my $hmtl = $helpmenu->Toplevel(); $hmtl->title("About DiskCheck"); $hmtl->Label(-justify => center, -text => "Originally written for UBS warburg, by Mr Leisure <mr_le +isure@hotmail.com>" )->pack; $hmtl->Button(-text => "Ok", -command => sub { $hmtl->withdraw } )->pack(-expand => "yes"); } else { $hmtl->deiconify(); $hmtl->raise(); } } sub really_quit { if (! Exists($qbtl)) { my $qbtl = $filemenu->Toplevel(-height=> 20, -width=> 45); $qbtl->title("Alert!"); $qbtl->Label(-text => "Do You Really Want To Quit?")->pack; $qbtl->Button(-text => "Yes", -command => sub {exit})->pack(-side => "left", -expand => "yes +"); $qbtl->Button(-text => "No", -command => sub {$qbtl->withdraw} )->pack(-expand => "yes", -s +ide => "right"); } else { $qbtl->deiconify(); $qbtl->raise(); } } ----------------------------------------- DS.PL ------------------------ #!/usr/bin/perl ###################################################################### +######## # # ds.pl - check diskspace utility on specified directory # # # # usage : ds.pl -dir=/YOURDIR -time=5 # # - will run utility on /YOURDIR directory, looping every 5 + seconds # # # ###################################################################### +######## # use strict; # use English; # use Cwd; # use efSetupEnv; use Getopt::Long; my %opt = (); GetOptions(\%opt, "dir=s", # name of directory to be checked "time=i", # sleep period before restart ); die "Must specify directory!" unless $opt{dir}; die "Must specify interval in seconds!" unless $opt{time}; until (! $opt{time}) { { check_disk_space($opt{dir} ) ; sleep($opt{time}) } sub check_disk_space { my $dfout = `df -k $opt{dir}` || die "Cannot check space on $o +pt{dir}!\n"; $dfout =~ s/ +/ /g; my @space = split (/ / , $dfout); my $block = $space[9]; if ($block < 50000) { # set this to whatever you want open(OUTPUT,">>ds.txt"); print OUTPUT "Error : Only $space[9] blocks free on $opt{dir} +!\n"; close(OUTPUT); } elsif ( $block < 6000000000 ) { #this too open(OUTPUT,">>ds.txt"); print OUTPUT "$space[9] blocks free on $opt{dir}\n"; close (OUTPUT); } else { } } }
      Is there a CGI version of this script? I have written a CGI script for process monitoring on several servers.. and this would come in handy! A quick question.. I have used remsh instead of Net::Telnet module to access the remote servers, and I am aware of its security pitfalls as it uses .rhosts. What do you think?
Re: Unix disk space reports
by salvadors (Pilgrim) on Dec 31, 2000 at 02:56 UTC
    This seems much too complicated for my liking.

    I really don't like the way it needs to create a temporary file, and that it writes it output out to a fixed file, rather than STDOUT, thus letting me redirect it, or play with it in some other way. I'd go for something more along the lines of:

    use strict; my %space; while (<>) { next unless m#^/#; next if m#^/proc#; next unless m#^[^ ]* *([^ ]*) *[^ ]* *([^ ]*) *[^ ]*#; $space{$ARGV}{total} += $1; $space{$ARGV}{free} += $2; } foreach my $host (sort keys %space) { printf "%s: %dk free, out of %dk, (%.2f%%)\n", $host, $space{$host}{free}, $space{$host}{total}, $space{$host}{free} / $space{$host}{total} * 100; }
    Then I'd call it as: perl ~/dfk hosts/* > report

    Playing with the format of the output is then trivial.

    If you really want to be able to view the intermediate 'space' file, then you could add a command line parameter for it (including the name of the output file?).

    Tony

      Well thanks for the arrogant reply there Tony. I guess the fact that this was my FIRST application of what I have learnt in Perl over the last month was lost on you big guy...
      if ($mr_leisure) { bow; }

        You're welcome.

        Although if you'd actually said "this is my first Perl script", or "please let me know what you think of this - I'm not really sure whether it's good or not", I might have replied differently than if you'd just offered it up as code for everyone, without any comments.

        I guess I'll note you down in my list of people who would rather everyone told them how great they were than offered constructive criticism?

        Tony

      I agree my script does limit general usage; however, I was working to get a report that had the format I wanted for my boss. As for keeping the temp files I usualy keep them until I'm very sure I'm getting everything I what out of the script. I guess I just live in debugland.
        I want the same kind of report which has the capablity of showing the diskpace status for the past month. Can some help?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://46730]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (12)
As of 2014-09-17 14:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (81 votes), past polls