我已经读到,如果您想以便携式方式使用Bash,则应该使用shebang:
#!/usr/bin/env bash
但是现在我在想:当我想明确声明我不依赖Bash时,而是写了一个POSIX兼容脚本,应该使用:
#!/bin/sh
还是#!/usr/bin/env sh
在这里也是可取的?
答案 0 :(得分:6)
POSIX specification for
sh: Application Usage状态的信息部分
您不能依靠sh
上安装的/bin/sh
可执行文件。
应用程序应注意,shell的标准 PATH 不能为 假定为 / bin / sh 或 / usr / bin / sh ,并且应为 通过查询由 PATH 返回的值确定 getconf PATH ,确保返回的路径名是绝对路径名,而不是绝对路径名 内置的外壳。
例如,确定标准sh实用程序的位置:
command -v sh
但是,与其建议使用env
来使用适当的PATH,
它建议应在安装时修改shell脚本以使用
sh
的完整路径:
此外,在支持可执行脚本(“
#!
构造),建议应用程序使用可执行脚本 使用安装它们 getconf PATH 确定外壳程序路径名并更新“#!
”脚本 适当地安装它(例如, sed。
我主要编写POSIX Shell脚本,实际上,每个GNU / Linux系统都编写
(基于Red Hat和Debian的操作系统)以及其他诸如Cygwin和OS X的操作系统,
符合POSIX的sh
已安装到/bin/sh
或作为软件或软件提供
这条路径上的硬链接。我从不需要使用env
来满足系统需求
sh
不使用此路径的地方。
在某些Unix系统上,可能没有符合POSIX的sh
为/bin/sh
。 POSIX规范建议将其安装在
某些系统为/usr/xpg4/bin/sh
。据我了解,这是真的吗?
对于其中/bin/sh
是Bourne shell的早期版本的Solaris系统
早于POSIX。在这种情况下,不能保证使用env sh
会有所帮助,因为它仍然可以在/bin/sh
的POSIX外壳之前找到Bourne外壳(在/usr/xpg4/bin/sh
处)。
如果您要为常见的Unix和Linux操作编写POSIX Shell脚本
系统,只需使用#!/bin/sh
作为shebang。
在极少数情况下,/bin/sh
是Bourne Shell而不是POSIX兼容的
Shell,则必须修改shebang以使用适当的完整路径
到POSIX shell。
在两种情况下,使用#!/usr/bin/env sh
都没有好处–
比仅使用#!/bin/sh
更有可能失败。
答案 1 :(得分:0)
我想说#!/usr/bin/env sh
是可取的。
一些可移植的结构,例如the loop over the results of find
,要求sh
被显式调用。考虑以下脚本:
#!/bin/sh
# ... some commands here ...
find . -exec sh -c '
for file do
# ... commands processing "$file" ...
done' find-sh {} +
开头的命令将由/bin/sh
运行,处理"$file"
的命令将由PATH中第一个出现的sh
运行,其行为可能与{ {1}}。这是意外错误的潜在来源。 /bin/sh
shebang解决了这个问题,因为所有命令都将由PATH中首先出现的#!/usr/bin/env sh
运行。
sh
shebang的唯一潜在缺点是,调用脚本时可能不会挂载#!/usr/bin/env sh
。但是,这在实践中不应该经常发生。在/usr
中也经常发现可移植脚本中经常使用的外部程序,例如awk
,因此可能很难确保在卸载了/usr/bin
的情况下正确运行脚本。>
如果您真的想携带并且不依赖于挂载/usr
,则可以按如下所示开始脚本,以确保始终由PATH中的/usr
执行该脚本。 :
sh
但这似乎有点过大,所以我想说#!/bin/sh
if test X"$SUBSHELL" != X"1"; then
SUBSHELL=1
export SUBSHELL
exec sh "$0" "$@"
exit 1
fi
# ... your actual script comes here ...
shebang是一个合理的折衷方案。