sh和Bash之间的差异
sh和Bash之间的差异
在编写shell程序时,我们通常使用/bin/sh
和/bin/bash
。我通常使用bash
,但是我不知道它们之间的区别。
Bash
和sh
之间的主要区别是什么?
在Bash和sh
编程时需要注意什么?
sh
: http://man.cx/sh
Bash: http://man.cx/bash
TL;DR: Bash 是 sh
的超集,具有更优雅的语法和更多的功能。在几乎所有情况下,使用Bash shebang 行是安全的,因为它在现代平台上非常普遍。
NB: 在某些环境中,sh
就是 Bash。检查 sh --version
。
什么是sh?
sh
(或Shell命令语言)是由POSIX标准描述的编程语言。它有许多实现(如ksh88
,Dash等)。Bash也可以被视为sh
的一种实现(见下文)。
由于sh
是一种规范,而不是一种实现,在大多数POSIX系统上,/bin/sh
是一个符号链接或硬链接到一个实际的实现。
什么是Bash?
Bash最初是一个sh
兼容的实现(尽管它比POSIX标准早了几年),但随着时间的推移,它已经获得了许多扩展。其中许多扩展可能会改变有效的POSIX shell脚本的行为,因此Bash本身不是一个有效的POSIX shell。相反,它是POSIX shell语言的一种方言。
Bash支持一个--posix
开关,使其更具有POSIX兼容性。如果作为sh
调用,它还尝试模仿POSIX。
sh = bash?
在大多数GNU/Linux系统中,/bin/sh
长期以来都指向/bin/bash
。因此,忽略它们之间的差别几乎是安全的。但最近情况开始发生改变。
一些流行的例子是,在一些系统上/bin/sh
不指向/bin/bash
(其中一些系统甚至可能不存在/bin/bash
):
- 现代的Debian和Ubuntu系统,默认情况下将
sh
软链接到dash
; - Busybox,通常在Linux系统引导时作为
initramfs
的一部分运行。它使用ash shell实现。 - BSD系统和一般的非Linux系统。OpenBSD使用
pdksh
,它是KornShell的后代。FreeBSD的sh
是原始Unix Bourne shell的后代。Solaris有它自己的sh
,长期以来不符合POSIX;可以从Heirloom项目获取一个自由的实现。
如何在您的系统上查找/bin/sh
指向哪里?
问题在于/bin/sh
可以是符号链接或硬链接。如果它是符号链接,则可以使用便携式的方法来解析它:
% file -h /bin/sh /bin/sh: symbolic link to bash
如果是硬链接,则尝试:
% find -L /bin -samefile /bin/sh /bin/sh /bin/bash
实际上,-L
标志涵盖了符号链接和硬链接,但这种方法的缺点是它不具备可移植性——POSIX未要求find
支持-samefile
选项,尽管GNU find和FreeBSD find都支持它。
Shebang行
最终,由你来决定在脚本的第一行写下 "shebang" 行应该使用哪个解释器。
例如:
#!/bin/sh
将使用 sh
(以及它指向的任何内容),
#!/bin/bash
如果可用,将使用 /bin/bash
(如果不可用,则会出现错误消息)。当然,您也可以指定其他实现,例如:
#!/bin/dash
该使用哪个解释器
对于我的脚本,我更喜欢使用 sh
,理由如下:
- 它是标准化的
- 它更简单易学
- 它可以在 POSIX 系统上移植 - 即使它们没有安装
bash
,也必须要有sh
当然,使用 bash
也有优点。它的特性使编程更方便,类似于其他现代编程语言。这些包括作用域局部变量和数组。纯 sh
是一种非常简单的编程语言。