我已經編寫了一個perl腳本,用於在服務器中搜索世界可寫文件。但是經過一些測試後,我發現我在邏輯上犯了一個錯誤。具體來說,我告訴它不要搜索/
。我最初的想法是,我一直在尋找本地安裝的卷,同時避免那些偏遠的品種(CIFS
,NFS
,what-have-you)。通過perl腳本搜索文件系統,同時忽略遠程座標
我沒有考慮到的是,並非每個目錄都有唯一的卷。因此,在我的掃描中排除/
,我錯過了幾個應該包含的目錄。現在我需要修改腳本以包含這些腳本,同時仍排除遠程卷。
#!/usr/bin/perl
# Directives which establish our execution environment
use warnings;
use strict;
use Fcntl ':mode';
use File::Find;
no warnings 'File::Find';
no warnings 'uninitialized';
# Variables used throughout the script
my $DIR = "/var/log/tivoli/";
my $MTAB = "/etc/mtab";
my $PERMFILE = "world_writable_w_files.txt";
my $TMPFILE = "world_writable_files.tmp";
my $EXCLUDE = "/usr/local/etc/world_writable_excludes.txt";
# Compile a list of mountpoints that need to be scanned
my @mounts;
# Create the filehandle for the /etc/mtab file
open MT, "<${MTAB}" or die "Cannot open ${MTAB}, $!";
# We only want the local mountpoints that are not "/"
while (<MT>) {
if ($_ =~ /ext[34]/) {
my @line = split;
push(@mounts, $line[1]) unless ($_ =~ /root/);
}
}
close MT;
# Read in the list of excluded files
my $regex = do {
open EXCLD, "<${EXCLUDE}" or die "Cannot open ${EXCLUDE}, $!\n";
my @ignore = <EXCLD>;
chomp @ignore;
local $" = '|';
qr/@ignore/;
};
# Create the output file path if it doesn't already exist.
mkdir "${DIR}" or die "Cannot execute mkdir on ${DIR}, $!" unless (-d "${DIR}");
# Create the filehandle for writing the findings
open WWFILE, ">${DIR}${TMPFILE}" or die "Cannot open ${DIR}${TMPFILE}, $!";
foreach (@mounts) {
# The anonymous subroutine which is executed by File::Find
find sub {
return unless -f; # Is it a regular file...
# ...and world writable.
return unless (((stat)[2] & S_IWUSR) && ((stat)[2] & S_IWGRP) && ((stat)[2] & S_IWOTH));
# Add the file to the list of found world writable files unless it is
# in the list if exclusions
print WWFILE "$File::Find::name\n" unless ($File::Find::name =~ $regex);
}, $_;
}
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}, $!";
}
我現在對於如何解決這個問題有點不知所措。我知道我可以使用stat -f -c %T
獲得必要的信息,但是我沒有看到perl內置的stat
的類似選項(除非我誤解了輸出字段的描述;也許可以在S_
變量之一中找到它)。
我只是在正確的方向尋找推動力。我真的不想下載到shell命令來獲取這些信息。
編輯:我發現this answer to a similar question,但它似乎並不完全有幫助。當我測試內置stat
對CIFS
安裝我得到18
。也許我需要的是可以返回遠程文件以進行比較的值的全面列表。
EDIT2:這是在其新的形式的腳本符合要求:
#!/usr/bin/perl
# Directives which establish our execution environment
use warnings;
use strict;
use Fcntl ':mode';
use File::Find;
no warnings 'File::Find';
no warnings 'uninitialized';
# Variables used throughout the script
my $DIR = "/var/log/tivoli/";
my $MTAB = "/etc/mtab";
my $PERMFILE = "world_writable_w_files.txt";
my $TMPFILE = "world_writable_files.tmp";
my $EXCLUDE = "/usr/local/etc/world_writable_excludes.txt";
my $ROOT = "/";
my @devNum;
# Create an array of the file stats for "/"
my @rootStats = stat("${ROOT}");
# 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]/) {
my @line = split;
push(@mounts, $line[1]);
}
}
close MT;
# Build an array of each mountpoint's device number for future comparison
foreach (@mounts) {
my @stats = stat($_);
push(@devNum, $stats[0]);
}
# Read in the list of excluded files and create a regex from them
my $regExcld = do {
open XCLD, "<${EXCLUDE}" or die "Cannot open ${EXCLUDE}, $!\n";
my @ignore = <XCLD>;
chomp @ignore;
local $" = '|';
qr/@ignore/;
};
# Create a regex to compare file device numbers to.
my $devRegex = do {
chomp @devNum;
local $" = '|';
qr/@devNum/;
};
# 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}, $!";
foreach (@mounts) {
# The anonymous subroutine which is executed by File::Find
find sub {
# Is it in a basic directory, ...
return if $File::Find::dir =~ /sys|proc|dev/;
# ...a regular file, ...
return unless -f;
# ...local, ...
my @dirStats = stat($File::Find::name);
return unless $dirStats[0] =~ $devRegex;
# ...and world writable?
return unless (((stat)[2] & S_IWUSR) && ((stat)[2] & S_IWGRP) && ((stat)[2] & S_IWOTH));
# If so, add the file to the list of world writable files unless it is
# in the list if exclusions
print(WWFILE "$File::Find::name\n") unless ($File::Find::name =~ $regExcld);
}, $_;
}
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}, $!";
}
當你說「開始於」時,你是指我從哪裏運行腳本? – theillien
在我的鍵盤上撥了一段時間然後往下走,然後回溯到不必要的路徑後,我相信我有我需要的東西:https://codereview.stackexchange.com/questions/46611/perl-script-to-find-world-可寫 - 文件 - 在本地的目錄只。我接受你的解決方案不僅僅是因爲它是唯一的(;)),而是因爲它正是我所需要的(以及我所要求的):正確的方向。 – theillien