Mar*_*rco 85
/bin
.小智 28
Linux 中(与 Debian 相关的:Ubuntu、Mint 等)中的大多数系统脚本都编写为在更快的 dash 中运行,这是这些系统中的默认 /bin/sh。原因有两个:
系统的速度。较小的破折号代码加载速度更快,运行速度也更快。为 shell 脚本程序员提供一些(小?)额外的努力(成本)。
安全。拥有多样性的外壳有助于抵御错误。Debian 系统大多不容易受到 shellshock 的影响,因为默认的 shell 没有这样的漏洞。
Bash 确实是用户的默认 shell ,因为它更强大,并且有更多的元素使编码更容易。它也是sh
Mac OS 中的默认设置(从 /bin/sh 链接的那个)。但是,bash
使用 的链接名称调用sh
使其作为符合 posix 的 shell 启动。
Jde*_*eBP 21
其他人指出,问题的前提,即 Bourne Again shell 是默认的并且无处不在,这是完全错误的。
除此之外,使用 Bourne Again shell 以外的东西来解释 shell 脚本确实有很好的理由。动机Ubuntu的和Debian的大项目,过了若干年后,除去bash化,并让尽可能多的shell脚本的这些原因,在系统初始化运行(这是一个很多与系统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 类需要考虑:
请注意,将其称为“偏好/bin/sh
”过于简单化。Debian 实际上至少有两个目标:
面对使用 Debian Almquist shell、Z Shell(在 POSIX 模式下)、Bourne Again shell(在 POSIX 模式下)、MirBSD Korn shell 和其他人的管理员/bin/sh
,要么……
...使脚本尽可能可移植,以便切换/bin/sh
映射到的内容不会破坏事物;或者
...使不可移植的脚本明确针对正确的解释器程序,而不是简单地期望/bin/sh
映射到它。
有制作的Debian Almquist外壳的默认映射/bin/sh
,而不是Bourne shell的,所以,那些脚本是POSIX的符合性(或者,更确切地说,Debian策略手册符合性)更快速地跑了。
当然,一旦进入这一领域,就可以走得更远;如考虑的喜欢的效率的权衡/bin/true
,并/usr/bin/clear
为shell脚本或编译的程序。但幸运的是,这超出了这个答案的范围。☺
当然,这些都不是新的,甚至也不是特定于 Unix 的。早在世纪之交之前,我编写并发布了一个命令行解释器,它有“交互式”和“非交互式”两种风格,解释了其文档中的这种划分,并指出了环境变量COMSPEC
和OS2_SHELL
环境变量之间的区别。同样,关于在 Debian 的 System V 中删除 bashismrc
和软件包安装/删除脚本的讨论可以追溯到 1990 年代。
/bin/sh
。Ubuntu 维基。/bin/sh
。Debian 维基。有什么理由让shebang指向/bin/sh而不是/bin/bash?
是的。@Marco 的出色回答很好地概括了这一点。
我应该在我的shebang中使用什么?
在编写自己的脚本时,您应该将shebang 指向您测试过的最通用的东西。
在我的系统(Centos 6.6)上,sh
符号链接到bash
:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Dec 2 2014 /bin/sh -> bash
Run Code Online (Sandbox Code Playgroud)
这意味着我总是#!/bin/bash
在我的 shebang 中使用,除非我已经确认我的脚本中没有 bashim。
通过将 shebang 设置为#!/bin/sh
您承诺该脚本将适用于sh
.
这是一个比说脚本将与 bash 一起工作更大的承诺。
下面是一个脚本示例,它会根据sh
系统使用的实现而行为不正确:
#!/bin/sh
n=1
a=$((++n))
echo $n
Run Code Online (Sandbox Code Playgroud)
使用bash
脚本时会打印:
2
Run Code Online (Sandbox Code Playgroud)
使用dash
脚本时会打印:
1
Run Code Online (Sandbox Code Playgroud)
如果我想使用#!/bin/sh
我需要做什么?
checkbashisms
- 请注意,这不会找到所有 bashim。它没有在我上面的脚本中找到 bashismsh
实现测试脚本。我通常使用 进行测试dash
,但是我希望一些 bashisms 或 dashims 仍然可以通过。 该DashAsBinSh页面上的Ubuntu的wiki有许多有趣的信息。
编写 shell 脚本而不是使用更强大且符合人体工程学的语言的脚本的唯一剩余原因是,是否可移植到具有一组未知的已安装软件的遗留系统比任何其他因素都更重要。
/bin/sh
是唯一一个可用于所有自称 Unix 的脚本解释器。但在大量遗留系统上,/bin/sh
相关实用程序甚至不符合 POSIX.1-1996“shell 和实用程序”规范,更不用说更现代的规范了。符合标准的工具是可选的附加组件,安装在/usr/xpg4
或某些此类不明显的位置。1 编写可移植子集 shell 语言的脚本比编写 POSIX shell 语言的脚本更加繁琐且容易出错。configure
(如果您不相信我,请有时阅读 Autoconf 生成的脚本。仅设置就足以说服您。)
但是,如果您可以假设安装了任何其他脚本解释器(例如 Bash),那么您可以假设安装了更好的脚本语言的解释器。例如,Perl比 Bash更容易使用。
因此,您永远不应该编写#! /bin/bash
脚本,因为如果可以选择,那么更好的语言也是一种选择。
1例如,Solaris 10 及更早版本将原始 Bourne shell作为/bin/sh
. 我得知Solaris 11已将其更新为ksh93。