filesystems - Ignore an entire directory when using File::Find in Perl script -
i have script scans every local filesystem world-writable files. found files written output file. uses file provides list of files ignore.
we have tivoli monitoring agent installed which, unusual reason, has been designed create every file in installation path world-writable permissions. known , there little can it, ignore entire directory.
i imagine can utilize glob such /opt/ibm/itm/* haven't first bit of clue @ how that.
at moment i've hard-coded directory script. less ideal, functional. i'd prefer have in list of excludes.
over @ code review suggested utilize file::find::prune. unfortunately, hasn't worked. gather , understand file::find::prune if finds file @ /opt/ibm/itm/.../.../file.txt supposed excluded, skip entire /opt/ibm/itm/.../.../ directory. fine, means need have exclusion entry every sub-directoy of /opt/ibm/itm/. tedious endeavor considering how many sub-directories , sub-sub-directories there are.
i did seek placing world-writable file under /opt/ibm/itm/ , add together exclusion list, didn't work. i'm guessing because wasn't found first.
the script:
#!/usr/bin/perl utilize warnings; utilize strict; utilize fcntl ':mode'; utilize file::find; no warnings 'file::find'; no warnings 'uninitialized'; $dir = "/var/log/tivoli/"; $mtab = "/etc/mtab"; $permfile = "world_writable_files.txt"; $tmpfile = "world_writable_files.tmp"; $exclude = "/usr/local/etc/world_writable_excludes.txt"; $mask = s_iwusr | s_iwgrp | s_iwoth; (%excludes, %devnums); $errheader; # compile list of mountpoints need scanned @mounts; open mt, "<${mtab}" or die "cannot open ${mtab}, $!"; # want local mountpoints while (<mt>) { if ($_ =~ /ext[34]/) { chomp; @line = split; push(@mounts, $line[1]); @stats = stat($line[1]); $devnums{$stats[0]} = undef; } } close mt; # build hash /usr/local/etc/world_writables_excludes.txt if ((! -e $exclude) || (-z $exclude)) { $errheader = <<header; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! /usr/local/etc/world_writable_excludes.txt !! !! missing or empty. study includes !! !! every world-writable file including !! !! expected , should excluded. !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! header } else { open xcld, "<${exclude}" or die "cannot open ${exclude}, $!\n"; while (<xcld>) { chomp; $excludes{$_} = 1; } } sub wanted { @dirstats = stat($file::find::name); # excluded report... homecoming if exists $excludes{$file::find::name}; # ...is tivoli installation directory... homecoming if ($file::find::name =~ /\b\/itm\b/); # ...in special directory, ... homecoming if ($file::find::name =~ /^\bsys\b|\bproc\b|\bdev\b$/); # ...a regular file, ... homecoming unless -f; # ...local, ... homecoming unless (exists $devnums{$dirstats[0]}); # ...and world writable? homecoming unless ($dirstats[2] & $mask) == $mask; # if so, add together file list of world writable files print(wwfile "$file::find::name\n"); } # create output file path if doesn't exist. mkdir($dir or die "cannot execute mkdir on ${dir}, $!") unless (-d $dir); # create our filehandle writing our findings open wwfile, ">${dir}${tmpfile}" or die "cannot open ${dir}${tmpfile}, $!"; print(wwfile "${errheader}") if ($errheader); finddepth(\&wanted, @mounts); close wwfile; # if no world-writable files have been found ${tmpfile} should zero-size; # delete tivoli won't alert if (-z "${dir}${tmpfile}") { unlink "${dir}${tmpfile}"; } else { rename("${dir}${tmpfile}","${dir}${permfile}") or die "cannot rename file ${dir}${tmpfile}, $!"; } it has been suggested elsewhere utilize file::find::rule. i'd rather avoid doing because don't want perform finish rewrite of script.
as i've said, script above works. i'd prefer not hard-coding exclusion, though. figuring out how allow me remove match against "special" directories.
to prune entire directory tree, set $file::find::prune value in wanted sub. work long bydepth not specified:
if ($file::find::name eq '/opt/ibm/itm') { $file::find::prune = 1; return; } perl filesystems
No comments:
Post a Comment