Linux 使Unix shell脚本与POSIX兼容

Linux 使Unix shell脚本与POSIX兼容,linux,bash,shell,unix,sh,Linux,Bash,Shell,Unix,Sh,我一直在编写一个shell脚本来自动化一些任务。确保shell脚本在大多数平台上运行时不会出现任何问题的最佳方法是什么。例如,我一直在使用echo-n命令将一些消息打印到屏幕上,但没有尾随的新行,-n开关在某些ksh shell中不起作用。我被告知脚本必须符合POSIX。如何确保脚本与POSIX兼容。有工具吗?或者有一个shell只支持最低限度的POSIX要求吗?使用--POSIX命令行选项启动Bash,或者在Bash运行时执行'set-o POSIX',通过在Bash默认值不同的区域更改行为以

我一直在编写一个shell脚本来自动化一些任务。确保shell脚本在大多数平台上运行时不会出现任何问题的最佳方法是什么。例如,我一直在使用
echo-n
命令将一些消息打印到屏幕上,但没有尾随的新行,
-n
开关在某些ksh shell中不起作用。我被告知脚本必须符合POSIX。如何确保脚本与POSIX兼容。有工具吗?或者有一个shell只支持最低限度的POSIX要求吗?

使用--POSIX命令行选项启动Bash,或者在Bash运行时执行'set-o POSIX',通过在Bash默认值不同的区域更改行为以匹配POSIX指定的行为,将使Bash更加符合POSIX标准

POSIX 第一步是将shebang设置为
/bin/sh
,并分析脚本。这将为您指明哪些操作有效,哪些操作无效,以及原因。
例如,在shellcheck编辑器窗口中粘贴此脚本:

#!/bin/sh
read -r a b <<<"$1"
echo $((a+b))
还可以创建一个到
bash
zsh
的本地链接,使两者都像一个旧的
sh
shell。像这样:

$ ln -s /bin/bash ./sh
$ ./sh
有很多替代方案(dash、posh、lksh、bash、zsh等)来获得一个可以作为POSIX shell使用的shell

便携式 然而,即便如此,上述所有情况都不能确保“可移植性”

不幸的是,使shell脚本“POSIX兼容”通常比在任何真实shell上运行要容易

现实世界中唯一明智的建议是在几个shell中测试脚本。
就像上面的列表:dash、posh、lksh和bash——posix

Solaris是一个独立的世界,您可能需要针对/bin/sh和xpg4/sh进行测试

后续行动:

补充:

对于一种方法,考虑使用(我编写的一个实用程序),允许您使用多个shell同时调用给定的脚本或命令,并反馈脚本/命令成功执行的目标shell

如果您安装了Node.js,您可以使用
npm install-g shall
(如果没有,请按照上面链接到GitHub repo获取手动安装说明)轻松安装它,然后按如下方式使用它:

shall scriptFile
或者,使用特别命令:

shall -c '<shell-commands>'
在macOS上,
bash
(有效地)充当
sh
,虽然
echo-n
sh
一起使用时没有失败,但您也可以看到
-n
bash
sh
的身份运行时没有被识别为选项

另一个macOS示例显示,
bash
允许某些特定于bash的扩展,即使在作为
sh
运行时也是如此,例如使用非标准的
[…]
条件(假设在Ubuntu系统上充当
sh
dash是通过以下方式安装的):


正如您所看到的,Bash作为
sh
运行时仍然接受
[…]]
,而
dash
,这是一个(大部分)POSIX只提供shell功能的shell,失败了,因为POSIX只要求
[…]
条件(作为
测试…
命令的别名).

有一些很好的反馈。请记住,shell脚本可移植性(POSIX兼容性)问题的一部分是所使用的shell符号。问题的另一半是对POSIX命令使用可移植(POSIX兼容)选项,而不是意外地对POSIX命令使用GNU扩展。有时很难避免这样的问题。您还需要决定是否可以使用诸如Perl或Python之类的非POSIX工具。这很有帮助,但关键是:即使Bash在POSIX兼容模式下运行(例如,
[…]
条件,

shall -c '<shell-commands>'
$ SHELLS=sh,bash shall -c 'echo -n hi'
✓ sh (bash variant)                       [0.00s]
  -n hi

✓ bash                                    [0.00s]
  hi

OK - All 2 shells (sh, bash) report success.
$ SHELLS=sh,bash,dash shall -c '[[ -n nonempty ]] && echo nonempty'
✓ sh (bash variant)                       [0.00s]
  nonempty

✓ bash                                    [0.00s]
  nonempty

✗ dash                                    [0.01s]
  dash: 1: [[: not found

FAILED - 1 shell (dash) reports failure, 2 (sh, bash) report success.