Linux

當僅執行目錄時,PATH 在 bash 和 csh 中的行為不同?

  • October 20, 2020

我們在各種子目錄中有一些應用程序,我們限制了 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

現在從 bash shell 我(“chem”組的成員)可以將此目錄添加到我的路徑並執行 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 下進行了這些測試,兩種情況下的行為都是相同的。

bash每次執行命令時都會搜尋 $PATH 中的每個目錄(從第一個到最後一個),並嘗試從該目錄中執行該命令。它要麼成功,要麼失敗。因此,如果/tmp/dir1在您的 $PATH 中,並且a.out在該目錄中,您可以嘗試執行a.out-bash將嘗試執行/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,並且…找不到命令。為了解決這個問題(不關閉散列),你執行rehashwhich 告訴csh去建構一組新的散列表,它會在上面拾取任何新添加的東西。

引用自:https://unix.stackexchange.com/questions/615554