推荐的POSIX sh shebang是什么

时间:2018-11-02 09:51:31

标签: shell sh posix

我已经读到,如果您想以便携式方式使用Bash,则应该使用shebang:

#!/usr/bin/env bash

但是现在我在想:当我想明确声明我不依赖Bash时,而是写了一个POSIX兼容脚本,应该使用:

#!/bin/sh

还是#!/usr/bin/env sh在这里也是可取的?

2 个答案:

答案 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是一个合理的折衷方案。