我正在与一位同事讨论:在 shell 脚本(例如安装脚本、cronjob 等)中显式指定命令的完整路径是否更好,甚至是否需要?
例如,脚本的用户可能已经设置了他们的系统(或者已经被黑客攻击(在这种情况下,可以说所有的赌注都被取消了)),这样在他们的系统的其他地方存在同名的命令并且被发现其命令搜索路径早于脚本所依赖的命令,可能会产生意外或不利的结果。
是否值得指定完整路径以确保脚本使用预期的命令,或者这只是想太多?
答案1
这是依赖于上下文的,两种选择都有其优点和缺点。总的来说,我会避免使用绝对路径,除非您有非常具体的理由这样做。
使用PATH环境变量调用
调用命令而不指定其绝对路径(IE 使用它们在PATH
目录中的存在)可以使脚本更可移植。对于 中的程序来说,这可能不太可能成为问题,/bin
但对于您期望使用的任何命令来说,这绝对是正确的/usr/bin
。不同的系统可以将它们放在各种位置,例如/opt
或/snap
。
更糟糕的是,用户可以出于多种不同原因配置其路径。这可能包括安装多个 java 运行时或 python 版本等。因此,任何调用java
几乎都不应该是/usr/bin/java
因为系统管理员可能安装了与您的脚本不兼容的版本。允许用户选择要使用的 java 版本至关重要。
另一个例子是某些发行版不一定遵循您期望的约定。事实上,Archlinux 已将/bin
/sbin
/usr/bin
/usr/sbin
所有内容捆绑到一个目录中,并带有指向其他目录的符号链接(看这里)。这应该是向后兼容的,但它表明某些标准并不像您想象的那样普遍。
请注意,诸如此类的工具须藤对内置的 PATH 环境变量有特定的保护,因此即使您不指定绝对路径,通常也可以安全地假设需要使用 sudo 运行的脚本是安全的。
使用绝对路径调用
通常,只有在有非常具体的原因时才使用绝对路径。
使用绝对路径的主要优点是您可以更好地控制正在运行的命令。您可以在此处安装特定的替代工具,这些工具旨在覆盖用户指定的路径。
你已经指出了安全问题。有很多方法可以做到这一点,但正如所指出的,sudo
执行的命令很少会成为问题。
你提到了 cron 脚本。著名的 cron 的 PATH 环境变量有一个问题,因为它通常没有按照您的预期设置(看这里)。我过去曾编写过带有绝对路径的脚本,以便与 cron 一起使用。这更多是因为我不信任安装它的系统管理员。我的偏好始终是使用设置良好的 PATH 来运行 cron 作业,而不是脚本中的绝对路径。
答案2
除了接受的答案之外,我想添加使用绝对路径的另一个效果:防止使用 shell 内置命令。
例如:
echo
:shell 将使用内置echo
命令,或回echo
退到PATH
./bin/echo
:强制shell使用这个程序,这比内置命令的成本稍高。
请参阅列表Bash 中的其他内置命令。
话虽如此,关于内置命令的两个问题:
POSIX允许shell 将标准命令实现为内置命令“提高常用实用程序的性能或实现在单独环境中更困难的功能”,虽然标准期望执行内置函数仅有的如果外部命令在搜索中可用PATH
,在许多实现中似乎并非如此。
此外,内置实现并不总是符合标准。例如,POSIX 鼓励printf
而不是echo
因为后者不太便携。
编辑:更新了有用的信息一角中。