Skip to content

第 6 章 终端与 Shell 入门

Part 2 · 命令行生存


引子

黑底白字,一个光标在闪烁。没有图标,没有菜单,没有鼠标右键。

这就是终端。每一个 Linux 老手每天打交道最多的东西,也是每一个新手最害怕的东西。

恐惧来自未知。光标在闪,但你不认识它背后的那套语言——你不知道该敲什么,不知道敲错了会不会爆炸,甚至不知道这个黑框框和那个叫「Shell」的东西到底是什么关系。

这章要做的事情很简单:拆掉这份恐惧。让你认识它,让它听你说话。

Shell 不是黑魔法。它是一种对话——只不过对话的语法比你想象的要严谨那么一点。而那个让你紧张的黑框框,甚至都不是 Shell 本身。


背景与动机

如果你之前用过 Windows,你大概从来没主动打开过命令提示符(cmd)或者 PowerShell。Windows 的哲学是「能点的别敲」,一切都在图形界面里解决。

但 Linux 不一样。准确地说,是嵌入式 Linux 开发不一样。

当你以后用 SSH 连上一块 i.MX 开发板,那块板子很可能连图形界面都没有——你能看到的,就只有一个终端。配交叉编译环境、烧写镜像、查看内核日志、调试驱动……这些事情全部要在命令行里完成。

早点习惯它,后面才不会在每个需要敲命令的环节都卡壳。


概念层

Shell 是什么?

你可以把 Shell 理解成一个翻译官——你对着它说人话(命令),它翻译成内核能听懂的指令,转发给内核;内核干完活,把结果丢回来,Shell 再格式化一下,显示在屏幕上给你看。

但「翻译官」这个比喻有一个地方是错的:真正的翻译官只会逐字翻,而 Shell 是有脑子的。它能记住你敲过的命令(历史记录),能猜你想敲什么(Tab 补全),甚至能把一串命令写成「剧本」让它照着演(Shell 脚本)。

这套「你说一句、它做一件」的交互方式,叫做交互式 Shell。后面我们会学到的 Shell 脚本,则是把一整套命令提前写好,Shell 一口气从头执行到尾——相当于给了翻译官一张任务清单,让它自己照单抓药。

Ubuntu 22.04/24.04 的默认 Shell 是 Bash(Bourne Again Shell)。你可以用下面这条命令验证:

bash
# 查看当前使用的 Shell
$ echo $SHELL
# 预期输出
/bin/bash

需要提一句的是:Ubuntu 里 /bin/sh 这个路径指向的不是 Bash,而是 dash(Debian Almquist Shell)。dash 比 Bash 更轻量、启动更快,系统执行脚本时默认用 dash。这个区别在写 Shell 脚本时可能踩坑——如果你的脚本用了 Bash 特有的语法,第一行必须写 #!/bin/bash 而不是 #!/bin/sh。这个问题我们在第 26 章会详细展开。

终端模拟器又是什么?

回到那个黑框框。

严格来说,你看到的那个窗口不是 Shell。它叫终端模拟器(Terminal Emulator),是一个把 Shell 包起来的图形窗口。Shell 才是里面干活的那个翻译官,终端模拟器只不过是翻译官面前的那块屏幕加键盘。

这个区分大多数时候不重要——你打开终端,Shell 就在里面等着。但当你遇到「为什么在 Windows Terminal 里能显示颜色,在老式 cmd 里不行」这种问题时,知道「终端」和「Shell」是两层东西,就能帮你找到正确的方向。

Ubuntu 桌面自带的终端模拟器叫 GNOME Terminal。如果你用 WSL2,那你在 Windows 里打开的可能是 Windows Terminal 或系统自带的「Ubuntu」快捷方式——它们本质上都是终端模拟器,连到你 WSL2 里的 Bash。

命令的解剖学

Shell 能听懂的不是自然语言,是一种固定格式的指令。标准结构长这样:

bash
command  [options]  [arguments]

三部分:

  1. command(命令名):动词。「做什么?」——列出文件(ls)、切换目录(cd)、查看手册(man)。
  2. options(选项):副词。「怎么做?」——要看详细信息加 -l,要看隐藏文件加 -a。通常以 - 开头。
  3. arguments(参数):宾语。「对谁做?」——对当前目录,还是对 /usr 目录。

ls 举三个例子,体会一下同一动词的不同用法:

bash
# 光杆司令:只列当前目录的文件名
$ ls
# 预期输出(实际取决于你的目录内容)
Desktop  Documents  Downloads  Music  Pictures  Videos

# 加选项 -l:列出详细信息(权限、大小、时间等)
$ ls -l
# 预期输出
total 24
drwxr-xr-x  2 charlie charlie 4096 Jun 10 10:00 Desktop
drwxr-xr-x  2 charlie charlie 4096 Jun 10 10:00 Documents
drwxr-xr-x  2 charlie charlie 4096 Jun 10 10:00 Downloads

# 加参数 /usr:不看当前目录了,看 /usr
$ ls /usr
# 预期输出
bin  games  include  lib  local  sbin  share  src

Tab 补全:别跟你的键盘过不去

命令成千上万,文件路径更是动辄几十个字符。如果每次都全拼出来,键盘迟早要被敲烂,拼写错误更是家常便饭。

Shell 的设计者早就想到这一点了——Tab 键是你的朋友。

逻辑很简单:你只打前几个字母,然后按一下 Tab。

  • 如果只有一个匹配:Shell 直接帮你把剩下的补全。省时间,还防拼写错误。
  • 如果有多个匹配:Shell 会发出一声提示音。你再按一次 Tab,它把所有可能的候选项列出来供你挑选。

试一下:

bash
# 只输入 if,然后按 Tab 键
$ if
# 如果有多个以 if 开头的命令,再按一次 Tab,Shell 会列出:
if    ifconfig    ifdown    ifquery    ifup

再多输一个字母 c,变成 ifc,再按 Tab——因为只剩 ifconfig 一个匹配,Shell 直接帮你补全。

记住这个习惯:能 Tab 就别手打。 这不是懒,是工程素养。在命令行里,一个字母的错位可能就是「成功执行」和「找不到文件」的区别。

历史记录:你敲过的命令都记着呢

Shell 会把你敲过的每一条命令记下来,存在一个叫 ~/.bash_history 的文件里。

两个最常用的快捷键:

  • ↑ 箭头:往上翻,调出上一条命令。连按可以一直往回翻。
  • Ctrl + R:反向搜索。按下后输入关键词,Shell 会从历史记录里找到最近一条匹配的命令。
bash
# 按 Ctrl+R,然后输入 "apt"
(reverse-i-search)'apt': sudo apt install build-essential

找到了,直接回车执行。不用重新打一遍。

遇事不决问男人:man 和 --help

命令太多,参数太杂,谁也记不全。Linux 内置了两套求助机制。

man(manual)

bash
$ man ls

这会打开一份详细的手册页。在里面用上下键滚动,按 q 退出。

--help

bash
$ ls --help

这会在终端里直接打印一份简要用法说明,不用进入分页模式。大部分命令都支持这个选项。

两个怎么选?想快速看一眼用法,用 --help;想彻底搞懂某个命令的所有行为,用 man


实践层

4.1 打开终端

在 Ubuntu 桌面上,打开终端有三种方式:

  1. 快捷键Ctrl + Alt + T——这是最快的。
  2. 应用菜单:搜索「Terminal」或「终端」。
  3. 右键桌面:选择「在终端中打开」。

如果你用的是 WSL2,在 Windows 搜索栏输入「Ubuntu」点击打开即可,或者用更强大的 Windows Terminal(从 Microsoft Store 免费安装)。

打开后,你会看到类似这样的一行:

bash
charlie@ubuntu:~$

这行叫命令提示符。我们来拆解一下:

部分含义
charlie当前用户名
@分隔符
ubuntu主机名(你装系统时起的)
:分隔符
~当前所在目录。~ 是家目录的简写
$权限标识。$ 表示普通用户,# 表示 root

光标在 $ 后面闪烁——系统在等你下命令。

4.2 敲下你的第一条命令

bash
# 显示当前日期和时间
$ date
# 预期输出
Wed Jun 11 14:30:00 UTC 2026

没有爆炸。Shell 听懂了,内核执行了,结果打印出来了。

再来几条,找找感觉:

bash
# 你是谁?
$ whoami
# 预期输出
charlie

# 这台机器的内核版本
$ uname -r
# 预期输出
5.15.0-XX-generic
# 实际输出可能不同,取决于你的系统版本

# 清屏
$ clear

clear 会把屏幕清干净,只留一行光标。快捷键 Ctrl + L 效果相同。

4.3 求助工具实战

当你拿到一个陌生命令,不知道怎么用——别搜百度,直接问系统。

bash
# 用 man 查看 ls 的完整手册
$ man ls
# 在里面用上下键滚动,按 q 退出

# 用 --help 快速查看用法
$ ls --help
# 预期输出(截取)
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.

  -a, --all                  do not ignore entries starting with .
  -l                         use a long listing format
  -h, --human-readable       with -l, print sizes in human readable format

养成一个习惯:遇到不会用的命令,先 --help,再 man 这个习惯会跟你的整个职业生涯。

4.4 命令提示符的秘密

还记得引子里说的那个光标在闪吗?现在你再看那行提示符,它已经不陌生了。

但还有一个细节值得注意——当你在终端里输入 sudo su 切换到 root 用户后,提示符会变:

bash
$ sudo su
[sudo] password for charlie:
# 输入密码时屏幕不会显示任何字符,盲打后回车即可

root@ubuntu:/home/charlie#

注意末尾:从 $ 变成了 #。这是 Shell 在提醒你——你现在手里拿着最高权限,每一个回车都可能造成不可逆的后果。

⚠️ 高危提醒# 提示符下,你拥有对整个系统的绝对控制权。日常操作请务必退回普通用户(输入 exit),只在需要时用 sudo 临时提权。

退出 root:

bash
root@ubuntu:/home/charlie# exit
exit
charlie@ubuntu:~$

回到 $,安全了。


练习题

走到这里,终端应该不再让你紧张了——或者你以为不紧张了。下面几道题试试手,建议自己敲一遍再看提示。

练习 6.1 ⭐(理解)

打开终端,依次执行 echo $SHELLecho $0。两个输出一样吗?为什么?这和「登录 Shell」与「子 Shell」的区别有关。

提示$SHELL 记录的是你的默认 Shell,$0 记录的是当前正在运行的那个。

练习 6.2 ⭐⭐(应用)

man 查看 history 命令的手册。找到 -c 选项是干什么用的,然后思考:在什么场景下你会需要清空命令历史?

练习 6.3 ⭐⭐⭐(思考)

如果一个命令同时支持 -h--help,它们的行为可能不同吗?写一条命令验证你的猜想。想一想,为什么有些命令用 -h 表示「帮助」,有些用 -h 表示「人类可读」(比如 ls -h)——选项命名冲突的问题是怎么产生的?


本章回响

这一章真正在做的事情,不是教你敲了哪几条命令——而是帮你拆开了一个认知上的黑盒:你面对的那个黑框框,其实是两层东西叠在一起的。外面那层叫终端模拟器,负责显示;里面那层叫 Shell,负责翻译你的指令、和内核对话。把它们搞混不会出什么大事,但当显示出了问题、行为不符合预期的时候,知道该去怪哪一层,会让你省掉很多瞎猜的时间。

Shell 这个翻译官比它看起来要能干得多。Tab 补全帮你防错,历史记录帮你偷懒,man--help 帮你自助。这三样东西加在一起,构成了你在命令行世界里独立生存的基础设施——不需要搜索引擎,不需要问别人,系统本身就能回答你的大部分问题。

还记得开头那个光标在闪的画面吗?现在你再看它,它不再是一个你不知道该怎么回应的问号了。你知道它背后站着一个叫 Bash 的翻译官,你知道该怎么跟它说话,你甚至知道说错了可以去查手册。恐惧的消除,不一定需要掌握多少东西,有时候只需要搞清楚「面前这个东西到底是什么」。

下一章,我们要让这个翻译官干点实事——在文件系统的迷宫里认路、导航、找到你想要的文件。届时你会发现,今天学的命令结构(动词 + 副词 + 宾语)会反复出现在每一个新命令里。


← 上一章下一章 →

Built with VitePress