🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

Ubuntu的默认Shell“Dash”是什么?用法与Bash差异详解

使用Ubuntu时,您可能听说过Dash(dash)这个词。尤其是在编写shell脚本时,Dash的存在就变得尤为重要。虽然大多数用户日常使用的shell是Bash,但实际上在Ubuntu系统的后台,Dash正发挥着积极作用。本文将为初学者通俗易懂地讲解Dash作为Ubuntu默认shell的定位、基本用法,以及许多人容易混淆的与Bash的区别。

Web开发者们在服务器配置和部署工作中接触shell脚本的机会越来越多。本文中的所有代码都只需复制粘贴即可运行,请务必亲自动手,体验“让代码跑起来”的乐趣!


Dash到底是什么?为什么Ubuntu要使用它?

Dash(Debian Almquist shell)是用于类UNIX操作系统的一种命令行shell。其最大的特点是轻量且运行速度快。与功能丰富、性能强大的Bash相比,Dash的功能仅限于基础部分,因此脚本的执行速度非常快。

Ubuntu(及其基础Debian)利用其高速度,将Dash作为默认的系统shell(/bin/sh),用于执行系统启动脚本和各种后台处理。也就是说,除了我们平时在终端中交互使用的登录shell(/bin/bash)之外,系统内部是由Dash来高效处理任务的。这种“系统shell用Dash,登录shell用Bash”的分工体系,支撑着Ubuntu的流畅运行

让我们来检查一下您自己环境中的/bin/sh链接到了什么。执行以下命令就会显示其实际指向。

ls -l /bin/sh

多数情况下,会显示/bin/sh -> dash,这表明/bin/sh的实体就是Dash。


Dash的基本用法

那么,让我们实际使用Dash来执行一个简单的脚本吧。Dash的用法非常简单。

1. 创建脚本文件

首先,用文本编辑器创建一个简单的脚本文件。这里我们将其命名为hello_dash.sh

nano hello_dash.sh

编辑器打开后,粘贴以下内容并保存。

#!/bin/sh
# 上面这行叫做“shebang”,它指定用/bin/sh(也就是Dash)来执行这个脚本。

echo "Hello, Dash!"

2. 授予执行权限

为创建的脚本文件赋予执行权限。

chmod +x hello_dash.sh

3. 执行脚本

准备就绪,我们来执行脚本吧。

./hello_dash.sh

如果终端显示“Hello, Dash!”就表示成功了!这是执行Dash脚本最基本的方法。通过在shebang中指定#!/bin/sh,该脚本就由Dash来解释和执行了。


应用示例:在Dash中使用变量和循环

作为一个更实际的例子,我们来看看使用变量和while循环的脚本。其基本语法与Bash相似,但重要的是要有意识地使用符合POSIX标准的写法,以确保在Dash中能够稳定运行。

下面的脚本会一直循环直到计数器达到3,并显示当前的计数值。

#!/bin/sh

# 定义变量
COUNT=1

# 当COUNT小于等于3时,继续循环
while [ "$COUNT" -le 3 ]; do
  echo "当前计数: $COUNT"
  # 将COUNT加1。使用expr命令是最可靠的方法
  COUNT=$(expr "$COUNT" + 1)
done

echo "循环结束。"

将此脚本保存为loop_test.sh之类的文件名,同样赋予执行权限后用./loop_test.sh执行。应该会显示从1到3的计数。


注意事项:Dash与Bash的不兼容性

编写shell脚本时,初学者最容易遇到的陷阱就是Dash与Bash的功能差异。平时在终端(Bash)中运行正常的命令,在指定了/bin/sh的脚本(Dash)中却报错,这种情况时有发生。

在Web开发领域,当在服务器上作为cron作业运行脚本,或通过部署工具执行脚本时,通常会由系统的默认shell——Dash来执行。因此,如果不经意间使用了只能在Bash中使用的功能(称为Bashism),就会导致只在生产环境中出错。

下面列出了一些尤其需要注意的典型不兼容性示例。

1. 无法使用数组

在Bash中,可以像fruits=("Apple" "Banana" "Cherry")这样轻松处理数组,但Dash不支持数组。

仅在Bash中有效的示例(在Dash中会报错):

#!/bin/bash
# 注意shebang是/bin/bash

fruits=("Apple" "Banana" "Cherry")
echo "第一个水果是 ${fruits[0]}。"

2. 无法使用大括号扩展 {..}

在Bash中,输入echo file{1..3}.txt会展开为file1.txt file2.txt file3.txt,但Dash没有此功能。

仅在Bash中有效的示例(在Dash中会原样显示):

#!/bin/bash

# 此命令在Bash中会生成三个文件名
touch data_{a,b,c}.csv

要在Dash中实现相同的功能,需要使用for循环等方法。


3. 无法使用测试命令 `[[ ... ]]`

如前所述,Bash的扩展测试命令[[ ... ]]功能更强大,但在Dash中无法使用。我们应该使用符合POSIX标准的[ ... ]

仅在Bash中有效的示例(在Dash中会报错):

#!/bin/bash

NAME="hoge"
# [[ ... ]] 内部可以使用 && 或 ||
if [[ "$NAME" == "hoge" && -n "$NAME" ]]; then
  echo "名字是hoge。"
fi

在Dash中也能运行的替代代码:

#!/bin/sh

NAME="hoge"
# 在 [ ... ] 中使用 -a (AND)
if [ "$NAME" = "hoge" -a -n "$NAME" ]; then
  echo "名字是hoge。"
fi

还请注意,字符串比较用的是=而不是==


总结:注意Dash,编写健壮的脚本

这次,我们讲解了作为Ubuntu默认shell的Dash的角色、基本用法以及与Bash的区别。

一开始可能会感到困惑,但理解了这些差异,就能预先防止“在本地能运行,但在服务器上却不行”这类问题。让我们熟悉Ubuntu dash的世界,力求创建更可靠的shell脚本吧!


相关文章

如果您想了解更详细的脚本编写方法或与Bash的兼容性,也推荐阅读这篇文章。