我在几个地方看到了使用以下 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
查看哪些失败。这应该可以提供有关“找不到文件”错误所指的线索。