#!/usr/bin/perl use Digest::MD5::File qw(file_md5_hex); use strict; use warnings; use DB_File; use Getopt::Std; use Net::XMPP; #Config: my $j_host = "s-teals.info"; my $j_login = "bot"; my $j_pass = "pass"; my $j_adm = 'timofei1394@s-teals.info'; my $command = 'who,ps'; my $logfile = 'mdval.log'; my %opts; #r - рекурсия (bool), n- флаг создания новой базы (bool), i - инпут, хуле (имя новой базы или имя той которую чекаем), #v - подробный вывод при создании базы (bool), o - отпут, имя новой базы стало быть, с - флаг чека базы. a- проверка #на новые файлы (bool) getopts("vncari:o:",\%opts); if($opts{n}){ if($opts{i} and $opts{o}){ gen_db($opts{i},$opts{o},$opts{r},$opts{v}); } } if($opts{c}){ check($opts{i}); } help(); #$exist_f - отсутствующие в директории файлы #$mdfailed_f - файлы с которыми не совпала контрольная сумма #$command_result - вывод комманд заданых в конфиге в переменной $command #$new_f - новые файлы в подконтрольной дире sub check{ logw("Cheking start"); my(%db,$exist_f,$md5failed_f,$new_f,$command_result); dbmopen(%db,"$_[0]", 0777) or logw("Check error: $!\n"); while(my($path,$md5_db) = each %db){ unless(-e $path){ $exist_f .= "$path\n" if("$path" ne 'dir' and "$path" ne 'recursive'); #Исключаем dir и recursive из путей. } else { my $md5_new = get_md($path); unless($md5_new eq $md5_db){ $md5failed_f .= "\n$path\nMD5 Old:$md5_db\nMD5 New:$md5_new\n"; } } } if($opts{a}){ my @ch_file_list = scan_dir($db{dir},$db{recursive}); for(my $i=0;@ch_file_list>$i;$i++){ $ch_file_list[$i] =~ s/\/\//\//g; unless($db{$ch_file_list[$i]}){ $new_f .= $ch_file_list[$i]; } } } dbmclose(%db); if($command){ my @command = split(',',$command); $command_result .= "$command:\n"; for(my $i=0;@command>$i;$i++){ $command_result .= `$command[$i]`."\n"; } } if($md5failed_f or $new_f or $exist_f){ jabber_send($j_adm,"\nFailedMD5:\n$md5failed_f\nNewFile:\n$new_f\nExistFile:\n$exist_f\nCommand_Result:\n$command_result"); } logw("Check finish"); exit(0); } #Осторожно! Рекурсия =) sub scan_dir{ my @list; my $recursive = $_[1]; my $dir = $_[0]; for my $file (glob($dir.'/*')){ unless(-d $file){ push @list, $file; } else { if($recursive){ $file =~ s/ /\\ /g; my @sub = scan_dir($file,$recursive); push @list, @sub; } } } return @list; } sub get_md{ my $digest; $digest = file_md5_hex("$_[0]"); return($digest); } sub gen_db{ logw("Generation DB starting"); my (@file_list,%result); @file_list = scan_dir($_[0],$_[2]); if(-e $_[1]){ print "$_[1] already exist. Overwrite it? \[y\\n\]\n"; while(){ chop $_; if($_ eq ''){print "Bye-bye\n";exit(0);} if($_ eq 'y' or $_ eq 'Y'){unlink("$_[1]") or die "Error: $!";last;} if($_ eq 'n' or $_ eq 'N'){print "Bye-bye\n";exit(0);} } } dbmopen(%result,"$_[1]", 0777); ($result{recursive},$result{dir}) = ($_[2],$_[0]); for(my $i=0;@file_list>$i;$i++){ my $md5= get_md($file_list[$i]); $file_list[$i] =~ s/\/\//\//g; $file_list[$i] =~ s/\n|\r//g; $md5 =~ s/\n|\r//; if($_[3]){ print "File: $file_list[$i]\n MD5:$md5\n"; } $result{$file_list[$i]} = $md5; } dbmclose(%result); logw("Generation DB finish"); exit(0); } sub jabber_send { logw("Sending message to jabber"); my $cnx = new Net::XMPP::Client(debuglevel=>0); $cnx->Connect(hostname => "$j_host", tls => 0); $cnx->AuthSend('hostname' => "$j_host", 'username' => "$j_login", 'password' => "$j_pass", 'resource' => "Oo"); $cnx->MessageSend('to' => "$_[0]", 'type'=>"chat", 'body' => "$_[1]"); $cnx->Disconnect(); } sub logw { my $log_msg = shift; my $now_time = localtime time; open(LOG,">> $logfile"); print LOG "\[$now_time\]: $log_msg\n"; close(LOG); } sub help { print < Keys: -n - Create new database with checksum files Keys that can be used with -n: -r - Recursive walk directory -i - path to directory with checksum files -o - path to saving database with checksums files -v - Advanced output at create database (warning many letters) -c - verifying checksum files by database Keys that can be used with -c: -i - path to database with checksum -a - verifying new files in control directory Example: perl $0 -nr -i /etc -o etc.db - create database with checksum files directiry /etc with recursive walk directory perl $0 -c -i etc.db - verifying checksum files by database etc.db without verifying new files in control directory HELP exit(0); }