Linux下计算文件的MD5值

字体大小: 中小 标准 ->行高大小: 标准

脚本功能

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

脚本用途

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

脚本用法(5种用法)

  1. 脚本名 -p [ > 输出的文件名] ← 该功能是计算PATH变量里面所有文件的MD5值 脚本名 文件1 文件2 文件3 ... [ > 输出的文件名] ← 该功能是计算指定文件的MD5值
  2. 脚本名 目录1 目录2 目录3 ... [ > 输出的文件名] ← 该功能是计算指定目录下所有文件的MD5值 脚本名 -c MD5文件1 MD5文件2 [ > 输出的文件名] ← 该功能是比较同一个目录下所有文件生成的2次MD5文件中有哪些MD5值不一致
  3. 脚本名 目录 -f MD5文件 [ > 输出的文件名] ← 该功能是跟上面的功能类似,只是这个不生成文件直接比对

注意事项

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

脚本内容

  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. #用法提示 $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]";
  7. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]"; $usagepath = "Usage: scriptname -p [ > OUTFILE]";
  8. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空
  9. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值 #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值
  10. if (@ARGV) { my $arg = $ARGV[0];
  11. if (-d $arg ) { if ($ARGV[1] eq '-f' && -T $ARGV[2]){
  12. &compareWithLastMD5File($arg); } else {
  13. &getDirectoryAllFileMD5(@ARGV); }
  14. } elsif ( -f $arg ) { &getSingleFileMD5(@ARGV);
  15. } elsif ($arg eq '-c' && @ARGV == 3 ) { die "$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]);
  16. &compareWithTwoMD5Files; } elsif ($arg eq '-p') {
  17. die "$usagepath\n" unless (@ARGV == 1); &getPathBinFileMD5;
  18. } else { die "$usage\n";
  19. } } else {
  20. die "$usage\n"; }
  21. #得到目录下所有文件(包括子目录)的MD5值
  22. sub getDirectoryAllFileMD5 { find(\&wantedPrint,@_);
  23. }
  24. #得到PATH变量里面所有的二进制文件的MD5值 sub getPathBinFileMD5 {
  25. my @path = split /:/,$ENV{PATH}; find(\&wantedPrint,@path);
  26. }
  27. #得到单个文件的MD5值 sub getSingleFileMD5 {
  28. foreach (@_) { if (-R $_) {
  29. print "$_ ",&getMD5($_),"\n"; } else {
  30. print "Can't read $_\n"; next;
  31. } }
  32. }
  33. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比 #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来
  34. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime sub compareWithLastMD5File {
  35. find(\&wantedHash,@_); my $md5file = $ARGV[2];
  36. open MD5FILE,"<","$md5file"or die "Can't read $md5file : $!\n";
  37. my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <MD5FILE>); my %lastMD5Hash = map { split } @lastMD5FilerecordsArray;
  38. close MD5FILE;
  39. foreach (keys %thisMD5Hash) { $thisMD5Filerecords++;
  40. }
  41. if ($thisMD5Filerecords >= $lastMD5Filerecords) { %hash1 = %thisMD5Hash;
  42. %hash2 = %lastMD5Hash; } else {
  43. %hash1 = %lastMD5Hash; %hash2 = %thisMD5Hash;
  44. }
  45. foreach (keys %hash1) { if (exists $hash2{$_}) {
  46. if ( $hash1{$_} ne $hash2{$_} ) { ($atime,$mtime,$ctime) = &getFileAMCTime($_);
  47. print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; }
  48. } else { if (-e $_) {
  49. ($atime,$mtime,$ctime) = &getFileAMCTime($_); print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";
  50. } else { print "Deleted:$_ $hash1{$_}\n";
  51. } }
  52. } }
  53. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的
  54. sub compareWithTwoMD5Files { my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]);
  55. open MD5FILE1,"<","$md5file1"or die "Can't read $md5file1 : $!\n"; open MD5FILE2,"<","$md5file2"or die "Can't read $md5file2 : $!\n";
  56. my $file1record = (@file1record = <MD5FILE1>); my $file2record = (@file2record = <MD5FILE2>);
  57. close MD5FILE1; close MD5FILE2;
  58. my %hashmap1 = map { split } @file1record;
  59. my %hashmap2 = map { split } @file2record;
  60. if ($file1record >= $file2record) { %hash1 = %hashmap1;
  61. %hash2 = %hashmap2; } else {
  62. %hash1 = %hashmap2; %hash2 = %hashmap1;
  63. }
  64. foreach (keys %hash1) { if (exists $hash2{$_}) {
  65. if ( $hash1{$_} ne $hash2{$_} ) { ($atime,$mtime,$ctime) = &getFileAMCTime($_);
  66. print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; }
  67. } else { if (-e $_) {
  68. ($atime,$mtime,$ctime) = &getFileAMCTime($_); print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";
  69. } else { print "Deleted:$_ $hash1{$_}\n";
  70. } }
  71. } }
  72. #遍历条件,找到之后输出
  73. sub wantedPrint { if (-f $_ && -R $_) {
  74. print "$File::Find::name ",&getMD5($_),"\n"; }
  75. }
  76. #遍历条件,找到之后形成一个HASH sub wantedHash {
  77. if (-f $_ && -r $_) { $thisMD5Hash{$File::Find::name} = &getMD5($_);
  78. } }
  79. #计算MD5值
  80. sub getMD5 { my $file = shift @_;
  81. open(FH, $file) or die "Can't open '$file': $!\n"; binmode(FH);
  82. my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest; close FH;
  83. return $filemd5; }
  84. #获取文件的atime,mtime,ctime
  85. sub getFileAMCTime { $filename = shift @_;
  86. my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10]; $atime = &getTime($atime);
  87. $mtime = &getTime($mtime); $ctime = &getTime($ctime);
  88. #将日期时间格式转换为比较友好的格式
  89. sub getTime { my $time = shift @_;
  90. my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5]; $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec;
  91. return $time; }
  92. return $atime,$mtime,$ctime; }

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/64781.html