X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=dsa-nagios-checks%2Fchecks%2Fdsa-check-libs;h=2dc0f159e60bc25892914021fd69c4c364370def;hb=b3923761df2779305961f11dc4e953dc31624f00;hp=77707d9cd5b66262b0c1547b23e5805668e6e562;hpb=02c5110489125ee137158e757b81814eb8186b28;p=mirror%2Fdsa-nagios.git diff --git a/dsa-nagios-checks/checks/dsa-check-libs b/dsa-nagios-checks/checks/dsa-check-libs index 77707d9..2dc0f15 100755 --- a/dsa-nagios-checks/checks/dsa-check-libs +++ b/dsa-nagios-checks/checks/dsa-check-libs @@ -30,7 +30,7 @@ $ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; my $LSOF = '/usr/bin/lsof -F0'; -my $VERSION = '0.2012042101'; +my $VERSION = '0.2015012901'; # nagios exit codes my $OK = 0; @@ -48,19 +48,37 @@ sub dief { exit $UNKNOWN; } +sub convert_time { + my $in = shift; + my ($ticks, $unit) = ($in =~ /^(\d+)([smhdw]?)$/); + + if ($unit eq 's' || $unit eq '') { } + elsif ($unit eq 'm') { $ticks *= 60; } + elsif ($unit eq 'h') { $ticks *= 60*60; } + elsif ($unit eq 'd') { $ticks *= 60*60*24; } + elsif ($unit eq 'w') { $ticks *= 60*60*24*7; } + else { die "Invalid unit '$unit' in '$in'\n" } + return $ticks; +} + + if (!GetOptions ( - '--help' => \$params->{'help'}, - '--version' => \$params->{'version'}, - '--quiet' => \$params->{'quiet'}, - '--verbose' => \$params->{'verbose'}, - '--config=s' => \$params->{'config'}, + '--help' => \$params->{'help'}, + '--version' => \$params->{'version'}, + '--quiet' => \$params->{'quiet'}, + '--ignore-pid-namespaces' => \$params->{'ignore_pid_namespaces'}, + '--verbose' => \$params->{'verbose'}, + '--ignore-younger=s' => \$params->{'ignore_younger'}, + '-v' => \$params->{'verbose'}, + '--config=s' => \$params->{'config'}, )) { - dief ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--quiet] [--config=]\n"); + dief ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--ignore-pid-namespaces] [--verbose] [--quiet] [--config=]\n"); }; if ($params->{'help'}) { - print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--verbose] [--quiet] [--config=]\n"; + print "$PROGRAM_NAME: Usage: $PROGRAM_NAME [--help|--version] [--ignore-pid-namespaces] [--verbose] [--quiet] [--config=]\n"; print "Reports processes that are linked against libraries that no longer exist.\n"; print "The optional config file can specify ignore rules - see the sample config file.\n"; + print "Can optionally ignore processes from other PID namespaces.\n"; exit (0); }; if ($params->{'version'}) { @@ -103,7 +121,6 @@ if (! exists $config->{'ignorelist'}) { dief("Config->ignorelist is not an array!\n"); } - my %processes; sub getPIDs($$) { @@ -138,11 +155,37 @@ sub inVserver() { close F; return 0; } +sub getYoungProcesses() { + my $ignore_hash = {}; + if (defined $params->{'ignore_younger'}) { + eval "use Proc::ProcessTable; 1" or die "We need Proc::ProcessTable to use --ignore-younger.\n"; + my $min_age = convert_time($params->{'ignore_younger'}); + my $cutoff = time() - $min_age; + + my $process_table = new Proc::ProcessTable(enable_ttys => 0); + for my $p ( @{$process_table->table} ){ + $ignore_hash->{$p->pid} = 1 if $p->start > $cutoff; + } + } + return $ignore_hash; +} + + +my $IGNORE_YOUNG_PROCESSES = getYoungProcesses(); + + + my $INVSERVER = inVserver(); +my $PID_NS_SUPPORT = (-f '/proc/self/ns/pid'); +my $PID_NS; +if ($PID_NS_SUPPORT and $params->{'ignore_pid_namespaces'}) { + $PID_NS = readlink('/proc/self/ns/pid'); +} + print STDERR "Running $LSOF -n\n" if $params->{'verbose'}; -open (LSOF, "$LSOF -n|") or dief ("Cannot run $LSOF -n: $!\n"); +open (LSOF, "$LSOF -n 2>/dev/null|") or dief ("Cannot run $LSOF -n: $!\n"); my @lsof=; close LSOF; if ($CHILD_ERROR) { # program failed @@ -155,10 +198,15 @@ LINE: for my $line (@lsof) { my %fields = map { m/^(.)(.*)$/ ; $1 => $2 } grep { defined $_ and length $_ >1} split /\0/, $line; $process = $fields{c}; $pid = $fields{p}; - $user = $fields{L}; + $user = $fields{L} || ''; next; } + if ($PID_NS_SUPPORT and $params->{'ignore_pid_namespaces'}) { + my $pidns = readlink('/proc/'.$pid.'/ns/pid'); + next if (defined $pidns and $PID_NS ne $pidns); + } + unless ( $line =~ /^f/ ) { dief("UNKNOWN strange line read from lsof\n"); # don't print it because it contains NULL characters... @@ -170,12 +218,23 @@ LINE: for my $line (@lsof) { my $inode = $fields{i}; my $path = $fields{n}; if ($path =~ m/\.dpkg-/ || $path =~ m/\(deleted\)/ || $path =~ /path inode=/ || $path =~ m#/\.nfs# || $fd eq 'DEL') { + my $deleted_in_path = ($path =~ m/\(deleted\)/ || $path =~ m/\.nfs/); + next if ($deleted_in_path && $fd =~ /^[0-9]*$/); # Ignore deleted files that are open via normal file handles. + next if ($deleted_in_path && $fd eq 'cwd'); # Ignore deleted directories that we happen to be in. + $path =~ s/^\(deleted\)//; # in some cases "(deleted)" is at the beginning of the string for my $i (@{$config->{'ignorelist'}}) { my $ignore = eval($i); next LINE if $ignore; } next if ($INVSERVER && ($process eq 'init') && ($pid == 1) && ($user eq 'root')); + if (exists $IGNORE_YOUNG_PROCESSES->{$pid}) { + if ( $params->{'verbose'} ) { + print STDERR "ignoring young $process($pid) because of [$path]:\n"; + print STDERR $line; + } + next LINE + } if ( $params->{'verbose'} ) { print STDERR "adding $process($pid) because of [$path]:\n"; print STDERR $line;