它可能是源目录或符号链接路径上任何位置的权限,还包括在这些东西的路径中遇到的任何其他符号链接。
这是一个脚本,它将为您显示所有这些权限。它将显示从根目录到相关路径的所有内容的权限,如果遇到符号链接,它将根据链接目标重新启动,除了它不会重复它拥有的任何目录的输出已经向您展示了(例如,/ 上的权限仅显示一次)。
#!/usr/bin/perl
#
use strict;
my $usage=<<EOF;
Usage: $0 file [file ...]
Shows permissions on every path component from root directory to the named
file(s), including paths traversed while following symlinks.
Also shows permissions and contents of any .ftpaccess or .htaccess files
encountered.
If multiple files are specified, gives a listing for them all, but for later
files does not show again the permissions on a path component already shown
for earlier files.
EOF
#----------------------------------------------------------------------
use Cwd;
my $cwd = cwd;
chomp $cwd;
if ($#ARGV==-1) {
print $usage;
exit 1;
};
my @history=();
my @accessfiles=();
# loop over files on command line.
FILE: foreach my $fullpath (@ARGV) {
# prepend cwd if relative path
$fullpath="$cwd/$fullpath" unless $fullpath =~ /^\//;
# fix pathname..
$fullpath=stripslashes($fullpath);
print "\n------ $fullpath ------\n\n";
my $len=length $fullpath;
my $pos=-1;
my @targets=($fullpath);
ELEMENT: while ($pos<$len) {
# get full pathname of next element (etc)
my $stem=($pos>=0) ? substr($fullpath,0,$pos) : ''; # parent
$pos=index($fullpath,'/',$pos+1);
$pos=$len if $pos==-1;
my $path=($pos>0) ? substr($fullpath,0,$pos) : '/';
my $remainder=substr($fullpath,$pos);
#
# stat the path element.
#
my @stat=lstat($path);
my $okay=($#stat != -1);
# tidy up as follows:
# if trailing "/foo/.." or "/." strip it and move to next element.
#
# We can do this because at this stage "foo" isn't a link,
# or we would already have followed it, but only do it if stat
# succeeded as parent might not be a directory (in that case, the
# error trap later will be executed).
#
my ($newpath, $subst);
if ($okay) {
$subst=1;
if ( $path =~ /\.\.$/ ) {
if ($stem eq '') {
$newpath='/';
$fullpath=$remainder;
} else {
($newpath = $stem) =~ s,/([^/]*?)$,, ;
$fullpath=$newpath.$remainder;
if ($newpath eq '') {$newpath='/';}
}
}
elsif ( $path =~ /\.$/ ) {
if ($stem eq '') {
$newpath='/';
$fullpath=$remainder;
} else {
$newpath = $stem;
$fullpath=$newpath.$remainder;
}
}
else {
$subst=0;
}
if ($subst) {
$path=$newpath;
$pos=length $path;
$len=length $fullpath;
next ELEMENT;
}
}
# have we been here before?
my $beenthere=grep {$_ eq $path} @history;
push @history,$path;
# is it a symlink?
if (-l _) {
# yes. see where it points
my $pointsto=readlink $path;
my $newfile;
if ($pointsto =~ /^\//) {
# link is absolute pathname
$newfile=$pointsto.substr($fullpath,$pos);
$pos=-1;
} else {
# link is relative pathname
$newfile=$stem.'/'.$pointsto.substr($fullpath,$pos);
$pos=length $stem;
}
if (!$beenthere) {
show_stat(\@stat,$path,$pointsto);
}
# strip extra "/"
$newfile=stripslashes($newfile);
# check for recursive links
my $beenthere2=grep {$_ eq $newfile} @targets;
push @targets,$newfile;
if ($beenthere2) {
print " === SYMLINK LOOP DETECTED ===\n";
next FILE;
}
# follow the link (stripping extra "/"s)
$fullpath=$newfile;
$len=length $fullpath;
} else {
# no, not a symlink
# print info, with usernames/groupnames where possible
# unless we've been here before...
if (!$beenthere) {
if (! $okay) {
print "\n*** ERROR : $path : $! ***\n";
next FILE;
}
show_stat(\@stat,$path);
#
# check for any {.htaccess,.ftpaccess} files
#
for my $name (qw(.htaccess .ftpaccess)) {
my $file = "$path/$name";
if (-e $file) {
push @accessfiles,$file;
}
}
}
}
} # end ELEMENT loop
} # end FILE loop
continue {
print "\n";
}
if ($#accessfiles > -1) {
print "Access control files of possible relevance:\n\n";
for my $file (@accessfiles) {
my @stat = stat($file);
show_stat(\@stat,$file);
if (open my $access,$file) {
print "\n ---- Contents of $file ----\n";
while (defined (my $line=<$access>)){
chomp $line;
print " $line\n";
}
close $access;
print " ------- End of $file -------\n";
} else {
print " Could not open $file: $!\n";
}
}
print "\n";
}
exit 0;
#-------------------------------------------------------------
sub stripslashes
{
my $line = shift;
# strip trailing or repeated '/'s
$line =~ s,/*$,,;
$line =~ s,//+,/,g;
$line =~ s,^$,/,;
return $line;
}
sub show_stat
{
use Fcntl ':mode';
my ($stat,$path,$linktarget) = @_;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = @$stat;
my @pwent=getpwuid($uid);
my $username=($#pwent == -1) ? "($uid)" : $pwent[0];
my @grent=getgrgid($gid);
my $grpname=($#grent == -1) ? "($gid)" : $grent[0];
printf ("%s %4o %-8s %-8s %s\n",
symbolic_mode($mode),
$mode&07777,$username,$grpname,$path);
if (S_ISLNK($mode) and defined($linktarget)) {
print " -> $linktarget\n";
}
}
sub symbolic_mode
{
# takes a numerical mode returned by stat,
# returns a symbolic string as per "ls -l"
# e.g. for 0640 returns "-rw-r-----"
my $mode = shift;
use Fcntl ':mode';
my $typechar =
S_ISREG($mode) ? '-' :
S_ISDIR($mode) ? 'd' :
S_ISLNK($mode) ? 'l' :
S_ISBLK($mode) ? 'b' :
S_ISCHR($mode) ? 'c' :
S_ISFIFO($mode) ? 'p' :
S_ISSOCK($mode) ? 's' :
'?';
my $modestr = $typechar . 'rwxrwxrwx';
for (my $bit=0; $bit <= 8 ; $bit++) {
if (($mode & (1<<$bit)) == 0) {
substchar(\$modestr,9-$bit,"-");
}
}
if ($mode & 01000) {
substchar(\$modestr,9,
($mode & 0001) ? "t" : "T");
}
if ($mode & 02000) {
substchar(\$modestr,6,
($mode & 0010) ? "s" : "S");
}
if ($mode & 04000) {
substchar(\$modestr,3,
($mode & 0100) ? "s" : "S");
}
return $modestr;
}
sub substchar
{
# substitutes a character in a string
my ($sref, $pos, $newchar) = @_;
my $string = $$sref;
my $newstring = substr($string,0,$pos) . $newchar . substr($string,$pos+1);
$$sref=$newstring;
}
示例输出:
$ mkdir -p /tmp/mydir/stuff
$ ln -s stuff /tmp/mydir/stuff2
$ cal > /tmp/mydir/stuff2/myfile
$ mkdir /tmp/mydir2
$ ls /tmp/mydir2/stuff2/myfile
ls: cannot access '/tmp/mydir2/stuff2/myfile': No such file or directory
$ ls /tmp/mydir/stuff2/
myfile
$ ln -s /tmp/mydir/stuff2/myfile /tmp/mydir/stuff2/thingy
$ chmod 700 /tmp/mydir
$ permsto /tmp/mydir/stuff2/thingy
------ /tmp/mydir/stuff2/thingy ------
drwxr-xr-x 755 root root /
drwxrwxrwt 1777 root root /tmp
drwx------ 700 myuser mygroup /tmp/mydir
lrwxrwxrwx 777 myuser mygroup /tmp/mydir/stuff2
-> stuff
drwxr-xr-x 755 myuser mygroup /tmp/mydir/stuff
lrwxrwxrwx 777 myuser mygroup /tmp/mydir/stuff/thingy
-> /tmp/mydir/stuff2/myfile
-rw-r--r-- 644 myuser mygroup /tmp/mydir/stuff/myfile
因此,您可以查看输出并一目了然地看到任何权限问题潜伏在哪里。
现在问题已更新为包含相关目录中脚本的输出,很明显问题出在以下目录的权限上:
drwxr--r-- 744 lucifer lucifer /home/lucifer
drwxr--r-- 744 segeeslice segeeslice /home/segeeslice
如果进程对目录具有读取但不执行访问权限,它将能够列出该目录,但不能以其他方式访问其中包含的任何路径。对于具有八进制模式 744 的目录,任何不以所有者(或 root)身份运行的进程都是这种情况,这将依赖于“组”或“其他”权限。如果改为八进制模式 755(即为“组”和“其他”添加执行权限),那么这些将具有必要的访问权限。