如何测试 shell 脚本的 POSIX 合规性?

如何测试 shell 脚本的 POSIX 合规性?

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

是否有任何 shell 只实现 POSIX 和 POSIX,这样它就会针对任何不兼容的功能抛出错误?

编辑我想澄清的是,我并不是要求提供编写可移植 shell 脚本的一般技巧。评论中提到的相关问题已经涵盖了这一点。当我发现bash有一个--posix选项但只是发现它只影响一些初始化行为时,我想到了这个问题,这并不完全是我想要的。

答案1

您可以使用ShellCheck (GitHub)作为 shell 脚本的 linter。还有一个网络版

检测 POSIX 兼容性问题(例如SC2039), 这舍邦线你的 shell 脚本应该是#!/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.

答案2

不幸的是,对于 shell 脚本来说,“可移植”通常是比“POSIX 兼容”更严格的要求。也就是说,编写在任何 POSIX shell 上运行的东西并不太难,但让它在任何现实世界的 shell 上运行就更难了。

您可以从在包管理器中安装每个 shell 开始,特别是 debian 的posh听起来像您想要的(符合策略的普通 SHell)。 Debian 的政策是 POSIX,但有一些例外(echo -n指定的,local...)。

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

我会推荐Autoconf 便携式 shell 指南,这绝对很棒并且节省了大量时间。其中很大一部分已经过时了,但这没关系;如果您不在乎,请跳过 TruUnix 和 Ultrix 等!

答案3

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,那么这是一个良好的开始。

答案4

是否有任何 shell 只实现 POSIX 和 POSIX,这样它就会针对任何不兼容的功能抛出错误?

短跑符合这里的要求。

DASH 是符合 POSIX 标准的实现,/bin/sh其目标是尽可能小。它在尽可能不牺牲速度的情况下做到这一点。事实上,对于大多数任务来说,它比 bash(GNU Bourne-Again SHell)要快得多。

编写 shell 脚本时应符合POSIX Shell 命令语言,我在测试脚本时使用 Dash 作为解释器,因为它仅实现 POSIX shell 功能,并且如果遇到任何 Bashism(例如数组变量或进程替换),则会抛出错误。

Dash 是 Almquist shell 的一个端口(因此得名 Debian Almquist shell),在基于 Debian 的系统上,/bin/sh它是/bin/dash.有关更多信息,请参阅阿尔姆奎斯特外壳 - 维基百科

相关内容