24

在以下意义上是否有一个最低限度的POSIX .2 兼容外壳(我们称之为它):mpcsh

如果mpcsh myscript.sh在我的(兼容的)系统上行为正确,那么对于任何兼容系统上xsh myscript.sh 的任何 POSIX.2 兼容 shell 的行为都将相同xsh。(“相同”到不太相关的事情,例如错误消息的措辞等)

破折号符合条件吗?

如果没有,有什么方法可以验证合规性myscript.sh吗?


编辑(9年后):

接受的答案仍然有效,但请查看此博客文章chackbashisms命令(来源)。避免 bashism 与编写符合 POSIX.2 的 shell 脚本不同,但它很接近。

4

5 回答 5

26

预先悲伤的答案

它不会帮助你(不像你期望的那样可靠和可靠)。


这就是为什么。

虚拟“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行为不符合标准,我明白为什么。措辞不仅不吉利,而且一开始就允许这样做也不是一个好主意。

在实践中,哪种行为是正确的并不重要,因为它们是“”“两个大壳”“”,人们会认为如果你不使用他们的扩展并且只使用它应该工作的符合 POSIX 的代码要么,但事实是,如果您依赖上面提到的一种或另一种行为,您的脚本可能会以可怕的方式中断。

示例 2 - 重定向

这是我几天前才了解到的,请在此处查看我的答案:

foo | bar 2>./qux | quux

常识和POLA告诉我,当命中下一行代码时,两者都quux应该bar已经完成​​运行,这意味着文件./qux已完全填充。对?不。

POSIX指出

如果管道不在后台(参见异步列表),shell 将等待管道中指定的最后一个命令完成,也可能等待所有命令完成。)

可以(!)等待所有命令完成!哇!

等待:

shell 在返回值之前等待管道中的所有命令终止。

没有:

每个命令(可能是最后一个命令除外)都作为单独的进程运行;shell 等待最后一个命令终止。

因此,如果您在管道之间使用重定向,请确保您知道自己在做什么,因为这会受到不同的处理,并且可能会在极端情况下严重中断,具体取决于您的代码。

我可以举另一个与管道无关的例子,但我希望这两个就足够了。

结论

有一个标准是好的,不断修改它更好,坚持它是很好的。但是,如果标准由于模棱两可或许可而失败,事情仍然会意外地破坏,实际上使标准的有用性无效。

这在实践中意味着,除了编写“符合 POSIX 的”代码之外,您还需要思考并知道您正在做什么以防止某些事情发生。

话虽如此,根据其手册页,一个尚未提及的 shellposh据说是 POSIX 加上比现有更少的扩展dash(主要echo -n是关键字):local

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。

于 2013-05-04T15:41:34.313 回答
5

可能最接近规范 shell 的是ashNetBSD 基金会和其他组织维护的。

这种外壳的下游变体称为dash更广为人知。

于 2013-01-15T15:49:14.177 回答
4

目前,没有单一的榜样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,但仍允许扩展。

于 2012-08-09T21:20:42.790 回答
2

POSIX 开发人员花了数年时间(毫不夸张地说)来解决这个问题:“应用程序符合标准意味着什么?” 虽然 POSIX 开发人员能够为标准(POSIX.1 和 POSIX.2)的实现定义一致性测试套件,并且可以将“严格符合应用程序”的概念定义为不使用超出强制元素的接口的概念在标准中,他们无法定义一个测试制度来确认特定应用程序“严格符合”POSIX.1,或者shell脚本“严格符合”POSIX.2。

最初的问题就是寻求这一点;验证脚本的一致性测试仅使用完全指定的标准元素。唉,该标准充满了放宽行为定义的“狡猾的词”,使得这样的测试对于任何显着有用性的脚本实际上是不可能的。(即使不考虑 shell 脚本可以生成和执行 shell 脚本的事实,这也是正确的,因此将“严格符合”的问题等同于停止问题。)

(全面披露:从 1988 年到 1999 年,我是 IEEE-CS TCOS(POSIX 系列标准的创建者)的工作成员和委员会负责人。)

于 2018-04-06T00:21:24.320 回答
1

如果没有,有什么方法可以验证 myscript.sh 的合规性吗?

这基本上是一个质量保证的案例。从...开始:

  • 代码审查
  • 单元测试(是的,我已经完成了)
  • 功能测试
  • 使用尽可能多的不同 shell 程序执行测试套件。( ash, bash, dash, ksh93, mksh, zsh)

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

编辑最近我偶然发现了rylnd/shpec - 一个用于你的 shell 代码的测试框架。您可以在测试用例中描述代码的功能,并指定如何验证它们。披露:我帮助它在 bash、ksh 和 dash 上运行。

于 2012-08-09T21:28:27.443 回答