[英]Perl script writing output twice; second time in reverse order
我試圖弄清楚一個腳本為什么兩次寫輸出。 第一次以正確的順序,第二次以相反的順序。 它應該只編寫一次。
#!/usr/bin/perl
use warnings;
use strict;
use Fcntl ':mode';
use File::Find;
no warnings 'File::Find';
no warnings 'uninitialized';
my $dir = "/var/log/tivoli/";
my $mtab = "/etc/mtab";
my $permFile = "world_writable_files.txt";
my $tmpFile = "world_writable_files.tmp";
my $exclude = "/usr/local/etc/world_writable_excludes.txt";
my $mask = S_IWUSR | S_IWGRP | S_IWOTH;
my (%excludes, %devNums);
my $errHeader;
# Compile a list of mountpoints that need to be scanned
my @mounts;
open MT, "<${mtab}" or die "Cannot open ${mtab}, $!";
# We only want the local mountpoints
while (<MT>) {
if ($_ =~ /ext[34]/) {
chomp;
my @line = split;
push(@mounts, $line[1]);
my @stats = stat($line[1]);
$devNums{$stats[0]} = undef;
}
}
close MT;
# Build a hash from /usr/local/etc/world_writables_excludes.txt
if ((! -e $exclude) || (-z $exclude)) {
$errHeader = <<HEADER;
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! /usr/local/etc/world_writable_excludes.txt is !!
!! is missing or empty. This report includes !!
!! every world-writable file including those which !!
!! are expected and should be excluded. !!
!! !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
HEADER
} else {
open XCLD, "<${exclude}" or die "Cannot open ${exclude}, $!\n";
while (<XCLD>) {
chomp;
$excludes{$_} = 1;
}
}
sub wanted {
my @dirStats = stat($File::Find::name);
# Is it excluded from the report...
return if exists $excludes{$File::Find::name};
# ...is the Tivoli installation directory or a special directory...
if ($File::Find::name =~ m{^/sys|^/proc|^/dev|^/opt/IBM/ITM}) {
$File::Find::prune = 1;
return;
}
# ...a regular file, ...
return unless -f;
# ...local, ...
return unless (exists $devNums{$dirStats[0]});
# ...and world writable?
return unless ($dirStats[2] & $mask) == $mask;
# If so, add the file to the list of world writable files
print(WWFILE "$File::Find::name\n");
}
# Create the output file path if it doesn't already exist.
mkdir($dir or die "Cannot execute mkdir on ${dir}, $!") unless (-d $dir);
# Create our filehandle for writing our findings
open WWFILE, ">${dir}${tmpFile}" or die "Cannot open ${dir}${tmpFile}, $!";
print(WWFILE "${errHeader}") if ($errHeader);
find(\&wanted, @mounts);
close WWFILE;
# If no world-writable files have been found ${tmpFile} should be zero-size;
# Delete it so Tivoli won't alert
if (-z "${dir}${tmpFile}") {
unlink "${dir}${tmpFile}";
} else {
rename("${dir}${tmpFile}","${dir}${permFile}") or die "Cannot rename file ${dir}${tmpFile}, $!";
}
輸出示例:
# cat world_writable_files.txt
/var/opt/ds_agent/am/diagnostic_1.log
/home/User1/report.pl.20130220
/home/User1/report.pl.20130220
/var/opt/ds_agent/am/diagnostic_1.log
每個文件在腳本中只被寫入一次,所以我想知道文件系統是否被掃描了兩次。 每個方向一次。 我看不到會發生什么,但我不知道。
排除文件:
# cat /usr/local/etc/world_writable_excludes.txt
/var/opt/ds_agent/diagnostic.log
/var/opt/ds_agent/am/diagnostic.log
對這個難題有什么想法嗎?
這是因為@mounts
除了/home
和/var
之外還具有/
。 因此,您要求它掃描/
以及以下的所有內容(包括/home
和/var
),然后掃描/home
以及以下的所有內容,然后掃描/var
以及以下的所有內容。
最好確定要避開的地方。
while (<MT>) {
my @fields = split;
if ($field[2] !~ /^ext[34]\z/) {
++$excludes{ $fields[1] };
}
}
find(\&wanted, '/');
sub wanted {
if ($excludes{$File::Find::name}) {
$File::Find::prune = 1;
return;
}
my @dirStats = stat($File::Find::name);
return if !-f;
return if $dirStats[2] & S_IWOTH;
print(WWFILE "$File::Find::name\n");
}
您不再需要if ($File::Find::name =~ m{^/sys|^/proc|^/dev|^/opt/IBM/ITM})
,因為它們不是ext3或ext4。 /opt/IBM/ITM
可能除外(因為我不知道那是什么)。 如果確實有一些要跳過的文件或目錄,請將其添加到%excludes
而不要進行相對昂貴的正則表達式匹配。
++$excludes{$_} for qw( /foo /bar /opt/IBM/ITM );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.