Centos下计算文件的MD5值

浏览次数:2305 关键词 ( 文件  Centos  )

脚本功能

脚本使用Perl编写,计算文件的MD5值

脚本用途

服务器在安装完操作系统后,计算PATH变量里面所有的二进制文件的MD5、计算单个文件MD5值、计算某个目录(包括子目录)下所有的文件的MD5值记录到文件,等日后再生成一份,然后2份文件进行对比,即可知道这些文件是否又被改动过.

脚本用法(6种用法)

  1. 脚本名 -p                   [ > 输出的文件名]  ← 该功能是计算PATH变量里面所有文件的MD5值

  2. 脚本名 -p -f MD5文件         [ > 输出的文件名]  ← 该功能是计算PATH变量里面所有文件的MD5值并跟上一次生成的MD5文件相对比

  3. 脚本名 文件1 文件2 文件3 ...  [ > 输出的文件名]  ← 该功能是计算指定文件的MD5值

  4. 脚本名 目录1 目录2 目录3 ...  [ > 输出的文件名]  ← 该功能是计算指定目录下所有文件的MD5值

  5. 脚本名 -c MD5文件1 MD5文件2  [ > 输出的文件名]   ← 该功能是比较同一个目录下所有文件生成的2次MD5文件中有哪些MD5值不一致

  6. 脚本名 目录 -f MD5文件       [ > 输出的文件名]  ← 该功能是跟上面的功能类似,只是这个不生成文件直接比对

注意事项

不能对/proc目录进行计算
不能对/(根)进行计算,因为/里面包含/proc
不能对挂载在Linux上Windows的共享目录进行计算

脚本内容

【第二版】

  1. #!/usr/bin/perl  

  2. use Digest::MD5;

  3. use File::Find;

  4. # 2012-12-16 15:24 Leo chanyipiaomiao@163.com

  5. # Blog:http://linux5588.blog.51cto.com

  6. #用法提示

  7. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]";

  8. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]";

  9. $usagepath = "Usage: scriptname -p | -p -f MD5File [ > OUTFILE]";

  10. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  

  11. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值

  12. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值

  13. if (@ARGV) {

  14.    my $arg = $ARGV[0];

  15. if (-d $arg ) {

  16. if ($ARGV[1] eq '-f' && -T $ARGV[2]){

  17.            &compareWithLastMD5File($arg);  

  18.        } else {

  19.            &getDirectoryAllFileMD5(@ARGV);

  20.        }

  21.    } elsif ( -f $arg ) {

  22.        &getSingleFileMD5(@ARGV);

  23.    } elsif ($arg eq '-c' && @ARGV == 3 ) {

  24. die"$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]);

  25.        &compareWithTwoMD5Files;

  26.    } elsif ($arg eq '-p') {

  27. if (1 == @ARGV) {

  28.            &getPathBinFileMD5;

  29.        } elsif($ARGV[1] eq '-f' && -T $ARGV[2]) {

  30.            &compareWithLastPathMD5File;

  31.        } else {

  32. die"$usagepath\n";

  33.        }

  34.    } else {

  35. die"$usage\n";

  36.    }

  37. } else {

  38. die"$usage\n";

  39. }

  40. #得到目录下所有文件(包括子目录)的MD5值

  41. sub getDirectoryAllFileMD5 {

  42.    find(\&wantedPrint,@_);

  43. }

  44. #得到PATH变量里面所有的二进制文件的MD5值

  45. sub getPathBinFileMD5 {

  46.    my @path = split /:/,$ENV{PATH};  

  47.    find(\&wantedPrint,@path);

  48. }

  49. #先得到本次PATH变量所有的目录下的文件的MD5值,然后对比以前是生成的MD5文件

  50. sub compareWithLastPathMD5File {

  51.    my @path = split /:/,$ENV{PATH};  

  52.    &compareWithLastMD5File(@path);

  53. }

  54. #得到单个文件的MD5值

  55. sub getSingleFileMD5 {

  56. foreach (@_) {

  57. if (-R $_) {

  58.            print "$_ ",&getMD5($_),"\n";

  59.        } else {

  60.            print "Can't read $_\n";

  61.            next;

  62.        }

  63.    }

  64. }

  65. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比

  66. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来

  67. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime

  68. sub compareWithLastMD5File {

  69.    find(\&wantedHash,@_);      #这里调用那个回调函数后就会生成一个%thisMD5Hash的哈希

  70.    my $md5file = $ARGV[2];

  71.    open LASTMD5FILE,"<","$md5file"ordie"Can't read $md5file : $!\n";

  72.    my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <LASTMD5FILE>);

  73.    %lastMD5Hash = map { split } @lastMD5FilerecordsArray;

  74.    close LASTMD5FILE;

  75. foreach (keys %thisMD5Hash) {

  76. $thisMD5Filerecords++;

  77.    }

  78.    &compare($thisMD5Filerecords,$lastMD5Filerecords);

  79. }

  80. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的

  81. sub compareWithTwoMD5Files {

  82.    my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]);

  83.    open MD5FILE1,"<","$md5file1"ordie"Can't read $md5file1 : $!\n";

  84.    open MD5FILE2,"<","$md5file2"ordie"Can't read $md5file2 : $!\n";

  85.    my $file1record = (@file1record = <MD5FILE1>);

  86.    my $file2record = (@file2record = <MD5FILE2>);

  87.    close MD5FILE1;

  88.    close MD5FILE2;

  89.    %thisMD5Hash = map { split } @file1record;

  90.    %lastMD5Hash = map { split } @file2record;

  91.    &compare($file1record,$file2record);

  92. }

  93. #对2个MD5文件进行比较或者是边生成边比对

  94. sub compare {

  95.    my($file1record,$file2record) = ($_[0],$_[1]);

  96. if ($file1record >= $file2record) {

  97.        %hash1 = %thisMD5Hash;    

  98.        %hash2 = %lastMD5Hash;      

  99.    } else {

  100.        %hash1 = %lastMD5Hash;

  101.        %hash2 = %thisMD5Hash;

  102.    }

  103.    my $count = 0;      

  104. foreach  (keys %hash1) {

  105. if (exists $hash2{$_}) {

  106. if ( $hash1{$_} ne $hash2{$_} ) {

  107. $count++;

  108.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  109.                print "Different --> $_\n";

  110.                print "$hash2{$_}\n";

  111.                print "$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n";

  112.            }

  113.        } else {

  114. $count++;

  115. if (-e $_) {

  116.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  117.                print "Added --> $_ \n$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n";

  118.            } else {

  119.                print "Deleted --> $_ $hash1{$_}\n\n";

  120.            }

  121.        }

  122.    }

  123. if ($count == 0) {

  124.        print "Not Found Different !!\n";

  125.    }

  126. }

  127. #遍历条件,找到之后输出

  128. sub wantedPrint {

  129. if (-f $_ && -R $_) {

  130.        print "$File::Find::name  ",&getMD5($_),"\n";

  131.    }

  132. }

  133. #遍历条件,找到之后形成一个HASH

  134. sub wantedHash {

  135. if (-f $_ && -r $_) {

  136. $thisMD5Hash{$File::Find::name} = &getMD5($_);

  137.    }

  138. }

  139. #计算MD5值

  140. sub getMD5 {

  141.    my $file = shift @_;

  142.    open(FH, $file) ordie"Can't open '$file': $!\n";

  143.    binmode(FH);

  144.    my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest;

  145.    close FH;

  146. return$filemd5;

  147. }

  148. #获取文件的atime,mtime,ctime

  149. sub getFileAMCTime {

  150. $filename = shift @_;

  151.    my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10];

  152. $atime = &getTime($atime);

  153. $mtime = &getTime($mtime);

  154. $ctime = &getTime($ctime);

  155.    #将日期时间格式转换为比较友好的格式

  156.    sub getTime {

  157.        my $time = shift @_;

  158.        my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5];

  159. $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec;

  160. return$time;

  161.    }

  162. return$atime,$mtime,$ctime;

  163. }


【第一版】

  1. #!/usr/bin/perl

  2. use Digest::MD5;

  3. use File::Find;


  4. # 2012-11-24 22:41 Leo chanyipiaomiao@163.com

  5. # Blog:http://linux5588.blog.51cto.com


  6. #用法提示

  7. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]";

  8. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]";

  9. $usagepath = "Usage: scriptname -p [ > OUTFILE]";

  10. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  

  11. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值

  12. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值

  13. if (@ARGV) {

  14.    my $arg = $ARGV[0];

  15.    if (-d $arg ) {

  16.        if ($ARGV[1] eq '-f' && -T $ARGV[2]){

  17.            &compareWithLastMD5File($arg);  

  18.        } else {

  19.            &getDirectoryAllFileMD5(@ARGV);

  20.        }

  21.    } elsif ( -f $arg ) {

  22.        &getSingleFileMD5(@ARGV);

  23.    } elsif ($arg eq '-c' && @ARGV == 3 ) {

  24.        die "$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]);

  25.        &compareWithTwoMD5Files;

  26.    } elsif ($arg eq '-p') {

  27.        die "$usagepath\n" unless (@ARGV == 1);

  28.        &getPathBinFileMD5;

  29.    } else {

  30.        die "$usage\n";

  31.    }

  32. } else {

  33.    die "$usage\n";

  34. }

  35. #得到目录下所有文件(包括子目录)的MD5值

  36. sub getDirectoryAllFileMD5 {

  37.    find(\&wantedPrint,@_);

  38. }

  39. #得到PATH变量里面所有的二进制文件的MD5值

  40. sub getPathBinFileMD5 {

  41.    my @path = split /:/,$ENV{PATH};  

  42.    find(\&wantedPrint,@path);

  43. }

  44. #得到单个文件的MD5值

  45. sub getSingleFileMD5 {

  46.    foreach (@_) {

  47.        if (-R $_) {

  48.            print "$_ ",&getMD5($_),"\n";

  49.        } else {

  50.            print "Can't read $_\n";

  51. next;

  52.        }

  53.    }

  54. }

  55. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比

  56. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来

  57. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime

  58. sub compareWithLastMD5File {

  59.    find(\&wantedHash,@_);

  60.    my $md5file = $ARGV[2];

  61. open MD5FILE,"<","$md5file"or die "Can't read $md5file : $!\n";

  62.    my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <MD5FILE>);

  63.    my %lastMD5Hash = map { split } @lastMD5FilerecordsArray;

  64. close MD5FILE;

  65.    foreach (keys %thisMD5Hash) {

  66.        $thisMD5Filerecords++;

  67.    }

  68.    if ($thisMD5Filerecords >= $lastMD5Filerecords) {

  69.        %hash1 = %thisMD5Hash;

  70.        %hash2 = %lastMD5Hash;

  71.    } else {

  72.        %hash1 = %lastMD5Hash;

  73.        %hash2 = %thisMD5Hash;

  74.    }

  75.    foreach  (keys %hash1) {

  76.        if (exists $hash2{$_}) {

  77.            if ( $hash1{$_} ne $hash2{$_} ) {

  78.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  79.                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  80.            }

  81.        } else {

  82.            if (-e $_) {

  83.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  84.                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  85.            } else {

  86.                print "Deleted:$_ $hash1{$_}\n";

  87.            }

  88.        }

  89.    }

  90. }

  91. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的

  92. sub compareWithTwoMD5Files {

  93.    my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]);

  94. open MD5FILE1,"<","$md5file1"or die "Can't read $md5file1 : $!\n";

  95. open MD5FILE2,"<","$md5file2"or die "Can't read $md5file2 : $!\n";

  96.    my $file1record = (@file1record = <MD5FILE1>);

  97.    my $file2record = (@file2record = <MD5FILE2>);

  98. close MD5FILE1;

  99. close MD5FILE2;

  100.    my %hashmap1 = map { split } @file1record;

  101.    my %hashmap2 = map { split } @file2record;

  102.    if ($file1record >= $file2record) {

  103.        %hash1 = %hashmap1;

  104.        %hash2 = %hashmap2;

  105.    } else {

  106.        %hash1 = %hashmap2;

  107.        %hash2 = %hashmap1;

  108.    }

  109.    foreach  (keys %hash1) {

  110.        if (exists $hash2{$_}) {

  111.            if ( $hash1{$_} ne $hash2{$_} ) {

  112.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  113.                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  114.            }

  115.        } else {

  116.            if (-e $_) {

  117.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  118.                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  119.            } else {

  120.                print "Deleted:$_ $hash1{$_}\n";

  121.            }

  122.        }

  123.    }

  124. }

  125. #遍历条件,找到之后输出

  126. sub wantedPrint {

  127.    if (-f $_ && -R $_) {

  128.        print "$File::Find::name  ",&getMD5($_),"\n";

  129.    }

  130. }

  131. #遍历条件,找到之后形成一个HASH

  132. sub wantedHash {

  133.    if (-f $_ && -r $_) {

  134.        $thisMD5Hash{$File::Find::name} = &getMD5($_);

  135.    }

  136. }

  137. #计算MD5值

  138. sub getMD5 {

  139.    my $file = shift @_;

  140. open(FH, $file) or die "Can't open '$file': $!\n";

  141.    binmode(FH);

  142.    my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest;

  143. close FH;

  144. return $filemd5;

  145. }

  146. #获取文件的atime,mtime,ctime

  147. sub getFileAMCTime {

  148.    $filename = shift @_;

  149.    my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10];

  150.    $atime = &getTime($atime);

  151.    $mtime = &getTime($mtime);

  152.    $ctime = &getTime($ctime);

  153.    #将日期时间格式转换为比较友好的格式

  154.    sub getTime {

  155.        my $time = shift @_;

  156.        my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5];

  157.        $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec;

  158. return $time;

  159.    }

  160. return $atime,$mtime,$ctime;

  161. }


本文出自 “雷纳科斯的博客” 博客,请务必保留此出处http://linux5588.blog.51cto.com/65280/1070915