我在幾個地方看到了使用以下 shebang 行的建議
#!/usr/bin/env bash
代替
#!/usr/bin/bash
我下意識的反應是,“如果有人用這個可執行檔替換他們自己的可執行檔怎麼辦~/.local/bin
?”此目錄通常設定在系統範圍路徑之前的使用者路徑中。我認為這是一個安全問題,通常作為旁注而不是任何值得認真對待的問題,但我想測試這個理論。
為了嘗試這個我做了這樣的事情:
echo -e "#!/usr/bin/python\nprint 'Hacked!'" > $HOME/.local/bin/bash
chmod 755 $HOME/.local/bin/bash
PATH=$HOME/.local/bin env bash
這產生
/usr/bin/env: ‘bash’: No such file or directory
為了檢查它是否拾取了任何東西,我也做了
echo -e "#!/usr/bin/python\nprint 'Hacked!'" > $HOME/.local/bin/perl
chmod 755 $HOME/.local/bin/perl
PATH=$HOME/.local/bin env perl
正如我所料,它會列印出
Hacked!
有人可以跟我解釋為什麼bash
沒有找到替代品,但找到替代品了perl
嗎?這是某種「安全」措施(從我的角度來看)沒有抓到重點嗎?
編輯:因為有人提示我:我不是問/usr/bin/env bash
與使用有何不同/bin/bash
。我正在問如上所述的問題。
EDIT2:這一定是我做錯了什麼。今天再次嘗試(使用顯式路徑env
而不是隱式路徑),沒有出現這種「未找到」行為。
答案1
「如果有人用 ~/.local/bin 中的這個執行檔取代自己的執行檔怎麼辦?
那麼這個腳本對他們就不起作用了。
但這並不重要,因為他們可以透過其他方式自行破壞腳本,或者直接運行另一個程式而不會弄亂PATH
或env
。
除非你的用戶有其他使用者的目錄PATH
,或可以編輯PATH
其他使用者的目錄,實際上不可能一個使用者弄亂另一個使用者。
但是,如果它不是 shell 腳本,而是授予額外權限的腳本,例如某些程式的 setuid 包裝器,那麼情況就會有所不同。在那種情況下,那就是必要的使用絕對路徑運行程序,請將其放置在非特權使用者無法修改的目錄中,並在啟動程序時清理環境。
答案2
至於 shell 和 之間的行為差異perl
,perl
與 shell 檢查第一行以確定要執行的內容不同:
$ cat tcl
#!/usr/bin/env tclsh
puts "TCL running as [pid]"
$ perl tcl
TCL running as 39689
$ cat sbcl
#!/opt/local/bin/sbcl --script
(format t "~a running as ~a~%" 'lisp (sb-unix:unix-getpid))
$ perl sbcl
LISP running as 39766
$
此功能的用途包括用 Perl 以外的其他語言編寫測試因此,人們可以使用其他語言編寫與 TAP 相容的腳本,並且prove
可以正確地執行它們。
答案3
這裡沒有安全風險。/usr/bin/env
應該根據使用者的環境選擇合適的二進位。因此,如果使用者bash
在 中安裝了自己的~/.local/bin
版本,那麼/usr/bin/env
確實應該嘗試使用它(例如,他們可能編譯了一個具有系統範圍版本中不可用的額外功能的版本,並且更願意在系統範圍版本的位置)。對於任何其他二進制/解釋器也是如此。不存在安全風險,因為用戶將無法運行任何他們本來無法運行的內容。
至於為什麼替代品在你的情況下失敗,我懷疑它與/usr/bin/env
.嘗試運行PATH=~/.local/bin bash
(PATH=~/.local/bin bash <path-to-script>
運行腳本時會呼叫它)並PATH=~/.local/bin /usr/bin/env bash
查看哪些失敗。這應該可以提供有關“找不到文件”錯誤所指的線索。