zl程序教程

您现在的位置是:首页 >  系统

当前栏目

Linux下计算文件的MD5值

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

脚本用法(5种用法)



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

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

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

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

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

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

脚本内容



#!/usr/bin/perl

use Digest::MD5;

use File::Find;

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

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

#用法提示 

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

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

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

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

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

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

 if (@ARGV) { 

    my $arg = $ARGV[0]; 

    if (-d $arg ) { 

        if ($ARGV[1] eq -f   -T $ARGV[2]){ 

             compareWithLastMD5File($arg);  

        } else { 

             getDirectoryAllFileMD5(@ARGV); 

        } 

    } elsif ( -f $arg ) { 

         getSingleFileMD5(@ARGV); 

    } elsif ($arg eq -c   @ARGV == 3 ) { 

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

         compareWithTwoMD5Files; 

    } elsif ($arg eq -p) { 

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

         getPathBinFileMD5; 

    } else { 

        die "$usage\n"; 

    } 

 } else { 

    die "$usage\n"; 

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

 sub getDirectoryAllFileMD5 { 

    find(\ wantedPrint,@_); 

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

 sub getPathBinFileMD5 { 

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

    find(\ wantedPrint,@path); 

 #得到单个文件的MD5值 

 sub getSingleFileMD5 { 

    foreach (@_) { 

        if (-R $_) { 

            print "$_ ", getMD5($_),"\n"; 

        } else { 

            print "Cant read $_\n"; 

            next; 

        } 

    } 

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

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

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

 sub compareWithLastMD5File { 

    find(\ wantedHash,@_); 

    my $md5file = $ARGV[2]; 

    open MD5FILE," ","$md5file" or die "Cant read $md5file : $!\n"; 

    my $lastMD5Filerecords = (@lastMD5FilerecordsArray =  MD5FILE  

    my %lastMD5Hash = map { split } @lastMD5FilerecordsArray; 

    close MD5FILE; 

    foreach (keys %thisMD5Hash) { 

        $thisMD5Filerecords++; 

    } 

    if ($thisMD5Filerecords  = $lastMD5Filerecords) { 

        %hash1 = %thisMD5Hash; 

        %hash2 = %lastMD5Hash; 

    } else { 

        %hash1 = %lastMD5Hash; 

        %hash2 = %thisMD5Hash; 

    } 

    foreach  (keys %hash1) { 

        if (exists $hash2{$_}) { 

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

                ($atime,$mtime,$ctime) =  getFileAMCTime($_); 

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

            } 

        } else { 

            if (-e $_) { 

                ($atime,$mtime,$ctime) =  getFileAMCTime($_); 

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

            } else { 

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

            } 

        } 

    } 

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

 sub compareWithTwoMD5Files { 

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

    open MD5FILE1," ","$md5file1" or die "Cant read $md5file1 : $!\n"; 

    open MD5FILE2," ","$md5file2" or die "Cant read $md5file2 : $!\n"; 

    my $file1record = (@file1record =  MD5FILE1  

    my $file2record = (@file2record =  MD5FILE2  

    close MD5FILE1; 

    close MD5FILE2; 

    my %hashmap1 = map { split } @file1record; 

    my %hashmap2 = map { split } @file2record; 

    if ($file1record  = $file2record) { 

        %hash1 = %hashmap1; 

        %hash2 = %hashmap2; 

    } else { 

        %hash1 = %hashmap2; 

        %hash2 = %hashmap1; 

    } 

    foreach  (keys %hash1) { 

        if (exists $hash2{$_}) { 

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

                ($atime,$mtime,$ctime) =  getFileAMCTime($_); 

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

            } 

        } else { 

            if (-e $_) { 

                ($atime,$mtime,$ctime) =  getFileAMCTime($_); 

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

            } else { 

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

            } 

        } 

    } 

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

 sub wantedPrint { 

    if (-f $_   -R $_) { 

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

    } 

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

 sub wantedHash { 

    if (-f $_   -r $_) { 

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

    } 

#计算MD5值 

 sub getMD5 { 

    my $file = shift @_; 

    open(FH, $file) or die "Cant open $file: $!\n"; 

    binmode(FH); 

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

    close FH; 

    return $filemd5; 

#获取文件的atime,mtime,ctime 

 sub getFileAMCTime { 

    $filename = shift @_; 

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

    $atime =  getTime($atime); 

    $mtime =  getTime($mtime); 

    $ctime =  getTime($ctime); 

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

    sub getTime { 

        my $time = shift @_; 

        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; 

        return $time; 

    } 

    return $atime,$mtime,$ctime; 

 


在Linux 中如何使用 Sipcalc 来计算 IP 子网 Sipcalc 是一个命令行 ip 子网计算器,支持 IPv4 和 IPv6,它会显示你填写 DHCP 信息或设置静态 IP 地址所需的所有 IP 相关信息。Sipcalc 的开发始于 2001 年,它具有我们想要的 ip 计算器的大部分功能。
Linux基础命令---ipcalc计算IP地址 ipcalc        ipcalc提供了一种计算主机IP信息的简单方法。各种选项指定ipcalc应该在标准输出上显示什么信息。可以指定多个选项。必须始终指定要操作的IP地址。大多数操作还需要一个网络掩码或CIDR前缀。