Perl脚本编写输出两次;倒序第二次

Perl脚本编写输出两次;倒序第二次,perl,Perl,我试图弄明白为什么一个脚本要写两次输出。第一次按正确顺序,第二次按相反顺序。它应该只写一次 #!/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 =

我试图弄明白为什么一个脚本要写两次输出。第一次按正确顺序,第二次按相反顺序。它应该只写一次

#!/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 /usr/local/etc/world_writable_excludes.txt 
/var/opt/ds_agent/diagnostic.log
/var/opt/ds_agent/am/diagnostic.log

对这个难题有什么想法吗?

这是因为
@mounts
除了
/home
/var
之外还有
//code>。因此,您要求它扫描
/
(包括
/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");
}

这是因为
@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");
}


你能把剩下的代码贴出来吗,特别是你从哪里得到文件列表,从哪里打印出来?我已经贴出了整个脚本。就这些。你滚动过它了吗?@CDahn它被打印在
通缉
子计数器中。我不确定,但是在调用
find(\&wanted,@mounts)之前,请尝试打印
@mounts
。因为“find()会按照给定的顺序对给定的@目录进行深度优先搜索。对于找到的每个文件或目录,它都会调用&want子例程。”我想它已经找到了两次这些文件,但我真的不知道,可能完全错了。奇怪的是,它没有正确地呈现给我。转到figure.printing
@mounts
生成
#/home/msnyder/ww_files-v4-4.pl//boot/home/opt/var/ecap/log_归档文件
你能把剩下的代码发布到哪里吗,特别是你从哪里得到文件列表,从哪里打印出来?我已经发布了整个脚本。就这些。你滚动过它了吗?@CDahn它被打印在
通缉
子计数器中。我不确定,但是在调用
find(\&wanted,@mounts)之前,请尝试打印
@mounts
。因为“find()会按照给定的顺序对给定的@目录进行深度优先搜索。对于找到的每个文件或目录,它都会调用&want子例程。”我想它已经找到了两次这些文件,但我真的不知道,可能完全错了。奇怪的是,它没有正确地呈现给我。进入figure.printing
@mounts
生成
#/home/msnyder/ww_files-v4-4.pl//boot/home/opt/var/ecap/log_归档文件
这很有趣。对于qw(/sys/proc/dev//opt/IBM/ITM),是否可以使用而不是
+$excludes{$\uz},将这些目录添加到我的排除文件,并以相同的方式添加它们?理想情况下,我更愿意将这些硬编码保存在脚本本身中。其次,由您决定它是硬编码的(如图所示)还是在您的文件中。我将
while
循环更改为您建议的,并添加了设置
$file::Find::prune=1的块。到目前为止,没有别的了。它抛出了一个错误:
位于/usr/share/perl5/File/Find.pm第598行第2行的顶部目录无效。
。我已将排除文件添加到我的帖子中以供参考。您没有将目录传递给
find
。您是否仍在使用
find(\&wanted,@mounts)?忽略我以前的评论(编辑之前的评论)。我已经添加了您提供的所有代码,它正在做它应该做的事情,包括删除硬编码目录的需要。这些现在是excludes文件的一部分。这很有趣。对于qw(/sys/proc/dev//opt/IBM/ITM),是否可以使用而不是
+$excludes{$\uz},将这些目录添加到我的排除文件,并以相同的方式添加它们?理想情况下,我更愿意将这些硬编码保存在脚本本身中。其次,由您决定它是硬编码的(如图所示)还是在您的文件中。我将
while
循环更改为您建议的,并添加了设置
$file::Find::prune=1的块。到目前为止,没有别的了。它抛出了一个错误:
位于/usr/share/perl5/File/Find.pm第598行第2行的顶部目录无效。
。我已将排除文件添加到我的帖子中以供参考。您没有将目录传递给
find
。您是否仍在使用
find(\&wanted,@mounts)?忽略我以前的评论(编辑之前的评论)。我已经添加了您提供的所有代码,它正在做它应该做的事情,包括删除硬编码目录的需要。这些现在是排除文件的一部分。
++$excludes{$_} for qw( /foo /bar /opt/IBM/ITM );