#!/usr/bin/perl # Author: gilbertas matusevicius # Kolmisoft, 2015 use strict; use warnings; use File::Basename; use File::Path qw(remove_tree); use File::Spec::Functions; #use File::stat; use Data::Dumper; my $root_folder = "/var/log/m2/pcap"; my $config_file = "/etc/m2/system.conf"; my $DEFAULT_PCAP_HDD_RESERVED_SPACE=1000; sub get_config { my $config_string = shift; my $value = 0; my $search_string = quotemeta "$config_string"; open(my $fh, "<", $config_file) or die "cannot open $config_file: $!"; while (my $row = <$fh>) { chomp $row; if ($row =~ m/$search_string\s*\=\s*(\d+)/g) { $value=$1; last; } } return $value; } sub get_dir_size { my $dir = shift; open my $dh, "du -sh -BM $dir |" || die "can't fork: $!"; my $dh_output = <$dh>; chomp $dh_output; close $dh; my ($dir_size) = $dh_output =~ /(\d+)M/; return $dir_size; } sub dirs_for_path { my $path = shift; my %directory_tree; opendir my $dfh, $path or die "Cannot open $path: $!"; # get first level dirs: 20150701, 20150702, etc. my @directories = grep { -d } map { catfile($path, $_) } readdir $dfh; close $dfh; for my $dir (@directories) { next if basename($dir) eq '.' or basename($dir) eq '..'; #get only dirs whose name have two or more digits if (basename($dir) =~ /^\d\d+$/) { $directory_tree{$dir} = {}; } } # get second level dirs: 11, 12, etc for my $monthly_dir (keys %directory_tree) { print "$monthly_dir\n"; #next if $monthly_dir eq '.' or $monthly_dir eq '..'; opendir my $dfh, $monthly_dir or die "Cannot open $monthly_dir: $!"; my @new_paths = grep { -d } map { catfile($monthly_dir, $_) } readdir $dfh; print "@new_paths\n"; my %temp_hash; for my $hourly_dir (@new_paths) { next if basename($hourly_dir) eq '.' or basename($hourly_dir) eq '..'; #get only dirs whose name have two or more digits if (basename($hourly_dir) =~ /^\d\d+$/) { $temp_hash{$hourly_dir} = get_dir_size $hourly_dir; } } $directory_tree{$monthly_dir} = \%temp_hash; } #print "@directories\n"; return \%directory_tree; } # MAIN logic if (! -d $root_folder) { print "$root_folder does not exist or is not a directory. Exiting\n"; exit 1; } my $max_size = get_config("pcap_hdd_reserved_space"); $max_size = $DEFAULT_PCAP_HDD_RESERVED_SPACE if $max_size < 1; printf "Starting $0 script:\n"; printf "pcap_hdd_reserved_space = $max_size MB\n"; my $initial_size = get_dir_size $root_folder; if ($initial_size < $max_size) { printf ("initial_size (%d MB) < max_size (%d MB), nothing to do!\n\nn", $initial_size, $max_size); exit 1; } my $directory_tree = dirs_for_path $root_folder; #print Dumper($directory_tree); printf ("initial_size (%d MB) > max_size (%d MB), will proceed to delete some dirs!\n", $initial_size, $max_size); #TO DO delete empty monthly dirs for my $monthly_dir ( sort {basename($a) <=> basename($b)} keys %$directory_tree ){ last if ($initial_size < $max_size); for my $hourly_dir ( sort {basename($a) <=> basename($b) } keys %{$directory_tree->{$monthly_dir}}) { last if ($initial_size < $max_size); my $dir_size = $directory_tree->{$monthly_dir}{$hourly_dir}; print("Proceeding to delete $hourly_dir\n"); remove_tree( "$hourly_dir", {error => \my $err} ); if (@$err) { for my $diag (@$err) { my ($file, $message) = %$diag; if ($file eq '') { print "general error: $message\n"; } else { print "problem unlinking $file: $message\n"; } } } else { print "No error encountered\n"; } $initial_size = $initial_size - $dir_size; print "$hourly_dir deleted, $dir_size MB freed, current $root_folder size $initial_size MB, max allowed size $max_size MB\n\n"; } }