当仅执行目录时,bash 和 csh 中的 PATH 行为不同?

当仅执行目录时,bash 和 csh 中的 PATH 行为不同?

我们在各个子目录中有一些应用程序,我们限制 unix 组对其进行访问,并且我们希望它们只能执行。因此,例如,如果我们希望“chem”组的成员对 a.out 具有仅执行访问权限,我们可以:

$ ll -d /tmp/dir1
drwx--x--- 2 root chem 18 Oct 20 07:50 /tmp/dir1/
$ ll /tmp/dir1/a.out 
-rwx--x--- 1 root chem 8728 Oct 20 07:50 /tmp/dir1/a.out

现在,我(“chem”组的成员)可以从 bash shell 将此目录添加到我的路径中并执行 a.out:

$ export PATH=/tmp/dir1:$PATH
$ a.out
 This is a test. . .

但是,从 tcsh 中,我不能:

$ set path = ( /tmp/dir1 $path )
$ a.out
a.out: Command not found.

我必须向父目录添加组读取权限,以便 tcsh 用户能够运行 a.out(bash 在这两种情况下都有效):

$ ll -d /tmp/dir1
drwxr-x--- 2 root chem 18 Oct 20 07:50 /tmp/dir1/

chmod 之后,我注销并重新登录(在 tcsh 下),然后:

$ set path = ( /tmp/dir1 $path )
$ a.out
 This is a test. . .

我们预计不需要父目录的读取权限。我已经查阅了所有文档来解释在这种情况下 bash 和 tcsh 之间明显的行为差异,但没有运气。谁能解释一下吗?顺便说一句,我在 SLES 12 和 CentOS 7 下进行了这些测试,两种情况下的行为是相同的。

答案1

bash每次运行命令时,都会搜索 $PATH 中的每个目录(从第一个到最后一个),并尝试从该目录运行该命令。它要么成功,要么失败。因此,如果/tmp/dir1位于您的 $PATH 中,并且a.out位于该目录中,您可以尝试运行a.out- bashwill tr​​y to run /tmp/dir1/a.out,并且会成功,因为您具有执行权限。

csh是不同的。当您更改(或设置) 时$pathcsh会构建在路径中每个目录中找到的所有内容的哈希表,并且它会记住这些目录在路径中出现的顺序。默认情况下,当您运行命令(不使用完整路径名)时,csh会查看其哈希表以查看它是否记得该命令位于路径中的某处(并且如果路径中的多个目录都有该命令,则它会选择第一个)它按照 中列出的顺序找到它$path。如果它在哈希表中没有找到它,那么它假设不存在这样的命令,并且您会收到一个错误,这在很久以前就很有用,当时它所花费的时间量。向下搜索路径中的所有目录并查找命令实际上不再那么重要了,但csh一直都是这样,今天仍然如此。

为了csh构建其哈希表,它需要对$path.因为它需要能够准确地知道哪些可执行文件位于$path.因为您已拒绝 的读取权限/tmp/dir1csh所以无法为其构建哈希表,并且它会将其视为该目录中根本没有命令。这就是为什么在没有读取权限的目录中csh找不到您的文件的原因。a.out$path

为了能够csh在 $path 上的目录中找到没有读取权限的命令,您必须关闭哈希函数。您可以通过运行内置命令来完成此操作unhash。一旦你运行它,哈希表函数就会关闭,并且csh将回退到仅尝试搜索路径中的每个目录,看看它是否可以从中运行命令,就像这样bash做一样。

这种哈希行为的另一个副作用是,如果您将可执行文件添加到csh搜索路径上的目录,csh则不会知道这一点。因此,假设您输入emacs/usr/local/bin位于您的搜索路径上)。然后你尝试运行emacs,然后...命令未找到。为了解决这个问题(不关闭散列),您可以运行rehash它,告诉csh我们构建一组新的散列表,它将拾取已添加的任何新内容。

相关内容