歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux下計算文件的MD5值

Linux下計算文件的MD5值

日期:2017/2/28 14:56:12   编辑:Linux教程

腳本功能

腳本使用Perl編寫,計算文件的MD5值

腳本用途

服務器在安裝完操作系統後,計算PATH變量裡面所有的二進制文件的MD5、計算單個文件MD5值、計算某個目錄(包括子目錄)下所有的文件的MD5值記錄到文件,等日後再生成一份,然後2份文件進行對比,即可知道這些文件是否又被改動過.

腳本用法(5種用法)

  1. 腳本名 -p [ > 輸出的文件名] ← 該功能是計算PATH變量裡面所有文件的MD5值
  2. 腳本名 文件1 文件2 文件3 ... [ > 輸出的文件名] ← 該功能是計算指定文件的MD5值
  3. 腳本名 目錄1 目錄2 目錄3 ... [ > 輸出的文件名] ← 該功能是計算指定目錄下所有文件的MD5值
  4. 腳本名 -c MD5文件1 MD5文件2 [ > 輸出的文件名] ← 該功能是比較同一個目錄下所有文件生成的2次MD5文件中有哪些MD5值不一致
  5. 腳本名 目錄 -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 [email protected]
  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. }
Copyright © Linux教程網 All Rights Reserved