是否有最低限度的POSIX. 2兼容shell?

imzjd6km  于 2022-11-16  发布在  Shell
关注(0)|答案(5)|浏览(191)

在以下意义上,是否存在至少符合POSIX.2的shell(我们称之为mpcsh):
如果mpcsh myscript.sh在我的(兼容的)系统上运行正常,那么xsh myscript.sh在任何兼容系统上的任何POSIX. 2兼容shell xsh上的运行都是相同的。(“相同”指不太相关的内容,如错误消息的措辞等。)
dash是否符合条件?
如果不是,是否有任何方法可以验证myscript.sh的合规性?
编辑(9年后):
公认的答案仍然有效,但请看一下this blog postcheckbashisms命令(source)。避免bashisms与编写符合POSIX. 2的shell脚本不同,但它很接近。

dw1jzc5e

dw1jzc5e1#

悲伤的答案提前
它不会帮助你(没有你期望的那么多和可靠)。
原因如下。
虚拟“POSIX shell”无法解决的一个大问题是,标准中的措辞含糊不清或没有解决,因此shell可能会以不同的方式实现,同时仍然遵守标准。
以下面两个关于管道的例子为例,其中第一个例子是众所周知的:

示例1 -范围界定

$ ksh -c 'printf "foo" | read s; echo "[${s}]"'
[foo]

$ bash -c 'printf "foo" | read s; echo "[${s}]"'
[]

ksh在当前shell中执行管道的最后一个命令,而bash在子shell中执行所有命令(包括最后一个命令)。bash 4引入了lastpipe选项,使其行为类似于ksh

$ bash -c 'shopt -s lastpipe; printf "foo" | read s; echo "[${s}]"'
[foo]

所有这一切都是(值得商榷地)根据标准:
此外,多命令流水线的每个命令都处于子 shell 环境中;然而,作为扩展,可以在当前环境中执行流水线中的任何或所有命令。
我不能100%确定 extension 是什么意思,但是基于文档中的其他示例,这并不意味着shell必须提供一种在行为之间切换的方式,而只是它可以,如果它希望这样的话,其他人对此有不同的理解,他们认为ksh的行为不符合标准,我知道为什么。不仅措辞不吉利,而且一开始就允许这样做也不是一个好主意。
在实践中,哪种行为是正确的并不重要,因为这是“两个大 shell “,人们会认为,如果您不使用它们的扩展,而只使用据说符合POSIX的代码,它将在其中任何一个中工作,但事实是,如果您依赖上面提到的一种或另一种行为,您的脚本可能会以可怕的方式中断。

示例2 -重定向

这是我几天前才知道的,请看我的答案here

foo | bar 2>./qux | quux

常识和POLA告诉我,当下一行代码被命中时,quuxbar应该都已经完成了运行,这意味着文件./qux已经完全填充了。
POSIX声明
如果管道不在后台(请参阅异步列表),则 shell 将等待管道中指定的最后一个命令完成,也可能等待所有命令完成。)

  • 可以 *(!)等待所有命令完成!WTH!

bash等待:
Shell会等待管道中的所有命令终止,然后再返回值。
ksh不会:
每个命令(可能最后一个命令除外)都作为单独的进程运行; shell将等待最后一个命令终止。
因此,如果您在管道之间使用重定向,请确保您知道自己在做什么,因为这是不同的处理方式,并且可能会在边缘情况下严重中断,具体取决于您的代码。
我可以再给予一个与管道无关的例子,但我希望这两个例子就足够了。
结论
有一个标准是好的,不断修订它更好,坚持它是伟大的。但如果标准失败,由于模糊或许可的事情仍然可以意外打破实际上使标准的有用性无效。
这在实践中意味着,除了编写“符合POSIX”的代码之外,您还需要思考和了解您正在做什么来防止某些事情发生。
话虽如此,还有一个shell尚未提及,那就是posh,它应该是POSIX加上比dash更少的扩展(主要是echo -nlocal关键字),根据其手册页:

BUGS
   Any bugs in posh should be reported via the Debian BTS.
   Legitimate bugs are inconsistencies between manpage and behavior,
   and inconsistencies between behavior and Debian policy
   (currently SUSv3 compliance with the following exceptions:
   echo -n, binary -a and -o to test, local scoping).

YMMV公司。

8hhllhi2

8hhllhi22#

可能是最接近canonical shell is ash的东西,它由NetBSD基金会和其他组织维护。
这种shell called dash的下游变体更为人所知。

0pizxfdo

0pizxfdo3#

目前,POSIX shell没有单一的 * 榜样 *。
自最初的Bourne shell以来,POSIX shell采用了许多附加功能。
我所知道的实现这些特性的所有shell都具有超出POSIX shell特性集的扩展。
例如,POSIX允许使用以下格式的算术表达式:

var=$(( expression ))

但它不允许等效的:

(( var = expression ))

bashksh93支持。
我知道bash有一个set -o posix选项,但这不会禁用任何扩展。

$ set -o posix
$ (( a = 1 + 1 ))
$ echo $a
2

据我所知,ksh93试图符合POSIX开箱即用,但仍然允许扩展。

xwbd5t1u

xwbd5t1u4#

POSIX开发人员花了数年时间(毫不夸张地说)来解决这个问题:“应用程序符合标准意味着什么?”尽管POSIX开发人员能够为标准(POSIX. 1和POSIX. 2)的 * 实现 * 定义一致性测试套件,并且能够将“严格符合标准的应用程序”的概念定义为不使用超出标准强制元素的接口的应用程序,他们无法定义一个测试机制来确认一个特定的应用程序“严格符合”POSIX.1,或者一个shell脚本“严格符合”POSIX.2。
原来的问题寻求的只是;一致性测试验证脚本只使用标准中完全指定的元素。2可惜的是,标准中充满了放松行为定义的“黄鼠狼话”,使得这样的测试实际上不可能对任何有效级别的脚本进行。(即使不考虑shell脚本可以生成和执行shell脚本这一事实,从而使“严格相容”问题等价于停止问题。)
(Full披露:1988-1999年,我是POSIX系列标准的创建者IEEE-CS TCOS的工作成员和委员会领导人。)

rhfm7lfc

rhfm7lfc5#

如果没有,是否有任何方法来验证myscript.sh?
这基本上是一个质量保证案例。从以下内容开始:

  • 程式码检阅
  • 单元测试(是的,我已经完成了)
  • 功能测试
  • 使用尽可能多的不同shell程序执行测试套件。(ashbashdashksh93mkshzsh

就我个人而言,我的目标是bashksh93支持的通用扩展集,它们是最古老、最广泛使用的shell语言解释器。

EDIT最近我偶然发现了rylnd/shpec-一个shell代码的测试框架。你可以在测试用例中描述你的代码的特性,并指定如何验证它们。披露:我帮助它在bash、ksh和dash之间工作。

相关问题