在我见过的大多数 shell 脚本中(除了我自己没有编写的脚本),我注意到 shebang 设置为#!/bin/sh
.对于较旧的脚本来说,这并不让我感到惊讶,但对于相当新的脚本来说,它也存在。
有什么理由优先选择/bin/sh
,/bin/bash
因为bash
它在许多 Linux 和 BSD 机器上几乎无处不在,而且通常是默认的,可以追溯到十多年前?
答案1
- 有些系统默认不提供 bash(例如 FreeBSD)。
- 即使安装了 bash,它也可能不会位于
/bin
. - 大多数简单的脚本不需要 bash。
- 使用 POSIX shell 更便于移植,并且脚本可以在更多种类的系统上运行。
答案2
Linux(Debian 相关:Ubuntu、Mint 等)中的大多数系统脚本都是为了在更快的破折号中运行而编写的,这是这些系统中的默认 /bin/sh。原因有两个:
系统的速度。较小的破折号代码加载速度更快,运行速度也更快。需要 shell 脚本程序员付出一些(小?)额外的努力(成本)。
安全。外壳的多样性有助于抵御错误。 Debian 系统大多不易受到 shellshock 的影响,因为默认 shell 不存在此类漏洞。
Bash 确实是默认的 shell用户,因为它更强大并且具有更多元素以使编码更容易。它也是sh
Mac OS 中的默认设置(从 /bin/sh 链接的)。但是,bash
使用链接名称进行调用sh
会使其作为 posix 兼容 shell 启动。
答案3
其他人指出,这个问题的前提是 Bourne Again shell 是默认的且普遍存在,这是完全错误的。
除此之外,使用 Bourne Again shell 以外的其他工具来解释 shell 脚本确实有充分的理由。这些原因促使 Ubuntu 和 Debian 的大项目多年来致力于消除 bashism 并使尽可能多的 shell 脚本由系统初始化运行(这是一个很多System 5 的 shell 脚本rc
)和软件包安装/删除使用Debian Almquist shell而不是 Bourne Again shell。
简而言之:Bourne Again shell 虽然充满了交互功能,但并不是符合 POSIX 的 shell 脚本最快的 shell 解释器。因此,如果可以使自己的 shell 脚本符合 POSIX 标准,并使用更轻量级的程序(例如 Debian Almquist shell)来解释它们,那么系统的性能将会更好。 (最后,Debian 不得不对 Almquist shell 进行轻微调整,以添加对几个非 POSIX shell 结构的支持,这些结构嵌入得太深、太广泛,而且太有用而无法摆脱。)
这一切的结果是引导性能的重大提升。
因此,这里有两类不同的 shell 需要考虑:
- 具有所有华丽交互功能的 shell,它们被配置为交互式登录 shell对于帐户数据库中的用户。
- 快速解释大量脚本的 shell,用作脚本解释器通过 shell 脚本程序。
请注意,将其称为“首选/bin/sh
”过于简单化了。 Debian 实际上至少有二目标:
面对使用 Debian Almquist shell、Z Shell(POSIX 模式)、Bourne Again shell(POSIX 模式)、MirBSD Korn shell 和其他 shell 的管理员,
/bin/sh
有两种选择:…使脚本尽可能可移植,这样切换
/bin/sh
映射到的内容就不会破坏事情;或者…使不可移植脚本明确定位正确的解释程序,而不是简单地期待
/bin/sh
它的映射。
将 Debian Almquist shell 作为默认映射
/bin/sh
而不是 Bourne Shell,以便那些脚本是符合 POSIX 规范(或者更准确地说,符合 Debian 策略手册)运行速度更快。
当然,一旦一个人进入这个领域,就可以走得更远。例如考虑shell 脚本或编译程序/bin/true
等的效率权衡。/usr/bin/clear
但幸运的是,这超出了这个答案的范围。 ☺
当然,这一切都不是很新,甚至也不是特定于 Unix 的。早在世纪之交之前,我就编写并发布了一个命令行解释器,它具有“交互式”和“非交互式”两种风格,在其 doco 中解释了这种划分,并指出了 和COMSPEC
环境OS2_SHELL
变量之间的差异。同样,关于删除 Debian System V 中的 bashismrc
和软件包安装/删除脚本的讨论可以追溯到 20 世纪 90 年代。
进一步阅读
- https://superuser.com/a/696310/38062
- https://unix.stackexchange.com/a/193210/5132
- 破折号为
/bin/sh
。 Ubuntu 维基。 - 破折号为
/bin/sh
。 Debian 维基。 - 巴什主义。格雷格的维基。
- 布莱恩·卡尔森 (2005-07-29)。10.4政策公益公告。 <[电子邮件受保护]>。 debian 开发。
- 拉斐尔·盖塞特 (2009-04-12)。dash 作为默认 /bin/sh 和无 bashisms 的存档 RG。 <[电子邮件受保护]> debian-devel。
- debian-policy:请不要声明在 dash 下工作的脚本“可能”符合策略。 Debian 错误 #490604。
- goal-dash 的 Debian 软件包报告
- debian-policy:请不要使用 echo -n 和 echo 一般情况。 Debian 错误#490605。
- 丽贝卡·索博尔 (2009-07-29)。 两个 shell 的故事:bash 或 dash。 LWN。
- 贾斯特斯·彭德尔顿 (1997-04-22)。包中的 bash-ism。 <[电子邮件受保护]>。 debian 开发。
- 乔纳森·德博因·波拉德 (2000)。“命令解释器前端”。命令解释器命令参考。 32 位命令解释器的在线文档。
- 约翰·钱伯斯 (1990)。/bin/true 命令和版权
答案4
编写 shell 脚本而不是使用更强大且更符合人体工程学的语言的脚本的唯一剩余原因是:向已安装一组未知软件的遗留系统的可移植性比任何其他因素都更重要。
/bin/sh
是唯一一个可用于所有自称 Unix 的脚本解释器。但在大量遗留系统上,/bin/sh
相关实用程序甚至不符合 POSIX.1-1996“shell 和实用程序”规范,更不用说更现代的规范了。符合标准的工具是可选的附加组件,安装在/usr/xpg4
或某些此类不明显的位置。1 编写可移植子集 shell 语言的脚本比编写 POSIX shell 语言的脚本更加繁琐且容易出错。 (如果您不相信我,请有时阅读 Autoconf 生成的configure
脚本。仅设置就足以说服您。)
但如果你可以假设任何其他脚本解释器安装了(例如 Bash),那么你可以假设一个解释器更好的脚本语言已安装。例如,Perl 是更多的可能比 Bash 更可用。
因此,您应该绝不编写#! /bin/bash
脚本,因为如果可以选择,那么更好的语言也是一种选择。
1例如,Solaris 10 及更早版本提供了原始的 Bourne shell作为/bin/sh
。我得知Solaris 11已将其更新为ksh93。