脚本功能

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

脚本用途

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

脚本用法(6种用法)


  1. 脚本名 -p                   [ >
  2. 脚本名 -p -f MD5文件 [ > 输出的文件名] ← 该功能是计算PATH变量里面所有文件的MD5值并跟上一次生成的MD5文件相对比
  3. 脚本名 文件1 文件2 文件3 ...  [ >
  4. 脚本名 目录1 目录2 目录3 ...  [ >
  5. 脚本名 -c MD5文件1 MD5文件2  [ >
  6. 脚本名 目录 -f MD5文件       [ > 输出的文件名]  ← 该功能是跟上面的功能类似,只是这个不生成文件直接比对

注意事项

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

脚本内容

【第二版】

1. #!/usr/bin/perl  
2. use
3. use
4.  
5. # 2012-12-16 15:24 Leo chanyipiaomiao@163.com 
6. # Blog:http://linux5588.blog.51cto.com
7.  
8. #用法提示 
9. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]"; 
10. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]"; 
11. $usagepath = "Usage: scriptname -p | -p -f MD5File [ > OUTFILE]"; 
12.  
13. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  
14. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值 
15. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值 
16. if
17. $arg = $ARGV[0]; 
18. if (-d $arg
19. if ($ARGV[1] eq '-f' && -T $ARGV[2]){ 
20. $arg);  
21. else
22.             &getDirectoryAllFileMD5(@ARGV); 
23.         } 
24. $arg
25.         &getSingleFileMD5(@ARGV); 
26. $arg eq '-c'
27. die "$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]); 
28.         &compareWithTwoMD5Files; 
29. $arg eq '-p') { 
30. if
31.             &getPathBinFileMD5; 
32. $ARGV[1] eq '-f' && -T $ARGV[2]) { 
33.             &compareWithLastPathMD5File; 
34. else
35. die "$usagepath\n"; 
36.         } 
37. else
38. die "$usage\n"; 
39.     } 
40. } else
41. die "$usage\n"; 
42. } 
43.  
44. #得到目录下所有文件(包括子目录)的MD5值 
45. sub getDirectoryAllFileMD5 { 
46.     find(\&wantedPrint,@_); 
47. } 
48.  
49. #得到PATH变量里面所有的二进制文件的MD5值 
50. sub getPathBinFileMD5 { 
51. $ENV{PATH};  
52.     find(\&wantedPrint,@path); 
53. } 
54.  
55. #先得到本次PATH变量所有的目录下的文件的MD5值,然后对比以前是生成的MD5文件 
56. sub compareWithLastPathMD5File { 
57. $ENV{PATH};  
58.     &compareWithLastMD5File(@path); 
59. } 
60.  
61. #得到单个文件的MD5值 
62. sub getSingleFileMD5 { 
63. foreach
64. if (-R $_) { 
65. "$_ ",&getMD5($_),"\n"; 
66. else
67. "Can't read $_\n"; 
68.             next; 
69.         } 
70.     } 
71. } 
72.  
73. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比 
74. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来 
75. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime 
76. sub compareWithLastMD5File { 
77.     find(\&wantedHash,@_);      #这里调用那个回调函数后就会生成一个%thisMD5Hash的哈希 
78. $md5file = $ARGV[2]; 
79.  
80. "<","$md5file" or die "Can't read $md5file : $!\n"; 
81. $lastMD5Filerecords
82.     %lastMD5Hash = map { split } @lastMD5FilerecordsArray; 
83.     close LASTMD5FILE; 
84.  
85. foreach
86. $thisMD5Filerecords++; 
87.     } 
88. $thisMD5Filerecords,$lastMD5Filerecords); 
89. } 
90.  
91. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的 
92. sub compareWithTwoMD5Files { 
93. $md5file1,$md5file2) = ($ARGV[1],$ARGV[2]); 
94. "<","$md5file1" or die "Can't read $md5file1 : $!\n"; 
95. "<","$md5file2" or die "Can't read $md5file2 : $!\n"; 
96. $file1record
97. $file2record
98.     close MD5FILE1; 
99.     close MD5FILE2; 
100.  
101.     %thisMD5Hash = map { split } @file1record; 
102.     %lastMD5Hash = map { split } @file2record; 
103. $file1record,$file2record); 
104. } 
105.  
106. #对2个MD5文件进行比较或者是边生成边比对 
107. sub compare { 
108. $file1record,$file2record) = ($_[0],$_[1]); 
109.  
110. if ($file1record >= $file2record) { 
111.         %hash1 = %thisMD5Hash;     
112.         %hash2 = %lastMD5Hash;      
113. else
114.         %hash1 = %lastMD5Hash; 
115.         %hash2 = %thisMD5Hash; 
116.     } 
117.  
118. $count
119. foreach
120. if (exists $hash2{$_}) { 
121. if ( $hash1{$_} ne $hash2{$_} ) { 
122. $count++; 
123. $atime,$mtime,$ctime) = &getFileAMCTime($_); 
124. "Different --> $_\n"; 
125. "$hash2{$_}\n"; 
126. "$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n"; 
127.             } 
128. else
129. $count++; 
130. if (-e $_) { 
131. $atime,$mtime,$ctime) = &getFileAMCTime($_); 
132. "Added --> $_ \n$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n"; 
133. else
134. "Deleted --> $_ $hash1{$_}\n\n"; 
135.             } 
136.         } 
137.     } 
138. if ($count
139. "Not Found Different !!\n"; 
140.     } 
141. } 
142.  
143. #遍历条件,找到之后输出 
144. sub wantedPrint { 
145. if (-f $_ && -R $_) { 
146. "$File::Find::name  ",&getMD5($_),"\n"; 
147.     } 
148. } 
149.  
150. #遍历条件,找到之后形成一个HASH 
151. sub wantedHash { 
152. if (-f $_ && -r $_) { 
153. $thisMD5Hash{$File::Find::name} = &getMD5($_); 
154.     } 
155. } 
156.  
157. #计算MD5值 
158. sub getMD5 { 
159. $file
160. $file) or die "Can't open '$file': $!\n"; 
161.     binmode(FH); 
162. $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest; 
163.     close FH; 
164. return $filemd5; 
165. } 
166.  
167. #获取文件的atime,mtime,ctime 
168. sub getFileAMCTime { 
169. $filename
170. $atime,$mtime ,$ctime) = (stat ($filename))[8,9,10]; 
171. $atime = &getTime($atime); 
172. $mtime = &getTime($mtime); 
173. $ctime = &getTime($ctime); 
174.  
175.     #将日期时间格式转换为比较友好的格式 
176.     sub getTime { 
177. $time
178. $sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5]; 
179. $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec; 
180. return $time; 
181.     } 
182. return $atime,$mtime,$ctime; 
183. }

 

【第一版】

1. #!/usr/bin/perl
2. use Digest::MD5;
3. use File::Find;
4.  
5. # 2012-11-24 22:41 Leo chanyipiaomiao@163.com
6. # Blog:http://linux5588.blog.51cto.com
7.  
8. #用法提示 
9. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]"; 
10. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]"; 
11. $usagepath = "Usage: scriptname -p [ > OUTFILE]"; 
12.   
13. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  
14. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值 
15. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值 
16.  if (@ARGV) { 
17.     my $arg = $ARGV[0]; 
18.     if (-d $arg ) { 
19. '-f'
20.             &compareWithLastMD5File($arg);  
21. else
22.             &getDirectoryAllFileMD5(@ARGV); 
23.         } 
24.     } elsif ( -f $arg ) { 
25.         &getSingleFileMD5(@ARGV); 
26. '-c'
27. "$usagecompare\n"
28.         &compareWithTwoMD5Files; 
29. '-p') { 
30. "$usagepath\n"
31.         &getPathBinFileMD5; 
32. else
33. "$usage\n"; 
34.     } 
35. else
36. "$usage\n"; 
37.  } 
38.   
39. #得到目录下所有文件(包括子目录)的MD5值 
40.  sub getDirectoryAllFileMD5 { 
41.     find(\&wantedPrint,@_); 
42.  } 
43.   
44. #得到PATH变量里面所有的二进制文件的MD5值 
45.  sub getPathBinFileMD5 { 
46.     my @path = split /:/,$ENV{PATH};  
47.     find(\&wantedPrint,@path); 
48.  } 
49.   
50.  #得到单个文件的MD5值 
51.  sub getSingleFileMD5 { 
52.     foreach (@_) { 
53.         if (-R $_) { 
54. "$_ ",&getMD5($_),"\n"; 
55. else
56. "Can't read $_\n"; 
57. next; 
58.         } 
59.     } 
60.  } 
61.   
62. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比 
63. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来 
64. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime 
65.  sub compareWithLastMD5File { 
66.     find(\&wantedHash,@_); 
67.     my $md5file = $ARGV[2]; 
68.   
69. open MD5FILE,"<","$md5file" or die "Can't read $md5file : $!\n"; 
70.     my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <MD5FILE>); 
71.     my %lastMD5Hash = map { split } @lastMD5FilerecordsArray; 
72. close
73.   
74.     foreach (keys %thisMD5Hash) { 
75.         $thisMD5Filerecords++; 
76.     } 
77.   
78.     if ($thisMD5Filerecords >= $lastMD5Filerecords) { 
79.         %hash1 = %thisMD5Hash; 
80.         %hash2 = %lastMD5Hash; 
81. else
82.         %hash1 = %lastMD5Hash; 
83.         %hash2 = %thisMD5Hash; 
84.     } 
85.   
86.     foreach  (keys %hash1) { 
87.         if (exists $hash2{$_}) { 
88.             if ( $hash1{$_} ne $hash2{$_} ) { 
89.                 ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
90. "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
91.             } 
92. else
93.             if (-e $_) { 
94.                 ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
95. "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
96. else
97. "Deleted:$_ $hash1{$_}\n"; 
98.             } 
99.         } 
100.     } 
101.  } 
102.   
103. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的 
104.  sub compareWithTwoMD5Files { 
105.     my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]); 
106. open MD5FILE1,"<","$md5file1" or die "Can't read $md5file1 : $!\n"; 
107. open MD5FILE2,"<","$md5file2" or die "Can't read $md5file2 : $!\n"; 
108.     my $file1record = (@file1record = <MD5FILE1>); 
109.     my $file2record = (@file2record = <MD5FILE2>); 
110. close
111. close
112.   
113.     my %hashmap1 = map { split } @file1record; 
114.     my %hashmap2 = map { split } @file2record; 
115.   
116.     if ($file1record >= $file2record) { 
117.         %hash1 = %hashmap1; 
118.         %hash2 = %hashmap2; 
119. else
120.         %hash1 = %hashmap2; 
121.         %hash2 = %hashmap1; 
122.     } 
123.   
124.     foreach  (keys %hash1) { 
125.         if (exists $hash2{$_}) { 
126.             if ( $hash1{$_} ne $hash2{$_} ) { 
127.                 ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
128. "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
129.             } 
130. else
131.             if (-e $_) { 
132.                 ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
133. "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
134. else
135. "Deleted:$_ $hash1{$_}\n"; 
136.             } 
137.         } 
138.     } 
139.  } 
140.   
141. #遍历条件,找到之后输出 
142.  sub wantedPrint { 
143.     if (-f $_ && -R $_) { 
144. "$File::Find::name  ",&getMD5($_),"\n"; 
145.     } 
146.  } 
147.   
148. #遍历条件,找到之后形成一个HASH 
149.  sub wantedHash { 
150.     if (-f $_ && -r $_) { 
151. name} = &getMD5($_); 
152.     } 
153.  } 
154.   
155. #计算MD5值 
156.  sub getMD5 { 
157.     my $file = shift @_; 
158. open(FH, $file) or die "Can't open '$file': $!\n"; 
159.     binmode(FH); 
160.     my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest; 
161. close
162. return
163.  } 
164.   
165. #获取文件的atime,mtime,ctime 
166.  sub getFileAMCTime { 
167.     $filename = shift @_; 
168.     my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10]; 
169.     $atime = &getTime($atime); 
170.     $mtime = &getTime($mtime); 
171.     $ctime = &getTime($ctime); 
172.   
173.     #将日期时间格式转换为比较友好的格式 
174.     sub getTime { 
175. time
176. min,$hour,$day,$mon,$year) = (localtime $time)[0..5]; 
177. time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec; 
178. return $time; 
179.     } 
180. return
181.  }

 


转载于:https://blog.51cto.com/linux5588/1070915