Linux—/bin/sh、/bin/bash、/bin/dash的区别

bash

bash 是一个为GNU计划编写的Unix shell。它的名字是一系列缩写:Bourne-Again SHell — 这是关于Bourne shell(sh)的一个双关语(Bourne again / born again)。Bourne shell是一个早期的重要shell,由史蒂夫·伯恩在1978年前后编写,并同Version 7 Unix一起发布。bash则在1987年由布莱恩·福克斯创造。

bash (GNU Bourne-Again Shell) 是许多Linux发行版的默认Shell 。事实上,还有许多传统UNIX上用的Shell,例如tcsh、csh、ash、bsh、ksh等等,Shell Script大致都类同。
由于历史原因,UNIX系统上有很多种Shell:

  • csh(C Shell):由Bill Joy开发,随BSD UNIX发布,它的流程控制语句很像C语言,支持很多Bourne Shell所不支持的功能:作业控制,命令历史,命令行编辑。

  • ksh(Korn Shell):由David Korn开发,向后兼容sh的功能,并且添加了csh引入的新功能,是目前很多UNIX系统标准配置的Shell,在这些系统上/bin/sh往往是指向/bin/ksh的符号链接。

  • tcsh(TENEX C Shell):是csh的增强版本,引入了命令补全等功能,在FreeBSD、Mac OS X等系统上替代了csh。

  • bash(Bourne Again Shell):由GNU开发的Shell,主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,bash从csh和ksh借鉴了很多功能,是各种Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash的符号链接。

可使用cat /etc/shells 指令查看自己系统可以使用的shell种类:

image-20211120231230430.png

用户的默认 Shell 设置在/etc/passwd文件中,例如:vim /etc/passwd

image-20211120231337573.png

sh

在 shell 脚本的开头往往有一句话来定义使用哪种 sh 解释器来解释脚本。
目前常见的 shell 脚本中主要有以下两种方式:
(1) #!/bin/sh
(2) #!/bin/bash

注意:每个脚本开头都使用"#!",#!实际上是一个2字节魔法数字,这是指定一个文件类型的特殊标记,在这种情况下,指的就是一个可执行的脚本。在#!之后,接一个路径名,这个路径名指定了一个解释脚本命令的程序,这个程序可以是shell,程序语言或者任意一个通用程序。
sh是bash的一种特殊的模式,也就是 /bin/sh 相当于 /bin/bash --posix。说白了sh就是开启了POSIX标准的bash 。
在一般的linux系统当中(如redhat),使用sh调用执行脚本相当于打开了bash的POSIX标准模式
sh一般设成bash的软链:

image-20211120231421597.png

怎么把sh改为指向bash呢?

  • 方法一:直接把/bin/sh的软链接改到bash中,如:ln -s /bin/bash /bin/sh
  • 方法二:配置shell,sudo dpkg-reconfigure dash

dash

鉴于 bash 过于复杂,有人把 bash 从 NetBSD 移植到 Linux 并更名为 dash(Debian Almquist Shell),并以获得更快的脚本执行速度。Debian Almquist shell,缩写为dash,一种 Unix shell。它比 Bash 小,只需要较少的磁盘空间,但是它的对话性功能也较少。它由 NetBSD版本的Almquist shell (ash)发展而来,于1997年,由赫伯特·许(Herbert Xu)移植到Linux上,于2002年改名为 dash。

ll -h /bin/

那么怎么把 sh 改为指 dash 呢?

sudo dpkg-reconfigure dash
# 选择yes使用dash作为默认的shell即可修改为dash。

#!/bin/bash是指此脚本使用 /bin/bash 来解释执行。其中,#!是一个特殊的表示符,其后,跟着解释此脚本的shell路径。
bash 只是 shell 的一种,还有很多其它 shell,如:sh,csh,ksh,tcsh,…我们可以通过以下一个示例来进行实验,了解#!/bin/bash的使用。
除第一行外,脚本中所有以“#”开头的行都是注释。
1)#!/bin/bash只能放在第一行,如果后面还有#!,那么只能看成是注释。
这里有三个脚本(脚本都要使用”chmod +x scriptname“命令来获得可执行权限):

  • tbash1.sh:
#!/bin/sh
source abc
echo “hello abc”
  • tbash2.sh:
#!/bin/bash
source abc
echo “hello abc”
  • tbash3.sh:
source abc
echo “hello abc”

三个脚本执行的结果:

[nsvc@localhost other]$ ./tbash1.sh
./tbash1.sh: line 2: abc: No such file or directory
# 注:当source命令执行有问题时,sh不再往下面执行。
[nsvc@localhost other]$ ./tbash2.sh
./tbash2.sh: line 2: abc: No such file or directory
hello abc
# 注:当source命令执行有问题时,bash继续执行下面命令。
[nsvc@localhost other]$ ./tbash3.sh
./tbash3.sh: line 1: abc: No such file or directory
hello abc
# 注:自身登录系统所在的shell是bash。所以,当source命令执行有问题时,bash继续执行下面命令。

如果将 tbash1.sh 改成:

echo “abc”
#!/bin/sh
source abc
echo “hello abc”

那么,执行结果是:

[nsvc@localhost other]$ ./tbash1.sh
abc
./tbash1.sh: line 3: abc: No such file or directory
hello abc
# 也就是说,脚本忽略了第二行“#!/bin/sh",直接使用当前所在的shell(也就是bash)来解释脚本。

当把 tbash1.sh 改成:

#!/bin/sh
#!/bin/bash
source abc
echo “hello abc”

执行结果为:

[nsvc@localhost other]$ ./tbash1.sh
./tbash1.sh: line 3: abc: No such file or directory
# 当执行完source命令时,并没有往下执行。说明,#!/bin/sh这一行起到作用了,但#!/bin/bash并没有起作用。在脚本中,除第一行外,脚本中所有以“#”开头的行都是注释。

2)#!后面的路径一定要正确,不正确会报错。
假如,我们把tbash1.sh中第一行的#!后面加了一个不存在的路径”/home/sh“:

#!/home/sh
source abc
echo “hello abc”

执行结果为:

[nsvc@localhost other]$ ./tbash1.sh
-bash: ./tbash1.sh: /home/sh: bad interpreter: No such file ordirectory
# 系统会提示/home/sh的路径不存在。

3)如果一个脚本在第一行没有加上#!+shell路径这一行,那么,脚本会默认当前用户登录的shell,为脚本解释器。
在1)中,脚本 tbash3.sh 的执行结果,就是用当前自己登录的shell(bash)解释后的结果。我们通常所用的shell都是bash,如果哪天登录到sh,再使用以上类型的脚本,就会有问题。以下是自己登录到sh下,执行tbash3.sh的结果:

-sh-3.2$ ./tbash3.sh
./tbash3.sh: line 1: abc: 没有那个文件或目录

与1)中的执行结果是不一样的。
因此,大家应该养成脚本首行加上#!+shell路径的习惯。

4)/bin/sh 相当于 /bin/bash --posix
我们将脚本 tbash1.sh 改为:

#!/bin/bash --posix
source abc
echo “hello abc”

执行结果:

[nsvc@localhost other]$ ./tbash1.sh
./tbash1.sh: line 2: abc: No such file or directory
# 与tbash1.sh原脚本执行的结果一样。

我们还可以以tbash3.sh为示例。
用以下命令来执行该脚本:

[nsvc@localhost other]$ bash tbash3.sh
tbash3.sh: line 1: abc: No such file or directory
hello abc
[nsvc@localhost other]$ sh tbash3.sh
tbash3.sh: line 1: abc: No such file or directory
[nsvc@localhost other]$ bash --posix tbash3.sh
tbash3.sh: line 1: abc: No such file or directory

"bash tbash3.sh"表示使用bash来作为脚本解释器来执行tbash3.sh。同样,也可以使用如”sh脚本名“这样的命令,来用sh作为脚本解释器。
从结果可以看出,/bin/bash–posix/bin/sh的执行结果相同。总结起来,sh跟bash的区别,实际上是bash有没开启posix模式的区别。遵守posix规范,可能包括,”当某行代码出错时,不继续往下执行。“

最后加上一点说明,每个脚本开头都使用"#!",#!实际上是一个2字节魔法数字,这是指定一个文件类型的特殊标记,在这种情况下,指的就是一个可执行的脚本。在#!之后,接一个路径名,这个路径名指定了一个解释脚本命令的程序,这个程序可以是shell,程序语言或者任意一个通用程序。

你可能感兴趣的:(Linux—/bin/sh、/bin/bash、/bin/dash的区别)