【问题标题】:How do I 'cd' to a symbolically linked directory that says "Permission denied"? [closed]如何“cd”到显示“权限被拒绝”的符号链接目录? [关闭]
【发布时间】:2020-06-06 10:59:08
【问题描述】:

我目前在我的 Linux 操作系统上有两个用户,用于两个不同的 DE。但是,我想尽可能地消除帐户之间的文件重复性。具体来说,我一直在尝试将~/german-capstone 文件夹从用户segeeslice 链接到lucifer

为此,作为lucifer,我致电:

ln -s /home/segeeslice/german-capstone /home/lucifer/

它按预期运行,将链接放在正确的位置。但是,尝试访问它会引发如下错误:

bash: cd: german-capstone: Permission denied


我知道这可能只是一个权限问题,但我找不到来源!我已经尽可能让双方完全访问该文件夹及其内容,但似乎没有任何效果。我错过了什么?

Here源目录的权限
Here符号链接的权限


针对评论,以下是完整的权限列表:

------ /home/lucifer/german-capstone ------

    drwxr-xr-x  755 root     root     /
    drwxr-xr-x  755 root     root     /home
    drwxr--r--  744 lucifer  lucifer  /home/lucifer
    lrwxrwxrwx  777 lucifer  lucifer  /home/lucifer/german-capstone
                                      -> /home/segeeslice/german-capstone
    drwxr--r--  744 segeeslice segeeslice /home/segeeslice
    drwxrwxrwx  777 segeeslice segeeslice /home/segeeslice/german-capstone

更高级别仍然具有正确的读取属性...我需要在某处授予更多权限吗?

【问题讨论】:

    标签: linux permissions symlink


    【解决方案1】:

    它可能是源目录或符号链接路径上任何位置的权限,还包括在这些东西的路径中遇到的任何其他符号链接。

    这是一个脚本,它将为您显示所有这些权限。它将显示从根目录到相关路径的所有内容的权限,如果遇到符号链接,它将根据链接目标重新启动,除了它不会重复它拥有的任何目录的输出已经向您展示了(例如,/ 上的权限仅显示一次)。

    #!/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(即为“组”和“其他”添加执行权限),那么这些将具有必要的访问权限。

    【讨论】:

    • 这是我在 1998 年写的代码,很高兴分享给人们按原样使用或适应自己,但很抱歉我现在不提供维护/改进它。
    • 谢谢!我用这个脚本的输出编辑了这篇文章
    • 我可以看到问题所在。我将用它的内容编辑我的答案。
    • @segeeslice 请在我的回答末尾查看新文本。
    • 谢谢!那行得通,我已将其标记为已解决。但是,为什么这条路径需要cd 的执行权限呢?我以为只与在文件夹中执行脚本有关
    猜你喜欢
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 2013-05-22
    • 2014-12-17
    • 2016-07-02
    • 2012-05-16
    • 2017-10-26
    相关资源
    最近更新 更多