推荐什么POSIX sh shebang
What is the recommended POSIX sh shebang
我读到,如果您想以便携方式使用 Bash,您应该使用 shebang:
#!/usr/bin/env bash
但现在我想知道:当我想明确声明我不依赖 Bash,而是写了一个 POSIX 兼容的脚本时,我应该使用:
#!/bin/sh
或者 #!/usr/bin/env sh
在这里也更可取吗?
正式视角
POSIX 规范的信息部分
sh:应用程序使用 状态
您不能依赖安装在 /bin/sh
.
的 sh
可执行文件
Applications should note that the standard PATH to the shell cannot be
assumed to be either /bin/sh or /usr/bin/sh, and should be
determined by interrogation of the PATH returned by
getconf
PATH, ensuring that the returned pathname is an absolute pathname and not
a shell built-in.
For example, to determine the location of the standard sh utility:
command -v sh
但是,不是建议使用 env
来使用适当的 PATH,
它建议 shell 脚本应该在安装时修改以使用
sh
:
的完整路径
Furthermore, on systems that support executable scripts (the "#!
"
construct), it is recommended that applications using executable scripts
install them using
getconf
PATH to determine the shell pathname and update the "#!
" script
appropriately as it is being installed (for example, with
sed).
在实践中
我主要编写 POSIX shell 脚本,实际上,每个 GNU/Linux 系统
(基于 Red Hat 和 Debian)——以及其他如 Cygwin 和 OS X——有一个
POSIX 兼容 sh
安装到 /bin/sh
或作为软件或
在这条路上很难link。我从来不需要使用 env
来迎合系统
其中 sh
不使用此路径。
可能有一些 Unix 系统的 POSIX 兼容 sh
不可用
作为 /bin/sh
。 POSIX 规范表明它可能安装在
一些系统为 /usr/xpg4/bin/sh
。据我了解,这是(曾经?)真实的
对于 Solaris 系统,其中 /bin/sh
是 Bourne shell 的早期版本
它早于 POSIX。在这种情况下,使用 env sh
不能保证有帮助,因为它仍然可以在 POSIX shell 之前找到 Bourne shell(在 /bin/sh
)在 /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
.
更容易失败
我会说 #!/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"
的命令将由最先出现的 sh
变为 运行在 PATH 中,其行为可能与 /bin/sh
不同。这是意外错误的潜在来源。 #!/usr/bin/env sh
shebang 解决了这个问题,因为所有命令都将由您的 PATH 中第一个 sh
运行。
#!/usr/bin/env sh
shebang 的唯一潜在缺点是 /usr
可能不会在调用脚本时挂载。但是,这在实践中不应该经常发生。可移植脚本中经常使用的外部程序,例如 awk
,也经常在 /usr/bin
中找到,因此可能很难确保脚本 运行s 与 /usr
正确反正卸载了。
如果你真的想要便携并且不依赖于 /usr
被安装,你可以开始你的脚本如下,以确保它总是由 sh
从 PATH 执行,无论在哪里它是:
#!/bin/sh
if test X"$SUBSHELL" != X"1"; then
SUBSHELL=1
export SUBSHELL
exec sh "[=11=]" "$@"
exit 1
fi
# ... your actual script comes here ...
但这似乎有点矫枉过正,所以我认为 #!/usr/bin/env sh
shebang 是一个合理的妥协。
我读到,如果您想以便携方式使用 Bash,您应该使用 shebang:
#!/usr/bin/env bash
但现在我想知道:当我想明确声明我不依赖 Bash,而是写了一个 POSIX 兼容的脚本时,我应该使用:
#!/bin/sh
或者 #!/usr/bin/env sh
在这里也更可取吗?
正式视角
POSIX 规范的信息部分
sh:应用程序使用 状态
您不能依赖安装在 /bin/sh
.
sh
可执行文件
Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH, ensuring that the returned pathname is an absolute pathname and not a shell built-in.
For example, to determine the location of the standard sh utility:
command -v sh
但是,不是建议使用 env
来使用适当的 PATH,
它建议 shell 脚本应该在安装时修改以使用
sh
:
Furthermore, on systems that support executable scripts (the "
#!
" construct), it is recommended that applications using executable scripts install them using getconf PATH to determine the shell pathname and update the "#!
" script appropriately as it is being installed (for example, with sed).
在实践中
我主要编写 POSIX shell 脚本,实际上,每个 GNU/Linux 系统
(基于 Red Hat 和 Debian)——以及其他如 Cygwin 和 OS X——有一个
POSIX 兼容 sh
安装到 /bin/sh
或作为软件或
在这条路上很难link。我从来不需要使用 env
来迎合系统
其中 sh
不使用此路径。
可能有一些 Unix 系统的 POSIX 兼容 sh
不可用
作为 /bin/sh
。 POSIX 规范表明它可能安装在
一些系统为 /usr/xpg4/bin/sh
。据我了解,这是(曾经?)真实的
对于 Solaris 系统,其中 /bin/sh
是 Bourne shell 的早期版本
它早于 POSIX。在这种情况下,使用 env sh
不能保证有帮助,因为它仍然可以在 POSIX shell 之前找到 Bourne shell(在 /bin/sh
)在 /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
.
我会说 #!/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"
的命令将由最先出现的 sh
变为 运行在 PATH 中,其行为可能与 /bin/sh
不同。这是意外错误的潜在来源。 #!/usr/bin/env sh
shebang 解决了这个问题,因为所有命令都将由您的 PATH 中第一个 sh
运行。
#!/usr/bin/env sh
shebang 的唯一潜在缺点是 /usr
可能不会在调用脚本时挂载。但是,这在实践中不应该经常发生。可移植脚本中经常使用的外部程序,例如 awk
,也经常在 /usr/bin
中找到,因此可能很难确保脚本 运行s 与 /usr
正确反正卸载了。
如果你真的想要便携并且不依赖于 /usr
被安装,你可以开始你的脚本如下,以确保它总是由 sh
从 PATH 执行,无论在哪里它是:
#!/bin/sh
if test X"$SUBSHELL" != X"1"; then
SUBSHELL=1
export SUBSHELL
exec sh "[=11=]" "$@"
exit 1
fi
# ... your actual script comes here ...
但这似乎有点矫枉过正,所以我认为 #!/usr/bin/env sh
shebang 是一个合理的妥协。