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的计数。
[ "$COUNT" -le 3 ]: 这是条件判断。-le表示“小于或等于”(less than or equal to)。因为Bash中常用的[[ ... ]]在Dash中无法使用,所以我们应该使用[ ... ]。COUNT=$(expr "$COUNT" + 1): 这是变量计算。虽然Bash中有((COUNT++))这样更简单的写法,但在Dash中使用expr命令是兼容性最好、最可靠的方法。
注意事项: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的区别。
- Dash轻量且高速,因此被用作Ubuntu的系统shell(
/bin/sh)。 - 我们平时使用的登录shell是Bash,两者存在功能差异。
- 编写shell脚本时,通过写上
#!/bin/sh并遵循在Dash中也能运行的POSIX标准写法,可以使脚本变得健壮且不依赖于特定环境。 - 数组、大括号扩展、
[[ ... ]]等是Bash特有的功能(Bashism),在/bin/sh脚本中应注意避免使用。
一开始可能会感到困惑,但理解了这些差异,就能预先防止“在本地能运行,但在服务器上却不行”这类问题。让我们熟悉Ubuntu dash的世界,力求创建更可靠的shell脚本吧!
相关文章
如果您想了解更详细的脚本编写方法或与Bash的兼容性,也推荐阅读这篇文章。