什么时候必须使用#!/bin/bash,什么时候必须使用#!/bin/sh?

什么时候必须使用#!/bin/bash,什么时候必须使用#!/bin/sh?

什么时候比在 shell 脚本中#!/bin/bash更合适?#!/bin/sh

答案1

简而言之:

  • 有几种 shell 实现了POSIX sh 规范。在不同的系统上,/bin/sh可能是指向 ash、bash、dash、ksh、zsh 等的链接。(但它始终与 sh 兼容 - 永远不会与 csh 或 fish 兼容。)

  • 只要您坚持使用sh功能,您就可以(甚至应该)使用,#!/bin/sh并且脚本应该可以正常工作,无论它是哪个 shell。

  • 如果你开始使用 bash 特有的功能(例如数组),你应该特别请求 bash - 因为即使/bin/sh已经在你的系统,它可能无法其他人的系统,您的脚本将不会在那里运行。(当然,这同样适用于 zsh 和 ksh。)您可以使用外壳检查来识别暴力倾向。

  • 即使脚本仅供个人使用,您也可能会注意到某些操作系统/bin/sh在升级过程中会发生变化 - 例如,在 Debian 上它曾经是 bash,但后来被非常小的 dash 取代。使用 bashisms 的脚本#!/bin/sh突然中断了。

然而:

  • Even#!/bin/bash不太正确。在不同的系统中,bash 可能位于/usr/bin/usr/pkg/bin或 中/usr/local/bin

  • 更可靠的选择是#!/usr/bin/env bash,它使用 $PATH。(尽管该env工具本身也没有严格保证,但/usr/bin/env仍可以在更多系统上运行/bin/bash。)

答案2

使用与您实际用于开发和调试脚本的 shell 相对应的 shebang。例如,如果您的登录 shell 是bash,并且您在终端中将脚本作为可执行文件运行,请使用#!/bin/bash。不要仅仅假设因为您没有使用数组(或bash您知道的任何功能),所以您可以安全地选择您喜欢的任何 shell。shell 之间存在许多细微的差异(echo、函数、循环,随便什么都可以),如果不进行适当的测试,就无法发现这些差异。

考虑一下:如果你离开#!/bin/bash并且你的用户没有它,他们会看到一个明确的错误消息,例如

Error: /bin/bash not found

大多数用户可以通过安装适当的软件包在一分钟内修复此问题。另一方面,如果您用 替换 shebang并在符号链接到 的#!/bin/sh系统上进行测试,则没有 的用户将遇到麻烦。他们很可能会看到一条神秘的错误消息,例如:/bin/sh/bin/bashbash

Error in script.sh line 123: error parsing token xyz

这可能需要几个小时才能修复,并且他们不知道应该使用哪个 shell。

您想要在 shebang 中使用不同 shell 的原因并不多。一个原因是您使用的 shell 并不普及。另一个原因是sh在某些系统上获得更快的性能,并且您的脚本将成为性能瓶颈。在这种情况下,请使用目标 shell 彻底测试您的脚本,然后更改 shebang。

答案3

您应该只使用#! /bin/sh

您永远不应该在 shell 脚本中使用 bash(或 zsh、或 fish 或...)扩展。

你应该只编写与以下环境兼容的 shell 脚本任何shell 语言的实现(包括与 shell 本身一起提供的所有“实用程序”程序)。现在你可以大概POSIX.1-2001不是-2008) 作为 shell 和实用程序功能的权威标准,但请注意,未来某一天你可能会被要求将脚本移植到旧系统(例如 Solaris 或 AIX)上,而旧系统的 shell 和实用程序在 1992 年左右就已冻结。

什么,真的吗?!

是的,说真的。

事实是这样的:Shell 是一个糟糕的编程语言。它唯一的优势是它/bin/sh是唯一一个脚本解释器,每一个Unix 安装保证有。

还有一件事:核心 Perl 5 解释器的一些迭代(/usr/bin/perl)是更多的在随机选择的 Unix 安装上可用的可能性比(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash实际的要高。其他优秀的脚本语言(Python、Ruby、node.js 等 — 与 shell 比较时,我甚至会将 PHP 和 Tcl 归入该类别)也与 bash 和其他扩展 shell 大致一样可用。

因此,如果你可以选择编写 bash 脚本,您也可以选择使用一种不那么糟糕的编程语言。

现在,简单的shell 脚本,即按顺序运行 cron 作业或其他程序的脚本,将它们保留为 shell 脚本没有任何问题。但简单的 shell 脚本不需要数组或函数,甚至不需要[[。你应该只写复杂的当你没有其他选择时,可以使用 shell 脚本。例如,Autoconf 脚本仍然是 shell 脚本。但这些脚本必须运行在每一个与配置的程序相关的化身/bin/sh。这意味着它们不能使用任何扩展。现在你可能不必关心旧的专有 Unix,但你可能应该关心当前的开源 BSD,其中一些bash默认情况下不会安装,以及仅提供最小 shell 和的嵌入式环境busybox

总之,当你发现自己想要可移植 shell 语言不具备此功能,这表明该脚本已变得过于复杂,无法继续作为 shell 脚本使用。请使用更好的语言重写该脚本。

答案4

更简洁地说,sh如果跨大多数系统的可移植性是最重要的,并且bash您想使用它的某些特定功能(例如数组)(如果 bash 版本支持它),则使用。

相关内容