为什么POSIX要求某些Shell内置程序具有外部实现?


18

这个关于printf是否是yash内置的问题开始这个答案引用了POSIX标准

答案指出,POSIX搜索序列是查找所需命令的外部实现,然后,如果外壳将其实现为内置程序,则运行内置程序。(对于不是特殊内置的内置。)

为什么POSIX在允许运行内部实现之前对存在外部实现有此要求?

似乎……随心所欲,所以我很好奇。


我相信这是启用/禁用内置功能的一种方式(如果需要/需要)。
艾萨克

2
通过删除外部实现来禁用内置功能?现在没有printf可用的名称命令。
studog

@studog,因此创建一个与内置文件同名的空文件,打开执行位,并将其放在PATH中的目录中。:P
通配符

@Wildcard严格兼容的shell在搜索时会看到名称PATH,然后调用内置实用程序,而不是外部脚本。如果您想在路径中调用外部脚本怎么办?嗯...这似乎需要一张描述不同可能性的表格。有一个在这里,但它没有道理给我。
库萨兰达

@Kusalananda,您的第一句话,这就是我的意思。因此,为什么我说要创建一个文件。
通配符

Answers:


15

这是一个“好像”规则。

简而言之:如果实现决定使标准的外部命令也可以作为内置的shell使用,则用户看到的shell行为不应更改。

我在/unix//a/496291/5132上显示的对比了PD Korn,MirBSD Korn和Heirloom Bourne壳(一方面)的行为之间的;(另一方面)Z,93 Korn,Bourne Again和Debian Almquist炮弹;渡边贝壳(在紧握的手上)突出了这一点。

对于不具备壳printf作为内置,消除/usr/bin来自PATH使得调用printf停止工作。Watanabe外壳以其一致性模式显示的POSIX一致性行为导致相同的结果。具有printf内置Shell的行为就像是在调用外部命令一样。

如果/usr/bin从中删除所有不符合条件的Shell的行为都不会改变PATH,并且它们的行为也不像调用外部命令那样。

该标准试图向您保证的是,shell可以内置各种正常的外部命令(或将其实现为自己的shell函数),并且您仍然会从内置程序中获得与您相同的行为如果要调整PATH以阻止找到命令,请使用外部命令。 PATH仍然是您选择和控制可以调用的命令的工具。

(如/unix//a/448799/5132所述,几年前,人们通过更改内容来选择Unix的个性PATH。)

人们可能会认为,使该命令始终起作用,无论是否可以找到它PATH 实际上是使通常的外部命令内置的关键所在。(这就是为什么我的NOSH工具集,只是获得了一个内置printenv的1.38版本的命令,实际上,虽然这是 shell。)

但是该标准为您提供了保证,使您可以看到不在shell 上的常规外部命令的行为与从其他调用该函数的非shell程序中看到的行为相同,并且shell不能神奇地运行(显然)其他程序无法找到的普通外部命令。从用户的角度来看,一切都是自洽的,并且是控制其工作方式的工具。PATHexecvpe()PATHPATH

进一步阅读


13

这是很荒谬的,这就是为什么没有shell在其默认模式下实现它的原因。

该标准的基本原理及其说明性示例表明,这是使常规内置文件与路径相关联的拙劣尝试,并让用户通过在其之前出现自己的二进制文件来覆盖它PATH(例如printf,与之相关联的内置文件)。/usr/bin/printf可以/foo/bin/printf通过设置PATH=/foo/bin:$PATH)由外部命令覆盖。

但是,该标准并没有最终要求这样做,而是完全不同的东西(并且也无用和意外)。

您可以在此错误报告中阅读有关它的更多信息。从最后接受的文本中引述:

许多现有的实现无需执行PATH搜索即可执行常规的内置命令。此行为与标准文本不匹配,并且不允许脚本作者通过特制的PATH覆盖常规的内置实用程序。此外,基本原理还解释了其目的是允许作者 通过修改PATH 覆盖内置函数,但这不是规范性文本所说的

FWIW,我认为也没有任何外壳可以实现接受文本中的修订要求。


另请参见article.gmane.org/gmane.comp.standards.posix.austin.general/…上的讨论(还有其他一些讨论)。
斯特凡Chazelas


不,(例如通过设置PATH = / foo / bin:$ PATH,可被/ foo / bin / printf外部命令覆盖与/ usr / bin / printf关联的内置printf)。,那是不正确的。的任一存在/两者/任何的/usr/bin/printf/foo/bin/printf在PATH将激活内置的printf。缺少(在PATH中)外部printf函数唯一要做的就是禁用内置函数。(按规格书字母)。
艾萨克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.