Linux 学习笔记(二):终端、Shell 与文件系统——走进 Linux 的日常工作现场
第二课:Linux 的工作现场——终端、Shell、文件系统与权限
本课定位:第一课回答了“Linux 是什么、为什么存在、内部大致有哪些层”。这一课开始进入每天真正使用 Linux 的现场:你怎样向系统发出命令,命令运行在哪里,文件放在哪里,为什么有些操作被拒绝,以及串口和 SSH 到底分别连接到了什么。
1. 本课目标
学完本课后,应当能够回答以下问题:
- 终端、终端模拟器、Shell 和命令分别是什么?
- 一行命令从敲下回车到出现输出,经历了什么?
- Linux 的路径、当前目录、绝对路径和相对路径分别是什么意思?
/home、/etc、/dev、/proc、/sys、/run等目录为什么存在?- 用户、组、root、
sudo和文件权限分别解决什么问题? - 标准输入、标准输出、标准错误、管道和重定向如何组合?
- 串口 Shell、SSH Shell 与本机终端有什么共同点和不同点?
- 怎样在不破坏系统的前提下观察 Linux?
2. 你面对的不是“黑框”,而是一条工作链
刚开始使用 Linux 时,终端窗口很容易被理解成“一个可以输入命令的黑框”。这不算错,但太粗糙。实际至少有几层东西在协作:
键盘输入
↓
终端模拟器或串口程序
↓ 字符流
Shell(例如 Bash)
↓ 解析命令、启动程序、建立管道和重定向
普通用户程序
↓ 系统调用
Linux 内核
↓
文件、进程、终端设备、网络设备、硬件
如果你通过 SSH 连接远端主机,或通过串口连接一台无屏设备,前半段会不同,但 Shell、普通程序和内核之间的关系仍然相似。
2.1 终端的历史含义
早期大型计算机不一定自带显示器和键盘。用户通过电传打字机或独立终端与主机通信。终端负责输入和输出,真正运行程序的是远处的主机。
今天的图形化 Linux 桌面里,常见的“终端窗口”通常是终端模拟器:它用图形窗口模拟传统字符终端,向其中运行的 Shell 传递字符,并显示程序输出。
所以“打开终端”并不等于“打开了 Linux 内核”。你通常是启动了一个图形程序,它再为你启动一个 Shell。
2.2 Shell 是命令解释器
Shell 的原义是“外壳”。内核处于系统核心,Shell 作为用户交互层,帮助你:
- 读取输入的一行文本;
- 按规则拆分、展开和解释它;
- 找到要执行的程序;
- 创建子进程运行程序;
- 连接文件、终端、管道和网络输入输出;
- 等待结果并显示下一个提示符。
Bash 是最常见的 Shell 之一;还有 Zsh、Fish、Dash、BusyBox ash 等。它们的交互体验和脚本语法有差异,但都在做“把文字组织成程序执行”的工作。
先查看当前 Shell:
printf '%s\n' "$SHELL"
ps -p $$ -o pid,ppid,tty,comm,args
这里的 $$ 是当前 Shell 的进程号。第二条命令没有修改系统,只是让 ps 显示当前 Shell 的 PID、父进程、关联终端和启动参数。
2.3 提示符不是装饰
你常会看到类似:
caige@host:~/work$
它通常包含用户名、主机名和当前目录。末尾的符号也常表达权限:
$:普通用户;#:root 用户。
这是一种惯例,不是内核强制规则。提示符可以被用户改成任何样子,所以真正判断身份要使用:
id
whoami
在不同系统的本地终端、SSH 会话或串口会话中,可能看到:
user@host:~$
root@device:~#
前者通常表示普通用户,后者通常表示 root 用户。它说明你进入了某台机器的命令解释环境;提示符的外观可以自定义,真正的身份仍应以 id 的输出为准。
3. 一条命令如何被理解
先看一条简单命令:
ls -l /etc
它可以粗略分成三部分:
ls -l /etc
│ │ │
程序名 选项 参数
ls是程序名;-l是选项,要求使用较详细的列表格式;/etc是参数,告诉程序要列出哪个目录。
Shell 并不“天然懂得” ls 怎么列目录。它先按照自己的语法处理这行文字,再根据 PATH 环境变量寻找可执行文件,最后创建进程运行它。ls 再通过系统调用请求内核读取目录内容。
3.1 命令名从哪里找到
查看搜索路径:
printf '%s\n' "$PATH"
输出通常是一串用冒号分隔的目录,例如:
/usr/local/bin:/usr/bin:/bin
当你输入 ls,Shell 会按顺序在这些目录中查找同名可执行文件。可以这样确认实际找到的是哪一个:
command -v ls
type ls
type 特别有用,因为一个名字不一定是独立程序:它可能是 Shell 内建命令、别名、函数或外部可执行文件。
type cd
type echo
type sudo
通常 cd 是 Shell 内建命令。原因很直接:改变目录必须改变当前 Shell 进程的状态。如果把 cd 做成一个独立子进程,它只能改变自己的目录,退出后你的 Shell 仍留在原地。
3.2 引号、空格和通配符
Shell 不会把输入机械地按空格切开;它还要处理引号、变量、通配符和转义符。
printf '<%s>\n' hello world
printf '<%s>\n' "hello world"
printf '<%s>\n' 'hello world'
第一条会得到两个参数,后两条把 hello world 作为一个参数。单引号通常保留其中文字的字面含义;双引号通常仍允许 $变量 展开。
name='Taishanpi'
printf '%s\n' "$name"
printf '%s\n' '$name'
通配符由 Shell 展开,不是 ls 自己理解的:
printf '%s\n' /etc/*.conf
这会在当前系统中匹配 /etc 下以 .conf 结尾的文件。因为匹配结果取决于真实文件,请先把它当作观察命令,不要对通配符匹配结果执行删除或覆盖操作。
3.3 环境变量与当前目录
环境变量是一组传递给新进程的名称和值。常见例子:
printf 'HOME=%s\n' "$HOME"
printf 'USER=%s\n' "$USER"
printf 'PATH=%s\n' "$PATH"
pwd
HOME 是当前用户的家目录,PATH 决定命令搜索位置,pwd 显示当前工作目录。它们都属于用户空间约定,不是“硬盘上的固定地址”。例如 root 的家目录常为 /root,普通用户的家目录通常在 /home/用户名。
4. 从 / 开始:路径与目录树
Linux 文件系统只有一个目录树根:/。无论硬盘、U 盘、临时内存文件系统还是网络文件系统,挂载后都会出现在这棵树的某个位置。
/
├── home
│ └── caige
├── etc
├── usr
├── var
├── dev
├── proc
├── sys
├── run
└── tmp
4.1 绝对路径与相对路径
以 / 开头的路径是绝对路径,从整个目录树的根开始计算:
/etc/os-release
/home/caige/workspaces
不以 / 开头的路径是相对路径,从当前工作目录开始计算:
notes/02-terminal-shell-filesystem-permissions.md
../materials
两个特殊名字几乎每天都会用到:
.:当前目录;..:当前目录的父目录。
安全练习:
pwd
ls
ls .
ls ..
cd ..
pwd
cd .. 会改变当前 Shell 的工作目录。结束练习后可用 cd - 返回上一个目录,或 cd 直接回到自己的家目录。
4.2 文件名不是“文件类型”
Linux 不通过扩展名强制决定文件类型。report.txt、program、Image 都只是文件名。能否执行主要由权限位、文件内容、解释器声明和 CPU 架构共同决定。
使用 file 观察真实类型:
file /bin/ls
file /etc/os-release
file /dev/null
你会看到普通可执行文件、文本文件和设备文件之间明显不同。设备文件后面会在第 6 节解释。
4.3 隐藏文件
Linux 中名字以 . 开头的文件或目录默认不会被普通 ls 显示:
ls -la ~
例如 .bashrc 常用于 Bash 的交互配置。它不是安全机制;“隐藏”只是一种显示习惯。重要配置依然需要正确的权限和备份。
5. 常见目录各自负责什么
Linux 发行版之间会有差异,但下表能帮助你读懂大多数系统。
| 路径 | 通常内容 | 为什么你会关心 |
|---|---|---|
/ |
根目录 | 所有路径的起点 |
/home |
普通用户家目录 | 个人代码、配置和文件通常放这里 |
/root |
root 的家目录 | 不等于整个根目录 / |
/etc |
系统级配置 | 网络、服务、用户等配置常在这里 |
/usr |
大量用户空间程序、库、共享资源 | /usr/bin、/usr/lib 很常见 |
/bin、/sbin |
基础命令的兼容入口 | 现代发行版常把它们链接到 /usr/bin、/usr/sbin |
/var |
会不断变化的数据 | 日志、缓存、队列、数据库数据等 |
/tmp |
临时文件 | 文件可能被清理,不适合放长期成果 |
/run |
本次启动期间的运行状态 | PID 文件、套接字、临时运行信息,重启后通常消失 |
/boot |
引导相关文件 | 普通 PC 常放内核和引导器配置;嵌入式设备布局可能不同 |
/dev |
设备节点 | 串口、磁盘、终端等的用户空间入口 |
/proc |
进程和内核状态的虚拟视图 | cpuinfo、meminfo、cmdline 等观察入口 |
/sys |
设备模型与驱动状态的虚拟视图 | 网卡、GPIO、总线、模块、供电等观察入口 |
/mnt、/media |
临时或可移动介质挂载点 | U 盘、数据盘常出现在这里 |
/opt |
可选的附加软件 | 第三方软件有时使用 |
5.1 /etc 不是“所有配置都在这里”
/etc 是系统级配置的重要位置,但今天的软件也可能在以下位置读取配置:
- 用户家目录中的
.config/; /usr/lib/的默认配置;/run/中运行时生成的配置;/var/lib/中服务自己的数据;- 内核命令行、设备树或固件文件。
因此排错时不能只猜“配置一定在 /etc”。要先看该程序的文档、日志和启动参数。
5.2 /proc 和 /sys 不是普通磁盘文件
下面命令读起来像打开文件:
cat /proc/cpuinfo
cat /proc/meminfo | head
cat /sys/class/net/wlan0/operstate
但 /proc 和 /sys 多数内容由内核在读取时动态生成,不一定真正占据磁盘块。它们是内核向用户空间暴露状态和控制入口的接口。
这也带来一个重要习惯:有些虚拟文件可写,而写入会立即影响内核行为。 初学阶段先以读取为主。看到网上的 echo 某个值 > /proc/... 或 > /sys/... 命令时,先弄清它改变哪一项内核或设备状态,再考虑执行。
5.3 /dev 把设备呈现为可打开的对象
例如:
ls -l /dev/tty*
ls -l /dev/null /dev/zero
/dev/ttyUSB0 这类名字可能对应 USB 串口适配器;/dev/ttyS*、/dev/ttyAMA*、/dev/ttyFIQ0 等则可能对应 SoC UART。名字与驱动、硬件平台有关,不能机械套用。
/dev/null 是一个经典设备:写入它的数据会被丢弃,读取通常立即得到文件结束。它适合说明“设备也可以通过文件描述符读写”,不是让人随意丢弃有价值的输出。
6. 文件系统、挂载和“磁盘在哪儿”
“目录”和“磁盘分区”不是同一个概念。
- 目录是文件系统命名空间中的位置;
- 分区是块设备上的一段范围;
- 文件系统是把块组织成目录、文件、权限和元数据的格式;
- 挂载是把某个文件系统接入目录树某一点的动作。
块设备 /dev/nvme1n1p5
↓
ext4 文件系统
↓ 挂载
目录树中的 /
你本机当前根文件系统正是一个 ext4 文件系统,挂载在 /。SDK 之前放在 NTFS 数据盘时,厂商 build.sh 拒绝继续;复制到 ext4 工作区后才通过检查。这个例子说明:路径看起来像普通目录,底层文件系统类型却可能影响权限、符号链接、大小写、时间戳和构建工具行为。
安全观察命令:
findmnt /
df -hT
lsblk -f
findmnt /:从挂载关系看根目录来自哪里;df -hT:看已挂载文件系统的容量和类型;lsblk -f:看块设备、分区、文件系统和挂载点。
不要把 df 的输出理解成“物理磁盘的全部布局”。它只关注已挂载的文件系统;而 lsblk 更接近设备和分区视角。
7. 用户、组与 root:为什么系统会拒绝你
Linux 是多用户系统。即使你一个人使用电脑,系统仍以用户身份、用户组和权限规则组织资源。
进程以某个用户身份运行
↓
请求访问一个文件、设备或系统资源
↓
内核根据 UID、GID、权限位、ACL、能力与安全策略判断
↓
允许,或者返回 Permission denied
7.1 UID、GID 和组
- UID:用户标识符;
- GID:主组标识符;
- 附加组:用户还可以属于多个组,用于共享权限。
观察自己的身份:
id
groups
在 Linux 主机上,串口权限常通过 dialout、uucp 或发行版定义的其他组授予。不要因为“打不开 /dev/ttyUSB0”就立刻使用 root;先查看设备权限和自己的组。
ls -l /dev/ttyUSB0
id
如果设备不存在,上面的第一条会报错;那通常意味着当前没有这个设备节点或名字不同,而不是权限问题。
7.2 root 是什么
root 通常指 UID 为 0 的超级用户。它可以绕过很多普通的文件权限检查,因此能做系统管理,但也更容易把错误的命令作用到整个系统。
root 不是“更懂 Linux 的用户”,也不是普通操作的默认身份。日常编辑代码、查看日志和运行构建,都应优先使用普通用户。需要明确的系统管理权限时,再使用 sudo 获得短时间、单次命令范围内的提升。
sudo -v
sudo systemctl status ssh
第一条可能要求验证你的密码,但不修改系统;第二条只是读取服务状态。sudo 的含义不是“请永远相信我”,而是“在允许的策略下,以另一身份执行这条明确的命令”。
7.3 su 与 sudo 的区别
su 切换到另一个用户的 Shell
sudo 某条命令 只以更高权限运行这一条命令
sudo -i 打开一个 root 登录式 Shell
它们都可能获得高权限,但使用场景不同。某些精简系统或恢复环境可能只提供 root Shell;作为日常开发习惯,应尽量让高权限操作短、小、可审查。
7.4 文件权限的十个字符
执行:
ls -l /etc/os-release
可能看到类似:
-rw-r--r-- 1 root root ... /etc/os-release
最前面的十个字符可这样读:
- rw- r-- r--
│ │ │ └─ 其他用户的权限
│ │ └───── 文件所属组的权限
│ └───────── 文件所有者的权限
└──────────── 文件类型:- 普通文件,d 目录,l 符号链接等
每组三个字符分别是:
r:read,读取;w:write,写入;x:execute,执行。
对于普通文件,x 常表示可作为程序执行。对于目录,含义更微妙:
r:可以读取目录条目列表;w:可以在目录中创建、删除或改名条目,通常还受其他条件影响;x:可以穿过该目录访问已知名字的内容。
所以目录缺少 x 时,即使你能看到名字,也可能无法进入或访问里面的文件。
7.5 chmod、chown 为什么要谨慎
chmod 改权限,chown 改所有者。它们是必要工具,但初学者不应把它们当成“权限报错万能修复键”。
尤其要避免:
chmod -R 777 某个目录
sudo chown -R 当前用户 /
第一条会把目录树递归地开放给所有人读、写、执行;第二条可能破坏整个系统的所有权和安全边界。遇到权限问题,更好的顺序是:
- 确认实际目标路径,没有拼错;
- 用
ls -ld 路径查看目录本身的属主与权限; - 用
id查看当前用户和组; - 判断操作本来是否应该由普通用户完成;
- 只对必要的一个文件或目录做最小改动。
8. 标准输入、标准输出与标准错误
每个普通进程启动时,通常都带有三条最基本的文件描述符:
| 编号 | 名称 | 默认去向 |
|---|---|---|
| 0 | 标准输入,stdin | 键盘或上游程序 |
| 1 | 标准输出,stdout | 终端窗口或下游程序 |
| 2 | 标准错误,stderr | 终端窗口 |
程序把正常结果写到 stdout,把错误或诊断消息写到 stderr。它们默认都显示在终端,所以初看时很像同一种输出;但 Shell 可以把它们分别接到不同位置。
8.1 管道:把一个程序的输出交给另一个程序
ip link | less
| 会创建管道,把左侧命令的标准输出送到右侧命令的标准输入。这个例子把较长的网卡信息交给 less 分页查看。
再看一个:
findmnt | grep -E 'ext4|ntfs'
这不是魔法:findmnt 输出文本,grep 从文本中筛选包含 ext4 或 ntfs 的行。管道是 Unix 工具组合能力的核心之一。
注意:普通管道默认只连接 stdout。若左侧程序把错误写到 stderr,它仍会直接显示在终端。
8.2 重定向:改变输入和输出的位置
常见符号:
> 文件 把标准输出写入文件;会覆盖已有文件
>> 文件 把标准输出追加到文件末尾
< 文件 让程序从文件读取标准输入
2> 文件 把标准错误写入文件;会覆盖已有文件
2>&1 让标准错误去往标准输出当前去向
为了理解,先在自己可写的临时目录中练习:
mkdir -p ~/tmp/shell-lesson
printf 'first line\n' > ~/tmp/shell-lesson/example.txt
printf 'second line\n' >> ~/tmp/shell-lesson/example.txt
cat ~/tmp/shell-lesson/example.txt
> 真的会覆盖目标文件。把练习限制在新建的专用目录,是为了让错误不会伤到项目文件或系统配置。
保存命令的正常输出和错误输出:
ls /etc /path/that-does-not-exist > ~/tmp/shell-lesson/out.txt 2> ~/tmp/shell-lesson/err.txt
cat ~/tmp/shell-lesson/out.txt
cat ~/tmp/shell-lesson/err.txt
第二个路径故意不存在,因此它的报错进入 err.txt,而 /etc 的正常列表进入 out.txt。实际工作中,这种分离很适合保存构建日志。
8.3 不要迷信 2>&1
2>&1 的意思是把 stderr 接到 stdout 当前的位置,因此顺序很重要:
command > log.txt 2>&1
这里两种输出都会进入 log.txt。而:
command 2>&1 > log.txt
会先让 stderr 指向当时的终端 stdout,再把 stdout 改到文件;结果可能不是你想要的。初学阶段只需要记住常见、安全的写法:
command > log.txt 2>&1
9. 进程、前台与后台
Shell 启动外部程序时,程序会成为一个进程。进程不是“一个应用图标”,而是一个正在运行、拥有 PID、地址空间、打开文件和权限身份的执行实体。
观察当前终端中的进程:
ps -ef | head
ps -p $$ -o pid,ppid,tty,stat,comm,args
9.1 前台任务
前台任务通常占用当前终端:Shell 等待它结束,你的键盘输入也交给它。例如:
sleep 30
执行后,30 秒内不会出现新的 Shell 提示符。按 Ctrl+C 会向前台进程组发送中断信号,通常使它结束。Ctrl+C 不是“关闭终端”,而是终端驱动配合 Shell 和信号机制提供的约定。
9.2 后台任务
命令末尾加 & 可以让 Shell 把任务放到后台:
sleep 30 &
jobs
这适合短时间的交互实验。长期服务不应靠“终端后面挂一个 &”管理;发行版通常使用 systemd、OpenRC 或 BusyBox init 的服务机制。
9.3 进程与线程不是一回事
初步理解即可:进程通常拥有独立的虚拟地址空间和资源视图;线程是同一进程内部可以并发执行的多个执行流。ps 主要从进程视角展示信息,某些参数可以进一步显示线程。
以后你看到“SSH 连不上”“Wi-Fi 没起来”时,需要区分:是程序没有启动、启动后退出、仍在运行但配置错误,还是内核驱动层根本没有设备。不要把所有问题都归为“程序卡住了”。
10. 串口、SSH 与本机终端:同一类交互,不同链路
无屏设备最容易混淆的地方之一,是把“我打开了一个终端”误认为“我已经连上远端设备”。实际上终端窗口只是本机程序;它到底连接到谁,取决于底层链路。
本机终端
图形终端模拟器 → 本机 Shell → 本机 Linux 内核
串口终端
串口程序 → USB-TTL / UART 字节流 → 设备串口 → 设备 Shell
SSH 终端
ssh 客户端 → TCP/IP 网络 → sshd → 远端设备的伪终端与 Shell
10.1 串口为什么是保底入口
嵌入式 Linux 设备的调试串口通常可以看到 Bootloader、内核和用户空间启动日志。它不依赖:
- Wi-Fi 驱动已经工作;
- 有效 IP 地址;
- 路由器或 DHCP;
- SSH 服务已经启动;
- 根文件系统中的用户配置已经正确。
因此,当系统没有启动、没有网或 SSH 不通时,先看串口。串口参数、信号电平和接线方式由具体硬件决定;常见原则是 TX/RX 交叉、GND 共地,且不能把不确定用途的供电引脚随意连接。
10.2 SSH 为什么适合日常使用
当系统已经能上网且 OpenSSH server 正常运行时,SSH 比串口更适合日常开发:
- 复制文本方便;
- 可使用多个窗口;
- 可传输文件;
- 可进行远程编辑、Git 操作和调试;
- 不会被内核启动日志持续冲掉输入行。
但 SSH 是更靠后的能力。它失败时,应按层排查:板是否启动、网卡是否出现、是否关联 Wi-Fi、是否获得 IP、是否能到达主机、sshd 是否运行、账号和密钥是否正确。
10.3 你在哪台机器上执行命令
这是远程与嵌入式 Linux 学习中必须养成的习惯。每次执行命令前先问:它运行在本机,还是远端目标设备?
| 任务 | 通常运行位置 |
|---|---|
| Git、编辑源码、交叉编译 | x86_64 Linux 开发主机 |
build.sh、Buildroot、内核编译 |
x86_64 Linux 开发主机 |
| 查看 U-Boot/内核早期日志 | 开发主机上的串口程序接收板端输出 |
uname -a、ip link、挂载 rootfs |
远端 Linux 目标设备 |
SSH 登录命令 ssh 用户@地址 |
开发主机发起,远端设备接收 |
例如,主机上的 uname -m 很可能输出 x86_64,而许多 ARM 设备上的同一命令会输出 aarch64。命令一样,观察对象不同。
11. 帮助系统:先问系统,再问搜索引擎
Linux 的命令往往选项很多,死记硬背效率很低。先建立查帮助的习惯:
ls --help | less
man ls
man hier
man 5 passwd
命令 --help:快速列出该程序支持的选项;man 命令:查看手册页;man hier:某些系统提供目录层次结构说明;man 5 passwd:查看第 5 类手册页中的文件格式说明,而不是同名用户管理命令。
常见手册页分类:
| 章节 | 通常内容 |
|---|---|
| 1 | 用户命令 |
| 2 | 系统调用 |
| 3 | 库函数 |
| 4 | 设备和特殊文件 |
| 5 | 文件格式与配置文件 |
| 8 | 系统管理命令 |
嵌入式 Buildroot 系统通常比桌面发行版小,未必安装 man 页面。这时可在开发主机查手册,也可用 命令 --help、项目文档和源码注释辅助理解。
12. 一套安全的日常观察命令
下面命令以“读取、列出、查询”为主,适合作为刚开始的工具箱。
12.1 身份与位置
id
hostname
pwd
uname -a
12.2 文件与目录
ls -lah
findmnt
df -hT
lsblk -f
12.3 进程与服务
ps -p 1 -o pid,comm,args
ps -ef | less
systemctl --failed
最后一条只适合使用 systemd 的系统。Buildroot 默认可能使用 BusyBox init,因此没有 systemctl 并不代表系统坏了;它只说明服务管理器不同。
12.4 网络
ip link
ip address
ip route
ping -c 3 1.1.1.1
ping -c 3 1.1.1.1 会发送三个 ICMP 回显请求。它适合在已知网络可用的环境测试连通性;若网络策略禁止 ICMP,失败不必然表示完全不能联网。
12.5 内核与设备
dmesg | tail -n 80
lsmod
cat /proc/cmdline
ls -l /sys/class/net
不同发行版可能限制普通用户读取 dmesg。不要为了看一眼日志就不加判断地把整台系统切到 root;先理解该发行版的权限策略。
13. 一次受控的小练习:建立自己的实验目录
学习命令时,最好的习惯是把会产生文件的实验限制在一个明确目录中。下面示例只会在自己的家目录下创建内容:
mkdir -p ~/linux-learning/lab-02
cd ~/linux-learning/lab-02
pwd
printf 'hello from lesson 02\n' > hello.txt
ls -l
cat hello.txt
接着观察权限和类型:
stat hello.txt
file hello.txt
最后验证标准错误分流:
ls hello.txt missing.txt > normal.log 2> error.log
cat normal.log
cat error.log
这个实验故意让 missing.txt 不存在。正常结果和报错分别写入两个文件;请先读懂它们,再继续下一步。练习完成后,即使你删除整个 ~/linux-learning/lab-02,影响也只在自己的练习目录内。
14. 常见误解
误解 1:终端就是 Shell
终端模拟器、SSH 客户端或串口程序负责传递字符;Shell 是解释命令的程序。它们常一起出现,但不是同一个东西。
误解 2:# 就是“危险模式”
# 通常表示 root 提示符,但提示符本身可以修改。真正关键是 id 的输出,以及你准备执行的命令是否会改变系统。
误解 3:看见 Permission denied 就 sudo
权限被拒绝可能是路径错误、设备不存在、文件系统只读、ACL 或安全策略限制。sudo 只能改变执行身份,不能修复错误路径、坏驱动或只读介质。
误解 4:/root 就是 /
/ 是整个目录树的根;/root 只是 root 用户通常的家目录,类似普通用户的 /home/用户名。
误解 5:所有 /proc、/sys 文件都存在于硬盘
它们大多是内核动态提供的虚拟接口。读取通常是观察状态,写入可能立即改变系统或硬件行为。
误解 6:删除文件只和它所在目录的权限有关
删除一个文件主要受父目录的写与执行权限控制,而不是只看文件本身是否可写。这是初学权限时很反直觉的一点。
误解 7:管道会自动传递所有报错
普通 | 默认只连接标准输出。标准错误仍会走向终端,除非显式重定向。
误解 8:能 SSH 就不需要串口
SSH 依赖目标系统、网络和服务都已正常。启动早期、Wi-Fi 故障或 rootfs 无法挂载时,串口才是保底入口。
误解 9:所有 Linux 都有 systemctl
systemctl 是 systemd 的管理客户端。精简系统可能使用 BusyBox init,其他发行版也可能采用不同初始化体系;同样是 Linux 内核,用户空间工具可以不同。
15. 面向 Linux 项目的工作习惯
从现在起,把工作明确分成三类位置:
开发主机的家目录
├─ 源码工作区:例如 ~/workspaces/...
├─ 学习项目:例如 ~/linux-learning/...
└─ 临时实验:例如 ~/tmp/...
NTFS 数据盘
└─ 原始资料、下载包和参考副本
远端 Linux 设备
├─ 串口:用于早期启动日志与恢复
└─ SSH:用于网络正常后的日常操作
对应的规则是:
- 在适合项目要求的工作区构建软件;
- 原始资料、下载包和重要配置不随意改动;
- 远端命令先标明“这是在目标设备执行”;
- 带有
>,rm,dd,mkfs,mount,flash等写入或破坏含义的命令,执行前先确认目标; - 不因为方便而长期使用 root;
- 碰到异常,先保存完整输出和当时所在机器,再尝试修复。
这几条听起来朴素,却会直接决定之后排查“本机编译问题、网络问题、串口问题还是远端系统问题”时是否混乱。
16. 本课总结
- 终端程序负责字符输入输出,Shell 负责解析命令和启动程序;它们不是 Linux 内核。
- 命令名、选项、参数、变量、引号和通配符都由 Shell 与程序共同处理。
- Linux 以
/为唯一目录树根;绝对路径从/开始,相对路径依赖当前目录。 - 目录、分区、文件系统和挂载是四个不同概念;同一个路径背后的文件系统类型会影响软件行为。
/dev、/proc、/sys是理解设备与内核状态的重要入口,其中一些文件写入会立即产生影响。- 用户、组和权限是内核的资源保护机制;root 权限应当短、小、明确,而不是日常默认身份。
- stdin、stdout、stderr、管道和重定向让小程序可以组合成可靠的工作流。
- 串口和 SSH 都能给你 Shell,但串口覆盖更早的启动阶段,SSH 依赖系统和网络已经正常。
- 远程或嵌入式开发时,先确认命令是在本机还是远端设备执行;同一条命令在两处可能观察到完全不同的系统。
17. 课后练习
17.1 开发主机观察练习
在 Linux 开发主机执行以下命令,记录输出中的关键信息:
id
pwd
printf '%s\n' "$SHELL"
type cd
findmnt /
df -hT
lsblk -f
ps -p 1 -o pid,comm,args
ip link
回答:
- 你当前是谁?属于哪些组?
- 当前 Shell 是什么?
cd为什么不是普通外部程序? - 根目录
/位于哪个文件系统,是什么类型? - PID 1 是什么程序?
- 主机上有哪些网络接口?
17.2 文件与重定向练习
在 ~/linux-learning/lab-02 中完成第 13 节实验,再回答:
>与>>的区别是什么?- 为什么报错进入
error.log而不是normal.log? - 如果把
2> error.log改成2>&1,结果会怎样? - 为什么练习文件不应直接放在
/etc、/usr或 SDK 源码根目录?
17.3 串口观察练习
如果你有一台可通过串口登录的 Linux 设备,且不改变任何设置,可以执行:
id
pwd
uname -m
cat /proc/cmdline
ip link
记录这些结果与开发主机的差异。不同设备的发行版、内核版本、目录布局、服务管理器和命令集合可能不同;观察到差异是正常的,先确认运行环境再解释结果。
17.4 思考题
- 为什么
cd必须由 Shell 自己实现? - 为什么
/proc中的内容不一定占用真实磁盘空间? - 为什么删除文件与父目录权限有关?
- 串口和 SSH 都能出现提示符,它们最重要的差别是什么?
- 为什么 ARM 设备上的
uname -m可能与主机不同,却仍能由主机编译它的程序? - 为什么第一版 Buildroot 要避免同时启用两套 SSH 服务?
18. 术语表
| 术语 | 含义 |
|---|---|
| Terminal | 终端;今天常指终端模拟器或远程字符交互环境 |
| Shell | 命令解释器,例如 Bash 或 BusyBox ash |
| Prompt | Shell 等待输入时显示的提示符 |
| PATH | Shell 搜索可执行程序的一组目录 |
| Working directory | 当前工作目录 |
| Absolute path | 从根目录 / 开始的路径 |
| Relative path | 相对当前工作目录解释的路径 |
| Filesystem | 组织文件、目录和元数据的格式与实现,例如 ext4 |
| Mount | 将一个文件系统接入目录树某位置 |
| UID / GID | 用户标识符 / 组标识符 |
| root | UID 为 0 的超级用户 |
| stdin / stdout / stderr | 标准输入、标准输出、标准错误 |
| Pipe | 用 | 连接进程输入输出的内核机制 |
| Redirection | 使用 >、>>、< 等改变输入输出去向 |
| PID | 进程标识符 |
| TTY | 终端设备的统称,也可指伪终端 |
| SSH | 基于加密网络连接的远程登录与命令执行协议 |
| UART | 通用异步收发器;嵌入式设备常用作调试串口 |
19. 延伸阅读
- Bash 手册:https://www.gnu.org/software/bash/manual/
- GNU Coreutils 手册:https://www.gnu.org/software/coreutils/manual/
- Linux
proc文件系统文档:https://docs.kernel.org/filesystems/proc.html - Linux sysfs 文档:https://docs.kernel.org/filesystems/sysfs.html
- Filesystem Hierarchy Standard:https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
- Linux
path_resolution(7):https://man7.org/linux/man-pages/man7/path_resolution.7.html - Linux
credentials(7):https://man7.org/linux/man-pages/man7/credentials.7.html
下一课:进程、服务与启动——从 PID 1、日志、systemd/BusyBox init,到 Linux 如何从内核进入用户空间的过程。
浙公网安备 33010602011771号