舍邦和路径

舍邦和路径

为什么 shebang 需要一条路径?

错误的

#!ruby

正确的

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

操作系统应该具有有关已注册命令的路径的信息,为什么它仍然期望给出它?

答案1

可能是为了让内核更简单。我认为内核不会搜索您的路径来查找可执行文件。这是由 C 库处理的。 #!处理在内核中完成,不使用标准 C 库。

另外,我认为内核不知道你的路径是什么。 $PATH是一个环境变量,只有进程才有环境。内核没有。我想它可以访问执行执行的进程的环境,但我认为内核中当前没有任何东西可以访问这样的环境变量。

答案2

您可以PATH使用 获得搜索语义env,因此:

#!/usr/bin/env ruby  

有你想要的语义

#!ruby

依赖PATH不被认为是良好实践的原因是脚本无法对 PATH 环境变量的内容做出任何假设,从而破坏了二进制文件的“顺序依赖模型”,其中

  1. /bin包含启动时所需的可执行文件;
  2. /usr/bin包含操作系统安装使用的其他可执行文件;
  3. /usr/local/bin包含由系统管理员安装的不属于基本操作系统的可执行文件。
  4. ~/bin包含用户自己的可执行文件。

每个级别不应假定序列中较晚的二进制文件存在,这些二进制文件更“应用”,但可能依赖于较早的二进制文件,这些二进制文件更“基础”。而PATH变量往往是从应用性走向基础性,这与上面的自然依赖关系是相反的方向。

为了说明这个问题,问问自己,如果 in 中的脚本调用了Ruby~/bin中的脚本,会发生什么?/usr/local/bin该脚本应该取决于操作系统安装的版本/usr/bin/ruby,还是取决于用户碰巧拥有的个人副本~/bin/rubyPATH搜索给出了与后者相关的不可预测的语义(可能~/bin/ruby是一个损坏的符号链接),而在路径中烘焙#!给出​​了前者。

实际上没有任何其他独立于平台的“操作系统......有关注册命令的路径的信息”,因此最简单的事情是坚持#!.

答案3

我相信这样您就可以根据需要或想要指定一名备用口译员。例如:

#!/home/user/myrubyinterpreter

更常见于 shell 脚本:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh

答案4

还有其他原因,但从安全角度来看,我永远不希望脚本对正确路径做出假设。如果错误并且运行了错误的 shell 或解释器怎么办?是由恶意用户插入的吗?或者如果它依赖于特定的 shell,并且如果使用错误的 shell 就会崩溃怎么办?

用户可能会弄​​乱他们的路径并破坏东西 - 不要信任用户:-) 我进行了多次攻击,这些攻击依赖于用户在他们的路径上做错误的事情 - 通常以错误的顺序得到东西 - 所以我可以颠覆正常的脚本调用。

是的,我知道如果您自己编写了脚本,您可以完全正确地声称您已经整理出自己的路径,但解释器无法做出这些决定。

相关内容