Skip to content

LV005-shell简介

一、 shell 简介

1. 是什么?

在计算机科学中,Shell 俗称 “壳” (区别于 “核”—— Linux 内核), Shell 是包裹在操作系统 外层 的一道程序,负责外界与 Linux “内核” 的交互,但它隐藏了操作系统底层的具体细节,就像是 Linux 内核的一个 “外壳”,所以 Shell(壳)的名称也由此而来。

shell 其实是一个用 C 语言编写的 程序,它是用户使用 Linux 的桥梁。它既是一种 命令语言,又是一种 程序设计语言

用户在命令行提示符下键入命令文本,开始与 shell 进行交互。接着, shell 将用户的命令或按键转化成内核所能够理解的指令控制操作系统做出响应,直到控制相关硬件设备。然后, shell 将输出结果通过 shell 提交给用户 。

Tips:那 shell 到底是什么?

  • 一个程序 → 安装在系统中的可执行软件
  • 一个解释器 → 解释命令并调用系统内核执行
  • 一个脚本引擎 → 解释执行 .sh 脚本文件

2. 常见的 shell

最初的 UNIX shell 经过多年的发展,由不同的机构、针对不同的目的,开发出许多不同类型的 shell 程序。目前流行的 shell 主要有几种 :

名称 全称 开发者 诞生时间 特点 当前状态
sh Bourne Shell Stephen Bourne 1977 年 Unix 系统上第一个标准 Shell,奠定了 Shell 脚本的基础语法,早已成为工业标准。目前几乎所有的 Linux 系统都支持它。不过 Bourne Shell 的作业控制功能薄弱,且不支持别名与历史记录等功能。 已不常用,仅用于兼容性,现代系统通常指向 dash
bash Bourne Again Shell Brian Fox 1989 年 GNU 项目的一部分,是 Bourne Shell 的增强版,支持命令补全、脚本调试等功能,能够提供环境变量以配置用户 Shell 环境,支持历史记录,内置算术功能,支持通配符表达式,将常用命令内置简化。 Linux 默认 Shell,最流行,社区资源最丰富
zsh Z Shell Paul Falstad 1990 年 集成了 bash、ksh、tcsh 等众多 Shell 的优点,支持强大的插件系统和主题定制 macOS 默认 Shell,配合 oh-my-zsh 使用广泛
fish Friendly Interactive Shell Axel Nilsson 2005 年 专为交互式使用设计,开箱即用,智能自动补全,语法简洁直观 逐渐流行,适合追求易用性的用户
dash Debian Almquist Shell Herbert Xu 1997 年 是 ash 的分支,轻量级、执行速度快,符合 POSIX 标准 Ubuntu/Debian 的/bin/sh,用于快速执行脚本
ksh KornShell David Korn 1983 年 兼容 Bourne Shell,同时吸收了 csh 的编程特性,执行效率高 在某些企业环境中仍有使用
tcsh TENEX C Shell Jim E. (The) Andersson 1979 年 csh 的增强版,支持命令补全、命令行编辑等功能 用户较少,主要用于兼容 csh 脚本
csh C Shell Bill Joy 1978 年 语法类似 C 语言,支持历史记录、别名等功能 已过时,不推荐新使用

3. 命令

3.1 命令提示符

shell 提示符标识了命令行的开始,用户在提示符后面输入一条命令并按 Enter 键,完成向系统提交指令。常见格式如下:

shell
user_name@host_name:direction Permission

【参数说明】

user_name 用户名,显示当前登录用户的账户
host_name 主机名,显示登录的主机名,例如若远 程登录后,则显示登录的主机名;
direction 目录名,显示当前所处的路径,当在根目录下显示为“/”,当在用户主目录下显示为“~”;
Permission 权限符号,一般用户权限显示为 $ , 若为 root 用户,则显示为 #

Tips:这个前缀主要是由环境变量 PS1 控制,可以自己任意更改。

3.2 命令格式

shell
$ Command [-Options] Argument1 Argument2 …
    指令      选项     参数1      参数2…

通常一条命令包含三个要素:命令名称、选项、参数。命令名称是必须的,选项和参数都可能是可选项。

参数说明

$ Shell 提示符,如果当前用户为超级用户,提示符为“#”,其他用户的提示符均为“$”;
Command 命令名称,Shell 命令或程序,严格区分大小写
Options 命令选项,用于改变命令执行动作的类型,由“-”引导,可以同时带有多个选项;
Argument 命令参数,指出命令作用的对象或目标,有的命令允许带多个参数。

注意

(1)一条命令的三要素之间用空格隔开;

(2)若将多个命令在一行书写,用分号 ; 将各命令隔开;

(3)如果一条命令不能在一行写完,在行尾使用反斜杠 \ 标明该条命令未结束;

(4)命令不带选项或参数,通常意为使用默认选项或参数。

4. 相关命令

4.1 支持哪些 shell 解释器?

我们可以在 linux 中执行以下命令看一下(注意这个命令查看的是一个文件,我们要是在自己移植的根文件系统的话,可能没有这个文件,就看不到啦):

shell
sudo cat /etc/shells

然后会看到如下输出信息:

shell
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash

可以看到我当前使用的 ubuntu 中支持这几种 shell 脚本解释器。上边我们已经知道怎么查看当前系统支持的 shell 解释器了,接下来做一个简单的了解吧,这里就简单介绍下 bash 和 sh,关于 dash 和其他的就暂时不做介绍了。

4.1.1 bash

bash(Bourne-Again Shell) ,Unix shell 的一种,在 1987 年由布莱恩·福克斯为了 GNU 计划而编写。1989 年发布第一个正式版本,原先是计划用在 GNU 操作系统上,但能运行于大多数类 Unix 系统的操作系统之上,包括 Linux 与 Mac OS X v10.4 起至 macOS Mojave 都将它作为默认 shell,而自 macOS Catalina,默认 Shell 以 zsh 取代。

4.1.2 sh

sh 是啥呢?我们看一下这个文件:

shell
ls -alh /bin/sh

然后会看到以下输出结果:

shell
lrwxrwxrwx 1 root root 4 8月  18 08:50 /bin/sh -> dash

发现它是一个超链接,GNU/Linux 操作系统中的 /bin/sh 本是 bash 的符号链接,但鉴于 bash 过于复杂,有人把 bash 从 NetBSD 移植到 Linux 并更名为 dash (Debian Almquist Shell),并建议将 /bin/sh 指向它,以获得更快的脚本执行速度。Dash Shell 比 Bash Shell 小的多,符合 POSIX 标准。

其实我们是可以修改 sh,让其指向 bash 的,我们可以在终端执行:

shell
sudo dpkg-reconfigure dash

然后就会弹出一个菜单界面

shell
 ┌─────────────────────────────┤ 正在设定 dash ├─────────────────────────────┐
 
 The system shell is the default command interpreter for shell scripts. 
 
 Using dash as the system shell will improve the system's overall          │ 
 │ performance. It does not alter the shell presented to interactive users.  │ 
 │                                                                           │ 
 │ Use dash as the default system shell (/bin/sh)?                           │ 
 │                                                                           │ 
 │                    <是>                        <否>                       │ 
 │                                                                           │ 
 └───────────────────────────────────────────────────────────────────────────┘

我们选择否就可以让 sh 指向 bash 啦,然后会出现以下提示信息:

shell
正在删除 dash 导致 /bin/sh 转移到 /bin/sh.distrib
正在添加 bash 导致 /bin/sh 转移到 /bin/sh.distrib
正在删除 dash 导致 /usr/share/man/man1/sh.1.gz 转移到 /usr/share/man/man1/sh.distrib.1.gz
正在添加 bash 导致 /usr/share/man/man1/sh.1.gz 转移到 /usr/share/man/man1/sh.distrib.1.gz

然后我们重新看一下这个超链接,就会发现它指向了 bash 了已经。

注意】 需要注意的是 dash 和 bash 有一些语法是不太一样的,所以我们写脚本的时候使用 sh 作为解释器的时候,有时候可能会出现问题,这个时候我们要知道是 bash 和 dash 语法有区别就可以了。

4.2 当前使用的是哪个?

那当前系统使用的是哪一个解释器呢?我们可以使用以下命令查看:

shell
echo $SHELL

这个是可以在移植的根文件系统上使用的,因为它打印的是当前 shell 的环境变量的值。

二、终端与 shell

1. 一个三层模型

text
┌──────────────────────────┐
│  终端 (Terminal)          │  ← 我们看到的窗口、标签、字体、颜色……
│  (Windows Terminal,      │
│   macOS Terminal, iTerm2)│  负责“显示”
└────────────┬─────────────┘
             │ (传递用户输入)
┌────────────┴─────────────┐
│  解释器 (Shell)           │  ← 真正理解并执行我们命令的“大脑”
│  • bash / zsh / fish     │
│  • cmd.exe / PowerShell  │  负责“执行”
└────────────┬─────────────┘
             │ (调用系统功能)
┌────────────┴─────────────┐
│  内核 & 程序 (Kernel)     │  ← 操作系统和 `git`, `ls` 等具体程序
│  (文件系统, 网络, 进程…)    │  负责“干活”
└──────────────────────────┘

还有一个直观的理解:

text
┌──────────────────────────────────────────────────────┐
│                       电脑屏幕                         │
│  ┌────────────────────────────────────────────────┐  │
│  │  终端模拟器 (Terminal / iTerm2 / Konsole)        │  │
│  │  ┌──────────────────────────────────────────┐  │  │
│  │  │  $ ls -la                                │  │  │
│  │  │  drwxr-xr-x  10 user  staff   320 Mar 13 │  │  │
│  │  │  ...                                     │  │  │
│  │  │                                          │  │  │
│  │  │         ← Shell (bash/zsh/fish) 运行在这里 │  │  │
│  │  └──────────────────────────────────────────┘  │  │
│  └────────────────────────────────────────────────┘  │
│                                                      │
└──────────────────────────────────────────────────────┘

这里有一个比喻来帮助理解:

现实场景对应技术作用
手机里的「点菜点菜小程序或者 APP 界面」终端 Terminal显示菜单、字体、动画,本身不做饭
选的「服务员」Shell读懂我们的菜单(命令),指挥厨房做菜
厨房里的「食材/灶具/电」内核/程序真正读写文件、启动进程、调用硬件

一句话小结终端是显示器,Shell 是翻译。 我们在显示器上打字,翻译读懂后告诉系统去执行。

2. 分层解释

2.1 终端 (Terminal):我们看到的那个“窗口”

2.1.1 什么是终端

终端 就是人与计算机 交互的接口。Unix 和 Linux 把这些人机交互的接口统称为 —— 终端。可以简单将终端理解为 “鼠标、键盘、显示器 、扬声器、麦克风” 等 硬件设备

【早期的终端】

早期的终端是一种叫做 电传打字机 - Teletype 的东西。当时还没有个人电脑,普通的计算机都有衣柜那么大,而且很昂贵,人手一台的可能性很低。但是一个用户占有一台计算机未免有点浪费,为了提高计算机的使用效率,Unix 的创始人 Ken Thompson 和 Dennis Ritchie 打算设计一个能够支持多用户进行操作的操作系统(也就是现在的 Unix),实现将一台计算机提供给多位用户进行使用。

想要实现多用户操作,首先需要给每位用户提供一套基本的输入输出设备来进行操作。但是当时的计算机设备都非常昂贵,每位用户人手一套的话费用也太高了。所以最后他们找到了更 便宜电传打字机 来作为替代,也就是下图的 ASR-33 电传打字机。

img

可以看出它有 键盘纸带,用户可以通过键盘向计算机 输入 信息,然后计算机通过在纸带上打印 输出 结果。这样看来,电传打字机完全可以作为人机交互设备使用。

于是 Unix 成为了世界上第一个支持多用户的操作系统,而 ASR-33 成为了第一个 Unix 终端。

【现在的终端】

随着计算机快速发展,其硬件设备也越来越便宜且先进。像电传打字机这样的早期终端设备早已退出历史舞台,取而代之的是 键盘、鼠标、显示器 等设备。

虽然现在电传打字机已经不再适用,但它也是计算机发展的一个重要象征。所以 Teletype 的缩写 TTY 沿用至今,作为各种类型的终端设备的统称。(我们现在看到的 tty 不再单纯指电传打字机,而是指各种各样的终端设备)

台式机的终端输入设备包括:键盘、鼠标、麦克风;终端输出设备包括:显示器、扬声器 【Linux 的终端】

前面我们说的终端指的都是物理的终端设备,而我们在 Linux 上常说的终端其实是 终端模拟器 - Terminal Emulator(一种 模拟终端的程序 ),也称为 —— 虚拟终端 ,但平时一般直接称为终端。

可以将 Linux 终端看作一个使用 软件 来模拟的输入、输出设备,其作用就是提供一个命令的输入、输出环境。Linux 终端是基于物理终端之上的

【终端模拟器出现的原因】

电传打字机时代是没有图形接口的,计算机直接从打字机读取用户的输入,然后自动将计算结果打印到纸带,是非常典型的命令行操作模式。

随着计算机发展,出现了各种各样的图形接口,很多操作系统也以图形界面操作为主。大部分的程序都能通过图形接口进行交互,但是仍然存在一些传统的命令行程序还不兼容图形接口,只能通过命令行进行交互。

但是现在已经没有电传打字机了,这些传统程序不能直接读取用户的键盘输入,也不能将计算结果直接输出到显示器(比如我们现在返回电脑桌面,随便在键盘上输入一些命令,是不会有什么反应的),这种情况下我们要如何运行这些程序呢?—— 【终端模拟器】

终端模拟器就是一个模拟传统终端设备进行命令行操作的程序。在该程序内输入的命令能够被计算机读取和执行,并将结果输出到显示器。简单来说,终端模拟器就是模拟了一台电传打字机,所以我们一般也直接称之为终端。

2.1.2 主要功能

终端的核心职责是 显示交互,它本身不理解命令。它的主要功能如下:

  • 字符渲染:把程序输出的字节流(比如 ls 的结果)变成你肉眼可见的文字、颜色和符号。
  • 会话管理:提供多标签、多窗格、会话恢复等功能。
  • 输入处理:捕获你的键盘输入,并发送给 Shell。
  • 美化与配置:允许你自定义字体、配色方案、背景模糊等视觉效果。要显示特殊图标(如 Powerlevel10k 中的小图标),通常需要安装 Nerd Fonts 字体。
2.1.3 主流实现
  • WindowsWindows Terminal, ConEmu, Fluent Terminal
  • macOSTerminal.app (系统自带), iTerm2 (功能更强)
  • LinuxGNOME Terminal, Konsole, Alacritty, kitty

2.2 Shell:那个解析命令的“大脑”

2.2.1 是什么?

前面已经说过了 shell 是什么?

2.2.2 主要功能

Shell 的核心职责是 解释执行。它是连接我们和操作系统内核的桥梁。

  • 命令解析:读取我们输入的字符串(如 ls -la),理解其含义。
  • 脚本编程:提供变量、循环、判断等语法,让你能编写自动化脚本(.sh, .ps1 文件)。
  • 环境管理:通过 配置文件 (如 ~/.bashrc, ~/.zshrc, profile.ps1) 管理环境变量、别名(alias)、启动任务等。
  • 管道与重定向:实现 |, >, < 等强大的数据流控制。
2.2.3 主流实现
  • POSIX 家族:
    • bash:最普及的 Shell,几乎所有 Linux 发行版和早期 macOS 的默认选择。
    • zsh:功能更强,交互体验更好,是当前 macOS 的默认 Shell。常与 Oh My Zsh 框架搭配使用。
    • fish:以“开箱即用”和“智能自动补全”著称。
  • Windows 家族:
    • cmd.exe:传统的命令提示符,功能简单。
    • PowerShell:现代化的 Shell,基于 .NET,语法强大,跨平台。

三、shell 脚本

1. 是什么?

shell 脚本语言是解释型语言,本质是 shell 命令的有序集合, 一般 shell 脚本文件的后缀名称是 .sh 。

注意】shell 脚本文件就是一个文本文件,只是后缀名建议使用 .sh 结尾,之后其实也会遇到很多根本就没有后缀的 shell 脚本文件。

2. Hello World!

shell
#!/bin/bash
echo "Hello World!"

这段代码是一个最简单的 shell 脚本程序,就像 C 语言学习时的第一个 hello world 程序一样。

  • 第一行: #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 shell 。这里就是设置当前 shell 脚本文件采用 bash 解析器运行脚本代码
  • 第二行:echo 命令用于向命令行窗口输出文本,这个后边会再学习。

3. 怎么运行脚本

3.1 使用 ./ 的方式

这种方式就是必须要进入脚本所在的目录中,才能执行脚本文件。

(1)进入 shell 脚本所在目录

shell
cd <file_path>

(2)赋予 shell 文件执行权限

shell
chmod permissions file_name.sh

permissions 为要赋予文件的权限(常用 777 或者 740,保证文件具有可执行权限即可)。

(3)执行 shell 脚本文件

shell
./file_name.sh

3.2 sh 或 bash + 脚本相对或绝对路径

这种方式我们并不需要这个脚本有 +x(也就是可执行权限)。这种方式以我们以这个脚本为例:

shell
#!/bin/sh
echo "hello world"

我们把它放在 /home/hk/6temp 目录下,然后到家目录下执行以下命令:

shell
# 使用 bash
bash 6temp/test.sh
bash /home/hk/6temp/test.sh
# 使用 sh
sh 6temp/test.sh
sh /home/hk/6temp/test.sh

会发现都是可以正常执行的。

3.3 相对路径或绝对路径执行

其实还有一种使用相对路径或者绝对路径的方式执行脚本,可以不使用 bash 和 sh 作为执行命令的前缀,这样在一些我们并不清楚使用的解释器是什么的情况下就比较方便。但是这种方式要求脚本文件具有可执行权限(+x)。我们这次到 test.sh 的上一级目录进行测试:

shell
# 赋予可执行权限
chmod +x 6temp/test.sh

# 相对路径执行
6temp/test.sh

# 绝对路径执行
/home/hk/6temp/test.sh

会发现这两种方式都是可以正常执行脚本文件的。

注意】 其实上边的 ./ 的方式就属于相对路径执行脚本的方式,只是是在脚本文件所在目录中执行的,但是这里需要注意,若是在脚本所在目录使用相对路径执行脚本的话,一定要加上 ./ ,否则是找不到这脚本的,当然,也可以将其添加到环境变量中去,这样就可以不需要 ./ 了。

三、shell 中的通配符

通配符 含义 实例
* 匹配任意长度的字符串 用 file_*.txt, 匹配 file_wang.txt、file_lee.txt、file3_liu.txt
? 匹配一个长度的字符 用 file_?.txt,匹配 file_1.txt、file_2.txt、file_3.txt
[...] 匹配其中指定的一个字符 用 file_[otr].txt, 匹配 file_o.txt、file_r.txt 和 file_t。txt
[-] 匹配指定的一个字符范围 用 file_[a-z].txt, 匹配 file_a.txt、file_b.txt, 直到 file_z.txt
[^...] 除了其中指定的字符均可匹配 用 file_[^otr].txt,除了 file_o.txt、file_t.txt、file_r.txt 的其它文件

参考资料:

Linux 学习笔记(一):终端 和 Shell 的区别和联系_shell 终端-CSDN 博客

终端与 Shell:从入门到看懂,一篇就够 | 吃糠咽菜