🍓 第四章 Linux 系统管理
📄 一句话概括

上一章你只是「会用」终端;这一节要把这台机器拆开看——你敲的每一个字,到底被谁接走、被谁读懂、又由谁去执行;命令是从哪儿找出来的(PATH);前台与后台是怎么回事。搞清楚这一层,后面三节(常用指令、权限、目录结构)才不会变成死记硬背。

📝 本节和前面几节的关系

3-1 讲了「终端机是什么」、3-5 讲了「有哪些命令」——本节讲的是它们中间那一层:命令行是怎么运作的。 换句话说:3-5 是「给你一本词典」,本节是「告诉你这门语言的语法」。 读完本节再看 4-2 的常用指令表,你会发现那些命令不是一盘散沙,而是同一个套路的不同零件。

一、先把三个角色摆清楚:终端机、Shell、内核

你在屏幕上敲命令时,其实是三个角色在接力:

角色 大白话 具体是什么
终端机(terminal) 一张「纸」——负责显示和接收你敲的字 窗口程序(如 lxterminal),或你 SSH 连过来的那条通道
Shell(壳) 一个「翻译官」——读你的字,理解意思,转给系统 最常见的是 bash,也可能是 zsh
内核(kernel) 干活的人——真正管 CPU、内存、磁盘、网卡 Linux 内核本体
💡 一句话记忆

终端机是「脸」,Shell 是「嘴」,内核是「手」。 你对着脸说话(打字),嘴把话解释成命令,手去执行。 换终端机不影响命令——同一个命令,在桌面窗口里、在 SSH 里、在图形界面按 F4 弹出的窗口里,结果完全一样(这也是 3-2 那句「图形和命令行是同一个世界」的由来)。

那到底「命令行(command line)」指的是什么? 它指的是用文字下命令这种工作方式,跟「图形界面(点图标)」相对。终端机是干这件事的窗口,Shell 是干这件事的程序。

二、敲下一条命令,机器走了四步

这是本节最值钱的一段。以你敲 ls -l /home 为例:

步骤 谁在做 做了什么
① 接收 终端机 把这一行字交给 Shell
② 拆词 Shell 按空格切成三块:ls(命令)、-l(选项)、/home(参数)
③ 找命令 Shell 去 PATH 列出的几个目录里挨个翻,看哪个目录里有叫 ls 的可执行文件
④ 执行 内核 把找到的程序加载起来跑,结果送回终端机显示

第 ③ 步是新手最常撞墙的地方,后面第五节单独讲。

还有一件常被忽略的事:Shell 在执行前,还会自己动手做几件「预处理」,比如:

所以有一句行家话:「你面对的不是命令,是 Shell。」 出错时先分清是 Shell 没理解你的意思(语法错),还是命令本身报的错(执行错)——这两类错的修法完全不同。

三、打开终端机的六种方式(比 3-5 多三种)

3-5 给过三种,这里补全,并告诉你各自什么时候用:

# 方式 怎么用 特点 / 什么时候用
1 桌面快捷键 Ctrl + Alt + T 最快,桌面在手边时首选
2 菜单 主菜单搜 terminal 快捷键失效时的退路
3 文件管理器里按 F4 在某个目录里就地开终端 路径自动落在该目录,最省事(3-2 讲的)
4 SSH 远程 从 Windows 用 ssh 用户名@主机 无头模式唯一的路(2-5 讲的)
5 虚拟控制台 按 Ctrl + Alt + F1~F6 图形界面卡死时的救命通道;Ctrl + Alt + F7(或 F1)切回桌面
6 开机自动进命令行 sudo raspi-config 里设开机方式 服务器用法,2-4 提过
⚠️ 第 5 条值得单独记一笔

图形界面点不动了、窗口全卡住,别急着拔电——按 Ctrl + Alt + F2(或 F1~F6 任一),你会看到一个纯黑底白字的登录提示,这是同一个系统的另一个「入口」,tty 虚拟控制台。 在这里登录后 sudo reboot 就能救回来。这是 3-2 那条「拔电永远是最后一步」的底气所在。

四、一条命令的三个部件(复习 + 升级)

部件 位置 例子里是 说明
命令 第一个词 ls 程序名
选项(option) 一般以 - 开头 -l 调行为;-l 短选项,--long 长选项,多数命令两者等价
参数(argument) 命令作用的对象 /home 路径、文件名、字符串

三条实用规则(3-5 提过,这里给出原因):

  1. 短选项能合并:ls -l -a = ls -la(Shell 不管,是 ls 自己认的规矩)。
  2. 选项和参数的顺序,只有命令自己在意:一般要先写选项,但很多命令也接受 ls /home -l(不推荐)。
  3. -- 是分界线:如果文件名本身以 - 开头(比如 -weird.txt),写 rm -- -weird.txt 告诉命令「后面这个是文件名,不是选项」。
💡 一个几乎万能的救命选项

不记得某命令怎么用? 分别试这三招(从轻到重):

ls --help      # 短说明,最快
man ls         # 完整说明书,按 q 退出
man -k 关键词   # 按关键词找命令,例:man -k password

man ls 里按 / 可以搜关键词,按 n 跳到下一个匹配。

五、命令到底住在哪里:PATH 与「命令的三种出身」

PATH 是一串目录清单,Shell 找命令时按这个清单从左到右挨个翻。

echo $PATH
# 典型输出(用冒号分隔):
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

看这个输出要读出三件事:

查一个命令的底细,用这四个:

命令 干什么 例子
which 命令 找出它在哪个目录(最常用) which python3
type 命令 看出它属于哪一类(下面那张表) type cd
command -v 命令 同上,但更适合写脚本(结果最标准) command -v git
whereis 命令 连程序、源码、手册一起找 whereis bash

用 type 能看出命令的三种出身——这是本节最容易被跳过、又最有用的一点:

出身 type 的输出 例子 说明
内建(builtin) cd is a shell builtin cd、echo、pwd Shell 自己实现的,磁盘上没有这个可执行文件!所以 which cd 查不到是正常的
外部程序 ls is /usr/bin/ls ls、apt、python3 磁盘上一个真实文件,靠 PATH 找到
别名(alias) ll is aliased to 'ls -l' 常有人把 ll 设成 ls -l 你或系统起的昵称,只是替换文字
⚠️ 为什么这件事重要

有人照着教程敲 which cd,返回空,就以为「系统坏了」——没坏,cd 是内建命令,本来就不在磁盘上。同理,看到别人的 type ll 有输出、自己全无,那只是因为对方设了别名。先分清出身,再谈「命令找不到」。

顺手认一下别名的两个动作(可选,知道有这回事就行):

alias                    # 列出当前所有别名
alias ll='ls -l'         # 临时加一个(关掉这个终端就没了)

六、命令的输出不只有一路:三个「流」

3-5 讲了 > 和 >>,这里补上它们的完整版图。

Unix 给每个命令配了三个标准通道:

编号 名字 装什么 重定向写法
0 标准输入 stdin 命令要读的输入 <
1 标准输出 stdout 命令正常的结果 > 或 >>
2 标准错误 stderr 命令报错的信息 2>

这就解释了一件新手常困惑的事:为什么 ls 不存在的文件 > out.txt,屏幕上照样跳出错误提示、而 out.txt 里是空的?

因为报错走的是第 2 路(stderr),而 > 只搬第 1 路(stdout)。 两条路各走各的。

把两路都收进同一个文件:

写法 含义 备注
命令 > all.txt 2>&1 正常输出和报错都进 all.txt 传统写法,最好认
命令 &> all.txt 同上 bash 简写,更短
命令 > /dev/null 2>&1 全都扔掉(静默) 写脚本时常用来「假装没这回事」
命令 2> err.txt 只把报错收进文件 排查问题时特别有用
💡 `/dev/null` 是什么

它是系统的「黑洞文件」——写进去的东西直接消失,永远读不回来。想「不看到输出但保留命令效果」(比如定时任务里不想被刷屏),就把它扔进这里。

七、前台、后台与作业控制(3-5 完全没讲的一层)

前台=命令占用着你的终端,你得等它跑完才能敲下一条。 后台=命令在背后跑,你立刻能把终端拿回来。

动作 键 / 命令 说明
打断当前命令 Ctrl + C 最常用的「救命键」——命令卡住了、跑太久、刷屏了,按它
暂停并退回提示符 Ctrl + Z 与 Ctrl + C 不同:它是挂起,没杀死
让命令在后台跑 命令末尾加 & 如 python3 long_task.py &
看后台有哪些作业 jobs 给每个作业一个编号 [1]、[2]
把作业拉回前台 fg(或 fg %1) 回去继续看着它
让挂起的作业在后台继续 bg 配合 Ctrl + Z 用

再区分一个极易混淆的概念:

⚠️ 关掉终端会怎样

用 & 放在后台的程序,多数会跟着终端一起结束(因为它是这个 Shell 的孩子)。 想让它真正「断线也活着」,要用 nohup 命令 & 或 setsid,或者干脆做成 systemd 服务。 别指望 & 能保命——这是很多教程一带而过、新手却踩得最疼的一点。

八、命令「成功还是失败」:退出码 $?

每个命令跑完,都会留下一个数字表示结果:

数值 含义
0 成功
非 0(1~255) 失败,具体数字由程序自己定义
ls /home
echo $?      # 输出 0 —— 上一条命令成功了

ls /不存在的目录
echo $?      # 输出 2 —— 上一条命令失败了

这在写脚本时是核心:if、&&、|| 全靠它判断。你现在只需要记住一件事:

&&=前面成功才继续(前面失败就停),||=前面失败才执行后面。 例:sudo apt update && sudo apt upgrade——更新索引成功,才去升级,这是最常用的组合(4-5 会反复用到)。

九、动手 Demo:让机器把你的「出身」讲一遍

在树莓派上(桌面终端或 SSH 里都行)依次跑这七步:

# 1. 你现在是谁、在哪个 Shell 里
whoami
echo $SHELL

# 2. 看命令是从哪些目录找出来的
echo $PATH

# 3. 三种出身各验一个
type cd
type ls
alias ll 2>/dev/null || echo "(没有 ll 这个别名,正常)"

# 4. 同一条命令,分别用「外部程序」和「内建」两种身份看
command -v echo
type echo

# 5. 看退出码:先成功,再失败
ls /home
echo $?
ls /this_does_not_exist
echo $?

# 6. 两条流分开收
ls /home /this_does_not_exist > out.txt 2> err.txt
echo "--- out.txt ---"; cat out.txt
echo "--- err.txt ---"; cat err.txt

# 7. 收尾:命令卡住时怎么脱身(先跑一个长命令,再按 Ctrl + C)
sleep 100

看到什么算成功:

步骤 预期看到
1 你的用户名;/bin/bash(或 /usr/bin/bash——它俩是同一个文件,4-4 会解释)
3 第一行含 shell builtin;第二行含 /usr/bin/ls;第三行要么列出一个别名,要么打印「(没有…正常)」
4 command -v echo 很有可能有输出,但 type echo 说它是 builtin——因为在多数系统里 Shell 内建的同名命令会优先
5 第一次 0;第二次非 0(常见是 2)
6 out.txt 里是 /home 下的内容;err.txt 里是那句报错——两条流真的分开了
7 屏幕停住不动,按 Ctrl + C 立刻回到提示符

做完之后检查一下(两条流那个实验留下的文件):

ls -l out.txt err.txt
rm out.txt err.txt

「读结果」提示:第 6 步是本节的核心验收——它把「报错不算输出」这件事从说法变成了你看得见的事实。第 7 步是保命技能:以后任何命令刷屏不止、卡着不动,第一反应就是 Ctrl + C。

十、30 秒实验

验证「Shell 先摊开通配符」这句话。

  1. 建三个文件:
mkdir -p ~/wildcard_test && cd ~/wildcard_test && touch a.txt b.txt c.log
  1. 用 echo 看通配符被换成了什么(echo 只是把收到的词原样打印):
echo *.txt
echo *
  1. 清理:
cd ~ && rm -r ~/wildcard_test

你会看到:echo *.txt 打印 a.txt b.txt;echo * 打印三个文件。echo 根本不知道有通配符这回事——是 Shell 在把 *.txt 交给它之前就已经换好了。

这 30 秒你收获的是:以后写 rm *.log 这种命令时,你会知道真正决定删哪些文件的是 Shell,所以「先 echo 看一眼再 rm」这个保命习惯(3-5 提过)是有原理支撑的,不是迷信。

十一、常见误区

自测三问 1. 终端机、Shell、内核各干什么?一句话说清。(**终端机是脸——收字显示;Shell 是嘴——解释你的意思;内核是手——真正干活**) 2. 敲一条命令时,Shell 会自己先做哪三件「预处理」?(**摊开通配符;处理重定向与管道;把 `$变量` 换成值**) 3. 为什么 `ls 不存在的文件 > out.txt` 里,报错仍然显示在屏幕上?(**报错走 stderr(第 2 路),而 `>` 只搬 stdout(第 1 路);要连报错一起收得写 `> out.txt 2>&1`**)

相关笔记