#!/usr/bin/perl -w # # show_deleted_maps # # Shows a list of all processes that have files memory mapped which are now deleted. # # by David Harris # # Copyright (c) 2001, DRH Internet Inc. # All Rights Reserved. # use strict; use Symbol qw(); use Getopt::Long; $|++; my $color_red = "\033[1;31m"; my $color_normal = "\033[0;39m"; my $VERSION = "1.00"; &main(); sub get_deleted_maps { my $pid = shift; my $maps_fh = Symbol::gensym(); open($maps_fh, "/proc/$pid/maps") or return undef; my @maps = <$maps_fh>; close($maps_fh); my $deleted_maps_hash; foreach my $map ( @maps ) { chomp $map; next if ( $map =~ m#^(?:\S+\s+){4}0$# ); $map =~ m#^(?:\S+\s+){5}(/.*?)( \(deleted\))?$# or warn "warning: bad map line for pid ($pid): $map\n"; if ( defined($2) ) { my $filename = $1; $deleted_maps_hash->{$filename}++ if ( $filename !~ m|^/SYSV\d+$| ); } } return [ keys(%$deleted_maps_hash) ]; } sub main { ## Parse the command line options my $no_color = 0; my $show_filenames = 0; Getopt::Long::config('bundling_override'); GetOptions( 'c|no-color' => \$no_color, 'f|show-filenames' => \$show_filenames, 'h|help' => sub { usage() }, ) or usage("unable to parse options"); ## Print a list of processes my $num_deleted_maps = 0; my $ps_fh = Symbol::gensym(); open($ps_fh, "ps axf |") or die "unable to open pipe from ps: $!"; while ( <$ps_fh> ) { if ( /^\s*PID\s/ ) { print; } elsif ( /^\s*(\d+)\s/ ) { my $pid = $1; my $maps = get_deleted_maps($pid); if ( not defined $maps ) { print; print " **** unable to find maps file (process terminated?)\n"; } elsif ( @$maps ) { print $no_color ? $_ : ($color_red . $_ . $color_normal); print " **** deleted maps: " . join(", ", sort @$maps) . "\n" if ( $show_filenames ); $num_deleted_maps += scalar(@$maps); } else { print; } } else { print; print " **** warning: unrecognized ps line\n"; } } close($ps_fh); print "\nnumber of deleted maps found: $num_deleted_maps\n"; } sub usage { my $error = shift; print "error: $error\n" if ( defined $error ); print < Copyright (c) 2002, DRH Internet Inc. All Rights Reserved. EOT exit 1; }