How Woyano Works Discover Publish Connect Create your channel Give Back Contribute Now

Comparing filesystems,files,environments with perl

Rate this:
By boomroker (Contact - View My Woyano)
Published Wed 23 May 2007, 285 Views, 7 Comments

Here is a nice little script that someone somday could find usefull I know I do in my work as a sys-admin.

What it does is compare 2 "systems" to each other and give you a report on what is different or the same.

Edit it and go wild... but it works fine for me as is...

#!/usr/local/bin/perl
#####################################################################
#
# Name    : envCmp.pl
# Purpose : compare environment and sub directories with checkSum.
# Description:  This script is generates a comparison report for 2 environment
#  that can be used to validate if they are the same or not based on the checkSum (MD5)
#  and the files size, the supported output formate are HTML, Excel, and plain text
# Usage   : see usage below
#
# Author:       boomroker
#
############################################################

BEGIN {
    push (@INC, "$ENV{'CCHOME'}/bin");
    push (@INC,"$ENV{'CCMNGRHOME'}/bin");
}
use Getopt::Long;


&analyzeOptions();

local $cksumCmd = "cksum";
local @CheckSumStrct=();
local %CheckSumHash=();
local $fileCount=0;
local %ck=();
local $logFile = "$ENV{HOST}_$ENV{USER}_".timeStamp();

if ($opt_log){
    $logFile = $opt_log;
}
if ($opt_format eq "excel"){
    $separator = ","; # CSV files
    $logFile = "$logFile.csv";
}elsif($opt_format eq "html"){
    $separator = "</td><td>"; #HTML Table
    $logFile = "$logFile.html"
}else{
    $separator = " "; # defualt space
    $logFile = "$logFile.cksum"
}
    
open(CKSUMLOG,">$logFile")|| die "Cannot write to log file '$logFile' n";
 # read only the files under specific directory
 if($opt_path && !$opt_Recursive){      
      @files = glob("$opt_path/*");
      cksumHash(@files,%CheckSumHash);
      genrateReport(%CheckSumHash);
      
 }elsif($opt_path && $opt_Recursive){
     @dirs=();
     push (@dirs,$opt_path);
    while ($dir = shift(@dirs)) {
        next if ($dir eq '.' || $dir eq '..');
                $status = opendir($dir,$dir);
                unless($status) {
                    die "can't open $dir, $! n";
                }
                @dir_files = readdir($dir);
                closedir($dir);

                foreach $file (@dir_files) {
                    if (-d "$dir/$file") {
                                next if ($file eq '.' || $file eq '..');
                                push(@dirs, "$dir/$file");
                    } else {
                                push(@files,"$dir/$file");
                    }
                }
    }
    cksumHash(@files,%CheckSumHash);
    genrateReport(%CheckSumHash);
    #foreach (keys %CheckSumHash) {print CKSUMLOG $CheckSumHash{$_}->{'CheckSum'} ."$separator" .$CheckSumHash{$_}->{'Name'}. "$separator" .$CheckSumHash{$_}->{'Size'}."n"};
}
if($opt_compare){
    local $sourceFile,$destFile;
    local %sourceHash,%destHash;
    if($opt_source){
       open(SOURCE,"<$opt_source")|| die "Cannot open source file '$opt_$source'n";
       foreach (<SOURCE>){
           next if ($_ =~ /CheckSum */|/$0/|/Environment comparison Tool/);
           if ($opt_format eq "html"){
               $_ =~ s/<[^>]*>/ /gs;
               $_ =~ s/^s+//gs;        
           }elsif($opt_format eq "excel"){
               $_ =~ s/,/ /gs;
           }
           # next if ($file =~ /^s*$/);
        @fileDet = split (/s+/, $_);
        $CheckSumHash{$fileDet[0]}->{'CheckSum'} = $fileDet[0];
               $CheckSumHash{$fileDet[0]}->{'Size'} = $fileDet[1];
               $CheckSumHash{$fileDet[0]}->{'Name'} = join(" " , @fileDet[2..$#fileDet]) ;
          }
          close (SOURCE);
        }
        if($opt_dest){
           open(DEST,"<$opt_dest")|| die "Cannot open destination environment file '$opt_$source'n";
       foreach (<DEST>){
           next if ($_ =~ /CheckSum */|/$0/|/Environment comparison Tool/);
           if ($opt_format eq "html"){
               $_ =~ s/<[^>]*>/ /gs;
               $_ =~ s/^s+//gs; # removing the first blank (what was <td> or <TR>    
           }elsif($opt_format eq "excel"){
               $_ =~ s/,/ /gs;
           }
            #next if ($file =~ /^s*$/);
        @fileDet = split (/s+/, $_);
        ${destHash}{$fileDet[0]}->{'CheckSum'} = $fileDet[0];
               ${destHash}{$fileDet[0]}->{'Size'} = $fileDet[1];
               ${destHash}{$fileDet[0]}->{'Name'} = join(" " , @fileDet[2..$#fileDet]) ;
          }
          close(DEST);
        }
         if (!$opt_source){
            $opt_source = $logFile;
         }
        if ($opt_format eq "html"){
        print CKSUMLOG "<html><body><center><h3> Environment comparison Tool 'comparison report'</h3><h5>Master file 'environment':<font color=blue>User:$ENV{USER},&nbsp Machine:$ENV{HOST},&nbsp logfile:$opt_source</font></h5><h5>Destination Environment:<font color=orange>logFile:$opt_dest</font></h5></center><table border=1><tr

bgColor=#efefdf><td><b><center>CheckSum</center></b>".$separator."<b><center>FileName</center></b>".$separator."<b>
<center>FileSize</center></b></td><td><b><center>SameFileSize</center></b></td><td><b><center>SameHash</center></b>
</td></tr>n";

    }else{
        print CKSUMLOG "CheckSum".$separator."FileName".$separator."FileSize".$separator."SameFileSize".$separator."SameHashn";
    }
      foreach (keys %CheckSumHash) {
          if ($opt_format eq "html"){
             print CKSUMLOG "<tr><td>";
           }
         print CKSUMLOG $CheckSumHash{$_}->{'CheckSum'} ."$separator" .$CheckSumHash{$_}->{'Name'}. "$separator" .$CheckSumHash{$_}->{'Size'};
         
         if ($opt_format eq "html"){
             if($destHash{$_}){
                print CKSUMLOG "<td><font color=green>TRUE</font></td>";
             }else{
               print CKSUMLOG "<td><font color=RED>FALSE</font></td>";
             }
             if($destHash{$_}->{'Size'} eq $CheckSumHash{$_}->{'Size'}){
               print CKSUMLOG "<td><font color=green>TRUE</font></td>";
             }else{
               print CKSUMLOG "<td><font color=RED>FALSE</font></td>";
             }    
             print CKSUMLOG "</tr>n";
         }else{
             if($destHash{$_}){
                print CKSUMLOG $separator."TRUE";
             }else{
               print CKSUMLOG $separator."FALSE";
             }
             if($destHash{$_}->{'Size'} eq $CheckSumHash{$_}->{'Size'}){
               print CKSUMLOG $separator."TRUE";
             }else{
               print CKSUMLOG $separator."FALSE";
             }    
             print CKSUMLOG "n";
         }
      }
      if ($opt_format eq "html"){
             print CKSUMLOG "</table><h5> <center>This is a generated file by $0 </center></h5></body></html>n";
      }
                   
}
    
    
#-----------E N D  O F  M A I N-----------#
#
sub cksumHash{
  local ($arrfiles, $hashRef) = @_;
  local ($fileCont,@fileDet);
   %{$hashRef}=();
   #@{$arrFiles}
      #$fileCount=0;
    foreach $file(@{$arrfiles}){
         next if ($file =~ /^s*$/);
         $file =~ s/ /\ /;
           @fileDet = split (/s+/, `$cksumCmd $file`);
           ${$hashRef}{$fileDet[0]}->{'CheckSum'} = $fileDet[0];
           ${$hashRef}{$fileDet[0]}->{'Size'} = $fileDet[1];
           ${$hashRef}{$fileDet[0]}->{'Name'} = join(" " , @fileDet[2..$#fileDet]) ;
        #$fileCount++;    
      }
  return "";        
}

sub genrateReport{
    local (%CheckSumHash)=@_;
    if ($opt_format eq "html"){
        print CKSUMLOG "<html><body><center><h3> Environment comparison Tool 'File List'</h3></center><table border=1><tr bgColor=#efefdf><td><b><center>CheckSum</center></b>".$separator."<b><center>FileSize</center></b>".$separator."<b>
<center>FileName</center></b><td></tr>n";
    }else{
        print CKSUMLOG "CheckSum".$separator."FileSize".$separator."FileNamen";
    }
      foreach (keys %CheckSumHash) {
          if ($opt_format eq "html"){
             print CKSUMLOG "<tr><td>";
           }
         print CKSUMLOG $CheckSumHash{$_}->{'CheckSum'} ."$separator" .$CheckSumHash{$_}->{'Size'}. "$separator" .$CheckSumHash{$_}->{'Name'};
         if ($opt_format eq "html"){
             print CKSUMLOG "</td></tr>n";
         }else{
             print CKSUMLOG "n";
         }
      }
      if ($opt_format eq "html"){
             print CKSUMLOG "</table><h5> <center>This is a generated file by $0 </center></h5></body></html>n";
      }
}
          
#########################################################
#
#sub analyzeOptions
#########################################################
sub analyzeOptions {
         $st=&GetOptions("help","Recursive","path=s","compare","source=s" ,"dest=s","log=s","format=s");
    &usage() unless ($st);   ## GetOptions returns non-zero upon sucess
    if (defined($opt_help))
    {
        &usage ();
    }
    
    if (defined($opt_path) && defined($opt_source)&& defined($opt_compare)){
        print "Error: your source and destination are the same and you cannot run comparen";
        &usage();
    }
    
    if (defined($opt_compare) && (!defined($opt_dest) && (!defined($opt_path)||!defined($opt_source)))){
        print "Error: you can compare only if you have path to sreach or source file to compare it with your destination filen";
        &usage();
    }
    if (defined($opt_Recursive) && !defined($opt_path)){
        print "Error: your cannot run recursive search with specifying your path firstn";
        &usage();
    }    

}

#########################################################
#
#sub usage
#########################################################
sub usage {
    die "Usage:
        envCmp.pl -help | [-Recursive -compare -format <outputFormat> [-path <directoryToSearch>| -source <fileName>] -dest <fileName> -log <output file>]  
        
        -help      : help (usage).
        -Recursive: recursive searsh including sub directories (defult is the specified directory in the path).
        -compare  : compare source file or current environment with the destination environment.
        -path      : unix path of the directory you want to start from.
        -source   : the file that contains the pre generated data of your master environment.
        -dest     : the file that contains the pre generated data of your destination environment.
        -log:      : output file name (if not specified the tool will generate it automaticaly (host_user_timeStamp.<format>).
        -format      : out put format, html or excel (defult is text with space separator)  
        
        FYI you can use the full name for any of the option above or it's short name (first letter) -compare same as -c
        example:
            to generate checksum file for your environment for all files under /usr/bla using the defult log name and html format.
            envCmp.pl -R -format html -p /usr/bla
            for excel format
            envCmp.pl -R -format excel -p /usr/bla
            
           to generate you output in a file named test123.html
            envCmp.pl -R -format html -p /usr/bla/ -log test123
           to compare to environment files (just compare without running the list generation) the output file will be generated/name automaticaly
            envCmp.pl -compare -format html -d file1.html -s file2.html
           to do the same and direct the autput to a file named final.html do the following
            envCmp.pl -compare -format html -d file1.html -s file2.html -log final
           to do as above while generating the list for the current envirnment (at the same time) use the following
           FYI in this option the output file will contain the file list as well as the compare report.
            envCmp.pl -compare -format html -d file1.html -log final
        n";
}


sub timeStamp
{

        local ($sec , $min , $hour , $mday , $mon , $year , $wday , $yday , $isdst);
        local ($stamp);

        ($sec , $min , $hour , $mday , $mon , $year , $wday , $yday , $isdst) = localtime (time);
        $year = $year + 1900;
        $mon  = $mon  + 1;
        if ($mon == 13)
        {
                $mon  = 1;
                $year = $year + 1;
        }

        $stamp = sprintf("%04d%02d%02d_%02d%02d%02d" , $year , $mon , $mday , $hour , $min , $sec);
        return $stamp;

}


This Item
Category: Knowledge, Snippets, Computers
Tags: perl,programming,
Contributor
boomroker
Share it
Link to this item:
Bookmark this item: RSS Feed

People who liked this item

    7 Comments

  1.  
    JV ~ 17 months ago
    0 votes thumbs up thumbs down
    This looks cool. Do you have an example of its output?
    [ reply ]
    1.  
      boomroker ~ 17 months ago
      0 votes thumbs up thumbs down
      Can I upload a snippet html?
      It is basicly just a table with the header... then

      md5sum size path/file (true or false)

      true if they are the same false if not...
      [ reply ]
    2.  
      boomroker ~ 17 months ago
      0 votes thumbs up thumbs down
      This is the output example for html

      Environment comparison Tool 'comparison report'

      Master file 'environment':User:integ, Machine:, logfile:PERFDATA_gui.html
      Destination Environment:logFile:ETE4DATA_gui.html


      CheckSum
      FileName
      FileSize
      SameFileSize
      SameHash
      1287976031/usr/unibase10/pcftp/RELEASE//win32applications.dll45056TRUETRUE
      This is a generated file by ./envcmp.pl
      [ reply ]
      1.  
        JV ~ 17 months ago
        0 votes thumbs up thumbs down
        Ohhhhhh I see! I thought it was going to output a synopsis of different patches etc. But that's cool.
        [ reply ]
        1.  
          boomroker ~ 17 months ago
          0 votes thumbs up thumbs down
          No just a tool I use to create a website for the different environments so I can make sure they are always in sync with each other and to keep project managers happy ...
          [ reply ]
          1.  
            JV ~ 17 months ago
            0 votes thumbs up thumbs down
            It's very cool. how long have you been a sys-op?
            [ reply ]
            1.  
              boomroker ~ 17 months ago
              0 votes thumbs up thumbs down
              Just under 6 years will be my guess not really sure... Started while I was still studying and then just kept going with it.
              It has its ups and downs. Can be very boring if you do your job right. And if the environment starts to repeat itself
              [ reply ]
        2.  
          22 votes thumbs up thumbs down
          This is my two cents...

             
          Hey you know AdGuy always gets the last word! ;)

        Please Login to Add Your Comment   ..or..  

        Replying to comment by