如何测试Shell脚本的POSIX兼容性?


72

考虑到POSIX是所有unice中最通用的标准,我很想知道是否有专门支持它的shell。尽管大多数现代Shell提供对POSIX的支持(并且可以毫无问题地运行POSIX兼容脚本),但它们在指出不兼容功能方面表现不佳。

是否有仅实现POSIX和POSIX的外壳,以至于它会为任何不兼容的功能抛出错误?

编辑我想澄清的是,我并不是在寻求有关编写可移植Shell脚本的一般提示。评论中提到的相关问题已经解决了这一问题。当我发现bash有一个--posix选择但只发现它只影响某些初始化行为时,我想到了这个问题,而这并不是我要寻找的。



@Gilles:也许我应该提到我确实遇到了这个问题,但是只有一个答案建议使用进行测试dash。我提到可移植性是我提出问题的一般背景,但这并不是其真正意图。
rahmu 2012年

当然,我希望将两个问题联系起来,因为它们可能是同一个人感兴趣的。它们绝不是重复的。顺便说一下,与dash相比,posh是一种更好的POSIX合规性测试。
Gilles 2012年

2
busybox非常接近POSIX和POSIX。让您绊倒的一件事是,如果您还安装了其他软件包(例如diffutils),则可能会添加功能。检出alpine linux的livecd,它会从纯busybox环境开始。Alpine使用musl C库,因此您不会获得可以添加诸如扩展正则表达式之类的功能的GNU扩展。
Michael Fox

Answers:


37

不幸的是,对于shell脚本,“可移植”通常比“符合POSIX”更强。也就是说,编写可以在任何POSIX shell上运行的东西并不难,但是要使其在任何实际的shell上运行更困难。

您可以从在软件包管理器中安装每个外壳开始,尤其posh是您想要的debian 声音(符合政策的普通外壳)。Debian的策略是POSIX,但有一些例外(echo -n指定,local...)。

除此之外,测试还必须涵盖一系列平台上的几个shell(尤其是/ bin / sh)。我在Solaris(/ bin / sh和xpg4 / sh)和BSD上进行测试。AIX和HP-UX非常兼容,不会造成问题。bash本身就是一个小世界。

向便携式外壳推荐Autoconf指南,这绝对是精妙的,可以节省很多时间。它的很大一部分已过时,但这没关系;如果您不在乎,请跳过TruUnix和Ultrix,依此类推!


posh确实听起来像我要的。我会尽快做一些测试。
rahmu 2012年

1
在找到相关问题之前,我已经回答了!posh是debian的事情,因此不会在所有系统上打包。另外,shell不一定是最需要担心的事情。例如,sed不兼容是一个大问题。
尼古拉斯·威尔逊

我不会麻烦移植到Solaris / bin / sh aka Bourne shell(不是POSIX)。像所有现代Unix系统Solaris提供了一个POSIX外壳,它只是碰巧不处于通常的位置(在/ usr / XPG4 / bin / sh的)
斯特凡Chazelas

可悲的是,我们发布的脚本必须至少在每个/ bin / sh上运行。它并不像所有的那样糟糕...我宁可不必这样做。
尼古拉斯·威尔逊

2
我将/ bin / sh视为重要的原因是因为它在许多脚本中都是从shebang调用的。“ / usr / bin / env sh”几乎没有改进。如果您要尽一切努力在非POSIX shell上运行某些东西,我觉得我也应该优先考虑每个系统的/ bin / sh。不久之后,一些客户便会使用默认外壳程序运行脚本,这并非没有道理。
尼古拉斯·威尔逊

28

您可以将ShellCheck(GitHub)用作shell脚本的子类。还有一个在线版本

要检测POSIX兼容性问题(例如SC2039),您的shell脚本的shebang行应为#!/bin/sh。您也可以传递--shell=shshellcheck

范例(test.sh):

#!/bin/sh
if [[ $HOSTNAME == test ]]; then
    echo fail &> foo
fi

结果(shellcheck test.sh):

In test.sh line 2:
if [[ $HOSTNAME == test ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is undefined.
      ^-- SC2039: In POSIX sh, HOSTNAME is undefined.    

In test.sh line 3:
    echo fail &> foo
              ^-- SC2039: In POSIX sh, &> is undefined.

1
这些年来,我从未听说过ShellCheck ...感谢您的链接!
Ton van den Heuvel

有史以来最好的工具!特别是拥有它的在线版本非常棒,可以快速检查一段代码!
梅基

12

如果POSIXLY_CORRECT设置了环境变量,则Bash将以POSIX兼容模式运行。从联机帮助页:

   POSIXLY_CORRECT
          If  this  variable  is  in the environment when bash starts, the
          shell enters posix mode before reading the startup files, as  if
          the  --posix  invocation option had been supplied.  If it is set
          while the shell is running, bash enables posix mode, as  if  the
          command set -o posix had been executed.

许多其他GNU实用程序也将兑现POSIXLY_CORRECT,因此,如果您使用的系统主要是GNU工具(例如大多数Linux系统),那么如果您的目标是POSIX一致性,那么这是一个好的开始。


21
即使在POSIX模式下,bash仍将允许某些非POSIX功能,例如[[
jordanm 2012年
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.