LinuxShell
1 shell 简介
命令行界面(CLI, Command Line Interface)是用户与操作系统交互的一种方式,通过输入文本命令来执行操作。不同的操作系统和环境提供了多种命令行解释器(shell),其中 sh
和 bash
是最常见和广泛使用的两种。
1.1 sh (Bourne Shell)
- 历史:
sh
是最早的 Unix shell 之一,由 Stephen Bourne 在 1977 年为贝尔实验室的第七版 Unix 系统开发。 - 标准:
sh
是 POSIX 标准定义的基础 shell,这意味着它提供了一套基本的、跨平台的功能集。 - 特点:
- 简单且轻量级。
- 语法相对严格,支持基本的变量、条件判断、循环等。
- 适合编写简单的脚本或在资源受限的环境中使用。
- 兼容性:大多数 Unix 和类 Unix 系统都包含一个符合 POSIX 标准的
sh
实现,例如 FreeBSD 的/bin/sh
或 Debian/Ubuntu 的dash
。
1.2 bash (Bourne Again Shell)
- 历史:
bash
由 Brian Fox 于 1989 年为 GNU 项目开发,旨在替代 Bourne Shell。 - 扩展功能:
bash
是sh
的超集,提供了许多额外的功能,包括但不限于:- 命令行编辑。
- 命令历史记录。
- 作业控制。
- 数组支持。
- 更强大的字符串处理能力。
- 高级模式匹配。
- 动态加载模块。
- 兼容性:
bash
可以运行大多数sh
脚本,并且通常默认安装在大多数 Linux 发行版中。它也是 macOS 和许多其他系统中的默认 shell。 - 特点:
- 更多的内置命令。
- 支持函数和局部变量。
- 更复杂的条件表达式和流程控制结构。
- 提供了更多的用户自定义选项,如别名、环境变量等。
- 使用场景:
bash
适合用于日常的命令行操作和编写复杂的脚本。由于其丰富的功能和广泛的可用性,bash
成为了许多开发者和系统管理员的首选 shell。
1.3 其他常见的 CLI
除了 sh
和 bash
,还有其他一些常用的命令行解释器:
- zsh (Z Shell):一种高度可配置的 shell,提供了比
bash
更多的特性,如主题、插件支持等。macOS Catalina 及更高版本将zsh
作为默认 shell。 - ksh (KornShell):由 David Korn 开发,结合了
sh
和 C 语言的一些特性,提供了更高级的编程功能。 - tcsh (TENEX C Shell):基于
csh
,提供了命令行编辑和历史记录等功能。 - fish (Friendly Interactive Shell):一种用户友好的 shell,具有自动建议、语法高亮等特性,适合初学者和需要快速上手的用户。
1.4 Ubuntu 中有哪些 Shell
Ubuntu默认安装了 bash
作为默认 shell,但它也支持其他 shell,包括 zsh
和 fish
。你可以通过以下命令查看当前使用的 shell:1
echo $SHELL
你可以通过以下命令查看系统中安装的 shell:1
2serenitatis@ubuntu:$ ls /bin/*sh
/bin/bash /bin/dash /bin/rbash /bin/sh /bin/static-sh
- static-sh 通常是静态编译的 shell。静态编译的程序不需要依赖外部库文件,因此可以在没有完整动态链接库的环境中运行。
- /bin/sh 是系统的默认 shell,但它实际上可以指向不同的 shell 解释器。在不同的系统中,/bin/sh 可能是指向 bash, dash, 或其他符合 POSIX 标准的 shell 的符号链接。
- rbash 是 bash 的一个受限版本,旨在提供一个受限制的 shell 环境,以防止用户执行某些可能对系统造成危害的操作。
- dash 是一个轻量级的 shell,设计为比 bash 更快更简单。它是 POSIX 标准的一个实现,旨在提供一个基本的、符合标准的 shell。
2 shell脚本是基本用法
2.1 . 选择 Shell
首先,你需要确定你的脚本将使用哪种 Shell 解释器(如 bash, sh, zsh, ksh 等)。大多数情况下,bash 是最常用的选择。在脚本的第一行指定使用的 Shell,例如:1
2.2 . 编写脚本
使用文本编辑器创建一个新文件,例如 myscript.sh
。在这个文件中,你可以开始编写命令。以下是一个简单的例子,它打印“Hello, World!”到屏幕上:1
2
echo "Hello, World!"
2.3 . 设置执行权限
保存文件后,需要给这个脚本文件设置可执行权限。可以使用 chmod
命令来改变文件的权限:1
chmod +x myscript.sh
2.4 . 运行脚本
运行脚本有几种方式。如果你在脚本所在的目录下,可以直接通过以下命令运行:1
./myscript.sh
或者,你也可以通过指定解释器来运行脚本:1
bash myscript.sh
2.5 . 使用变量
Shell 脚本支持变量的使用,这使得脚本更加灵活。例如:1
2
3
name="World"
echo "Hello, $name!"
2.6 . 条件判断
你可以使用条件语句来根据不同的情况执行不同的操作。例如:1
2
3
4
5
6
if [ "$1" == "hello" ]; then
echo "Hello, how are you?"
else
echo "Do you know me?"
fi
2.7 . 循环
循环结构可以帮助你重复执行一系列操作。例如,使用 for 循环打印数字 1 到 5:1
2
3
4
5
for i in
do
echo "Number: $i"
done
2.8 . 函数
定义函数可以使代码更加模块化和易于维护。例如:1
2
3
4
5
6
7
8
greet()
{
echo "hello $0"
echo "hello $2"
}
greet "User" "abc"
2.9 . 参数传递
你可以从命令行向脚本传递参数。这些参数可以在脚本内部通过 $1
, $2
, … 访问。例如:1
2
3
echo "First argument: $1"
echo "Second argument: $2"
2.10 . 错误处理
为了使脚本更加健壮,你应该加入错误处理逻辑。例如,检查命令是否成功执行:1
2
3
4
5
6
ls -ld abc
if (($?!=0)); then
echo "Error"
exit 1
fi
返回1
2ls: 无法访问'abc': 没有那个文件或目录
Error
- $? 是一个特殊变量,保存了上一个命令的退出状态码。在 Unix 和 Linux 系统中,命令成功执行通常返回 0,而任何非零值表示命令执行失败。
- 1 是传递给 exit 的参数,表示脚本以非零状态码退出。通常,非零状态码表示脚本执行过程中发生了错误。状态码 1 是一个常见的选择,但你可以根据需要使用其他非零值来表示不同的错误类型。
3 更多的表达式
在 Bash 脚本中,[]
/[[ ]]
和 (( ))
都用于条件测试也即执行逻辑运算,但它们之间有一些重要的区别,不同版本的bash可能会有一定的兼容性上的差异。理解这些区别有助于编写更强大和灵活的脚本。
3.1 []
(单括号)
- 标准:
[]
是 POSIX 标准的一部分,因此它在大多数 shell 中都可用,包括 sh、dash 和 bash。 - 语法严格:使用
[]
时,需要确保所有元素之间都有空格。例如,[ -f "$file" ]
是正确的,而[ -f"$file" ]
或[ -f "$file"]
会导致语法错误。 - 文件名扩展:
[]
内部不会进行文件名扩展(globbing),这意味着你不能直接使用通配符如*
或?
来匹配文件名模式。 - 字符串比较:在
[]
中进行字符串比较时,=
,!=
等运算符是区分大小写的,并且只能用于简单的字符串比较。 - 逻辑运算符:
-a
代表逻辑 AND,-o
代表逻辑 OR,!
代表逻辑 NOT。但是,这些运算符在某些情况下可能不如[[ ]]
中的&&
,||
,!
直观。
3.2 [[ ]]
(双括号)
- Bash 特性:
[[ ]]
是 Bash 的扩展特性,不适用于所有的 shell。如果你的脚本只需要在 Bash 中运行,那么使用[[ ]]
是一个好选择。 - 宽松语法:
[[ ]]
允许更加宽松的语法,不需要每个元素之间都有空格。例如,[[ -f "$file" ]]
是正确的,而且即使写成[[ -f"$file" ]]
也是可以接受的。 - 模式匹配:
[[ ]]
支持高级模式匹配,允许使用通配符*
,?
,+
等来匹配文件名或字符串。 - 字符串比较:
[[ ]]
中的字符串比较支持更多的操作符,如==
,!=
,<
,>
,<=
,>=
等,并且可以使用~
和!~
进行正则表达式匹配。 - 逻辑运算符:
[[ ]]
使用&&
表示逻辑 AND,||
表示逻辑 OR,!
表示逻辑 NOT。这些运算符更加直观,并且与大多数编程语言中的逻辑运算符一致。
3.3 (( ))
(双括号)
- 算术运算:
(( ))
用于算术运算和整数比较。它提供了类似 C 语言的算术表达式处理能力。 - 变量自动展开:在
(( ))
中,变量名会被自动展开为它们的值,不需要使用$
符号。例如,(( a = 5 ))
会将变量a
设置为 5。 - 算术运算符:支持常见的算术运算符,如
+
,-
,*
,/
,%
等。 - 比较运算符:支持整数比较运算符,如
==
,!=
,<
,>
,<=
,>=
等。 - 逻辑运算符:支持逻辑运算符
&&
(AND),||
(OR),!
(NOT)。
3.4 示例
3.4.1 使用 []
1 | if [ -f "$file" ]; then |
3.4.2 使用 [[ ]]
1 | if [[ -f "$file" ]]; then |
3.4.3 使用 (( ))
1 | a=5 |
3.5 总结
[]
:POSIX 标准,语法严格,主要用于基本的文件测试和简单的字符串比较。[[ ]]
:Bash 扩展,提供更宽松的语法和高级功能,如模式匹配和正则表达式。(( ))
:用于算术运算和整数比较,支持类似 C 语言的算术表达式。
选择哪种方式取决于你的具体需求和脚本的兼容性要求。如果需要编写跨平台的脚本,建议使用 []
;如果需要利用 Bash 的高级特性,可以使用 [[ ]]
和 (( ))
。