在 Linux shell 环境中,sh、dash 和 bash 之间的关系既有继承、兼容,也有替代和侧重,核心在于历史演变、标准遵循和性能优化。
1.sh (Bourne Shell):历史的起点
sh 指的是原始的 Bourne Shell,由 Stephen Bourne 在 1977 年左右为 Unix V7 开发。
它是早期 Unix 系统的标准命令解释器,奠定了现代 shell 的基础语法和核心功能(如变量、控制流、管道、重定向等)。
其路径通常是 /bin/sh。
关键点: 现代 Linux 系统中 /bin/sh 通常不再是原始的 Bourne Shell 可执行文件,而是一个指向其他兼容 shell(如 dash 或 bash)的符号链接。
2.bash (Bourne-Again Shell):增强的继任者
bash 是 Bourne-Again Shell 的缩写,由 Brian Fox 为 GNU 项目开发,首次发布于 1989 年。
设计目标: 完全兼容 sh (Bourne Shell) 的语法和特性,同时极大地扩展**了功能集。
*主要增强包括:
*命令行编辑(如 readline 库支持的历史记录、补全)。
*作业控制(jobs, fg, bg)。
*数组变量。
*更强大的条件表达式 ([[ ... ]])。
*命令别名 (alias)。
*函数定义更灵活。
*大量内置命令和扩展特性(如 select, $RANDOM, ${variable//pattern/replacement} 等)。
*路径通常是 /bin/bash。
与 sh 的关系:
bash 兼容 Bourne Shell (sh) 语法。一个符合 POSIX sh 标准的脚本通常可以在 bash 下运行。
在某些系统(尤其是较老的或某些 BSD 系统)上,/bin/sh 可能直接指向 /bin/bash。
当 bash 以 sh 的名字被调用(例如通过 /bin/sh 符号链接启动,或者使用 bash --posix)时,它会尽量模拟 POSIX sh 的行为,禁用一些非标准的 bash 扩展特性,以提高兼容性。但这并非 100% 等同于原始的 Bourne Shell 或 dash。
3.dash (Debian Almquist Shell):轻量高效的 POSIX 实现
dash 是 Debian Almquist Shell 的缩写,是 NetBSD 的 ash (Almquist Shell) 的一个现代分支,被 Debian 和 Ubuntu 等发行版采用。
ash 本身是一个轻量级、兼容 Bourne Shell 的 clone,由 Kenneth Almquist 在 1980 年代末开发。
设计目标:
严格遵循 POSIX 标准。
极致的执行速度和启动速度。
极小的内存占用(Footprint)。
与 sh 的关系:
在 Debian、Ubuntu 及其衍生版 中,默认的 /bin/sh 符号链接指向 /bin/dash,而不是 /bin/bash。
这意味着在这些系统上,当你运行一个以 #!/bin/sh 开头的脚本,或者直接在命令行输入 sh 命令时,实际执行的是 dash。
与 bash 的关系:
dash 只保证实现 POSIX sh 标准。它不包含 bash 的众多扩展特性(如数组、[[ ]]、source 命令(在 dash 中只能用 .)、高级参数扩展等)。
脚本如果依赖 bash 特有的语法或特性,在 /bin/sh 指向 dash 的系统上运行会失败(报语法错误)。
dash 在启动速度和执行简单脚本的效率上显著优于* bash,尤其是在系统初始化阶段(init 脚本、systemd 服务单元中的 ExecStart= 命令等),这是 Debian/Ubuntu 选择它作为默认 sh 的主要原因。

sh 是一个标准/接口: /bin/sh 是一个指向具体实现(dash 或 bash)的符号链接。这个实现必须符合 POSIX Shell 标准。
dash 是轻量级、严格 POSIX 的 sh 实现: 专注于速度、效率和标准符合性,不提供额外扩展。是 Debian/Ubuntu 系默认的 sh。
bash 是功能丰富的超集: 完全兼容 sh 标准,并提供了大量增强特性和更友好的交互体验。是许多发行版默认的交互式登录 shell* 和 RHEL/Fedora 等发行版默认的 /bin/sh 实现(或指向)。但其启动和运行比 dash 稍慢。
兼容性是关键问题:
如果一个脚本声明 #!/bin/sh,它应该只使用 POSIX sh 标准语法,这样才能在指向 dash 或 bash 的系统上都正常运行。
如果一个脚本需要用到 bash 的扩展功能,它必须*声明 #!/bin/bash(或完整路径)。否则在 /bin/sh 指向 dash 的系统上会出错。
*反之,用 #!/bin/bash 的脚本在只安装了 dash 的系统上(虽然罕见)也无法运行。
何时使用哪个?
写系统级脚本/追求最大兼容性/需要极速启动: 用 #!/bin/sh,并严格遵守 POSIX shell 语法*(无论系统实际链接到 dash 还是 bash)。这是最佳实践。
*需要 bash 的强大功能或交互式使用: 用 #!/bin/bash(脚本)或直接在 bash 终端中工作。
*系统初始化脚本/短小脚本: 系统默认使用 /bin/sh(即 dash)是为了速度。
*用户日常命令行: 通常默认使用 bash(或其他如 zsh),因为它交互体验好。
理解 sh、dash、bash 之间的关系,特别是 /bin/sh 符号链接的指向差异,对于编写可移植的 shell 脚本和调试脚本兼容性问题至关重要。