Linux 使Unix shell脚本与POSIX兼容
我一直在编写一个shell脚本来自动化一些任务。确保shell脚本在大多数平台上运行时不会出现任何问题的最佳方法是什么。例如,我一直在使用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默认值不同的区域更改行为以
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.