---
type: learning-note
title: Linux:软件包管理 apt——装 / 卸 / 查
date: 2026-09-29
description: apt 是什么、update 刷的是"货单"不是软件、apt 与 dpkg 的两层关系、dpkg -l 状态位 ii/rc、search 与 show、交易预览三组、./ 的作用、remove 与 purge、autoremove 清孤儿
---
# 2026-09-29 学习笔记
> 📌 GitHub:https://github.com/AR-firefly
## 笔记区
### 核心观点
**apt 是 Ubuntu 的软件包管理命令**
`apt --help` 原文:_apt is a commandline package manager and provides commands for searching and managing as well as querying information about packages._
「apt 就是可以搜看装删更新的指令」但「更新」在 apt 里是**两个动作**,`update` 动的是**货单**,`upgrade` 才动**软件**。
**`apt update` 刷的是"货单",不是软件**
- **仓库(repository)**:网上放软件的地方。本机配了 **2 个**(`archive.ubuntu.com` + `security.ubuntu.com`),写在 `/etc/apt/sources.list.d/ubuntu.sources`。⚠️ `/etc/apt/sources.list` **不保证是全量**(本机它只剩注释)。
- **索引(货单)**:仓库发布的"里面有哪些包、什么版本"的清单。`apt update` 把它拷到本地 `/var/lib/apt/lists/`——本机 **65 个文件、150M**。
- 拷完 apt 顺手对一遍账,报"**55 packages can be upgraded**",**但一个都没升**。
- `man apt` 原文:_update is used to **download package information** from all configured sources._
**屏幕上那 4 行 `Hit` 是哪来的**:配置文件里 `archive` 那段写了 **3 条** `Suites`(`resolute` / `-updates` / `-backports`)、`security` 那段写了 **1 条**(`resolute-security`)——**3 + 1 = 4**。不是随便冒出来的。
**`apt list` 与 `apt list --installed` 是两个世界**
| 命令 | 条数 | 列的是 |
| ---------------------- | --------- | -------------------- |
| `apt list` | **78416** | 仓库里**全部能装的** |
| `apt list --installed` | **545** | **本机已装的** |
`--installed` 是个**过滤条件**——选项就是"命令后面的开关",加一道筛子就换一种结果。
**`apt` 和 `dpkg` 是两层,不是上下级**
- **`dpkg` 在下层**:`dpkg --help` 里 `-i|--install` 后面跟的是 `<.deb file name>`——**它只认本地 `.deb` 文件**,不上网、不算依赖、不下载。
- **`apt` 在上层**:上网搬索引 → 算依赖 → 把 `.deb` 下到本地 → **交给 dpkg 装**(装包时预览里的 `Inst` ↔ dpkg 的 `--unpack`、`Conf` ↔ `--configure`)。
- **站在上层 = 上下都能看**:apt 往外看得到仓库,**往下也读得到本机那本账**(`/var/lib/dpkg/status`,本机 **544** 个包,跟 `apt list --installed` 的 545 对得上)。
- ⚠️ 所以**不是**"apt 管网上、dpkg 管本机"——**"本机装了什么",两个都看得到**。
**`dpkg -l` 的三个状态位**
表头那三行是**指针**:`+` 在第几位,那一行就解释第几位。
| 位 | 名字 | 在问什么 |
| --- | ----------- | --------------------------------- |
| 1 | **Desired** | 你**希望**它怎样(U/I/R/P/H) |
| 2 | **Status** | **实际**怎样(N/I/C/U/…) |
| 3 | **Err** | 有没有坏(**出现大写字母 = 坏**) |
- **`ii`** = 期望装 + 已装 + 无错 ← 正常已装的样子
- **`rc`** = **r**emove + **c**onffiles remain ← **包卸了、配置文件还在**
**`search` 搜的是描述,`show` 给的是身份**
- `search` 在**包的描述**里搜(`apt --help`:_search in package descriptions_)。所以搜 `figlet` 出来 **9 个包**,真叫 figlet 的只有 1 个——`toilet` 能冒出来,是因为它描述里写着 "similar to **FIGlet**"。
- `show` 给完整字段:`Version` / `Installed-Size`(装完占多少)/ `Depends`(依赖谁)/ `Download-Size`(下多少)/ `APT-Sources`(从哪个仓库哪条线来)。
**装包前那张纸:三样 + 三组**
三样最该看:**装哪些包 / `Download size` / `Space needed`**。(卸的时候对应的是 `Freed space`,一进一出。)
三组按「**谁点的名**」分:
```
Installing: ← 你点名的
Installing dependencies: ← apt 为满足依赖自己算出来带上的(**必需,不是次要**)
Suggested packages: ← 只是建议,**apt 从不自动装**
```
⚠️ `Installing dependencies` 那组不是"次要"——本机实测:想单独卸掉 `libcaca0`,apt 要**把 toilet 一起删掉**(没它 toilet 跑不起来)。
**`./` 的作用**
apt 默认把参数当**仓库里的包名**。`./` 是**路径前缀**,告诉它"这是当前目录下的文件"。
| 写法 | apt 当作 | 结果 |
| ------------------------------ | ------------ | ----------------------------------------------------------------------- |
| `figlet_2.2.5-3.1_amd64.deb` | 仓库里的包名 | `Error: Unable to locate package ...` |
| `./figlet_2.2.5-3.1_amd64.deb` | 本地文件路径 | `Note, selecting 'figlet' instead of './...'`——**打开文件、读出真包名** |
「`./` 是从本地找」。
**`remove` 与 `purge`**
| | 程序文件 | 配置文件 | `dpkg -l` 那行 |
| -------- | -------- | -------- | -------------- |
| `remove` | 删 | **留** | 变 **`rc`** |
| `purge` | 删 | **删** | **整个消失** |
`man dpkg` 原文(`-r, --remove`):_This removes everything **except conffiles** ... **which may avoid having to reconfigure the package if it is reinstalled later**._
**这就是"为什么 remove 要故意留着配置"的官方答案**:以后重装同一个包,改过的设置还在。
`man apt-get` 原文(purge):_identical to remove except that packages are removed and purged (**any configuration files are deleted too**)._
**`autoremove` 清孤儿**
- **孤儿包** = 当初作为依赖**自动装上**(就是点 3 那个 `[installed,automatic]` 标记)、现在**没有任何包再用它**
- `remove toilet` 时 apt 自己会说:_The following packages were automatically installed and are no longer required_ —— **但它不动手**,把决定权留给人
- 判断跟"装多久""仓库里有没有"都**无关**,只看**本机的依赖关系**
### 关键方法/流程
- **刷货单**:`sudo apt update`
- **搜 → 看详情**:`apt search 关键词` → `apt show 包名`
- **看装了哪些**:`apt list --installed`(apt 口径)/ `dpkg -l`(dpkg 口径,带状态位)
- **装**:`sudo apt install 包名`(**先看那张纸的三样**)
- **装本地 deb**:`sudo apt install ./xxx.deb`(`./` 不能省)
- **卸**:`sudo apt remove 包名`(留配置)/ `sudo apt purge 包名`(连配置删)
- **清孤儿**:`apt autoremove --dry-run`(先看)→ `sudo apt autoremove`
- **只演示不动手**:`-s` = `--dry-run` = `--just-print` = `--no-act`(`man apt-get` 里是同一串别名)
- **查操作历史**:`/var/log/apt/history.log`(记着**发起人** `Requested-By`)
### 实战记录
**① 装 figlet —— 那张纸的三样**
```
Installing: 1
Download size: 138 kB
Space needed: 752 kB / 1024 GB available
```
**② remove → purge 的四个证据**
```
装完 ii figlet ... /etc/emacs/site-start.d/50figlet.el 在(290 字节)
remove 之后 rc figlet ... 文件还在(290 字节,日期没变)
purge 之后 那一行整个消失 ls: No such file or directory
```
**③ toilet 带出两个依赖,卸完变孤儿**(用户亲手做)
```
Installing: 3
Installing dependencies:
libcaca0 toilet-fonts
(remove toilet 之后 apt 自己提示)
The following packages were automatically installed and are no longer required:
libcaca0 toilet-fonts
```
---
## 线索区(学完后合上材料,自问自答)
**Q: `apt update` 下载的是什么?它升级软件吗?**
A: 下载的是**索引(货单)**——"仓库里有哪些包、什么版本"。**它不升级任何软件**,只把货单拷到本地(`/var/lib/apt/lists/`),升软件是 `apt upgrade`。
**Q: 为什么 `apt update` 和 `apt upgrade` 必须分两步?**
A: apt 做任何决定都得先有货单,货单是旧的就只能算出旧结果。**先刷货单,再照着货单动手。**
**Q: `apt list` 和 `apt list --installed` 差在哪?**
A: `--installed` 是个**过滤条件**。不带 → **78416** 条(仓库里全部);带了 → **545** 条(本机已装)。
**Q: `apt` 和 `dpkg` 是什么关系?"本机装了什么"谁看得到?**
A: **两层分工**:`dpkg` 在下层,**只认本地 `.deb`**、不上网不算依赖;`apt` 在上层,上网、算依赖、下载,**再交给 dpkg 装**。**本机装了什么,两个都看得到**(apt 在上层,往下读得到 dpkg 那本账)。
**Q: `dpkg -l` 那三个状态位分别在问什么?**
A: 第 1 位 **Desired**(你希望它怎样)· 第 2 位 **Status**(实际怎样)· 第 3 位 **Err**(有没有坏,大写字母 = 坏)。
**Q: `ii` 和 `rc` 分别是什么意思?**
A: `ii` = 期望装 + 已装 + 无错。`rc` = **r**emove + **c**onffiles remain——**包卸了、配置文件还在**。
**Q: 装包前那张纸,哪三样最该看?**
A: **装哪些包 / `Download size`(下多少)/ `Space needed`(占多少)**。不看就回车 = 放弃唯一一次说"不"的机会。
**Q: 预览里 `Installing` / `Installing dependencies` / `Suggested` 凭什么分?**
A: 按**谁点的名**。第一组你点的;第二组 apt 为满足依赖**自己算出来带上的**(**必需**);第三组只是建议,**永远不会被自动装**。
**Q: `apt install ./x.deb` 里 `./` 为什么必须写?不写会怎样?**
A: apt 默认把参数当**仓库里的包名**。不写 → 拿文件名去仓库搜 → `Error: Unable to locate package`;写了 → 它打开文件、**读出真包名**(`Note, selecting 'figlet' instead of './...'`)。
**Q: `remove` 和 `purge` 差在哪?怎么用命令看出"包卸了但配置还在"?**
A: `remove` 只删程序、**留配置文件**;`purge` 连配置文件一起删。**看 `dpkg -l` 的状态位**:变 `rc` 就是"包没了、配置还在";`purge` 之后那一行**整个消失**。
**Q: `remove` 为什么故意留着配置文件?**
A: `man dpkg` 原文:这样可以 **avoid having to reconfigure the package if it is reinstalled later**——以后重装同一个包,改过的设置还在。
**Q: 什么包会被 `autoremove` 盯上?为什么 apt 不自己删?**
A: **当初作为依赖被自动装上、现在没有任何包再用它**的包。apt **只提示不动手**——"没人依赖"不等于"用不着",删是不可逆动作,得人点头。
**Q: `apt autoremove --dry-run` 里的 `--dry-run` 和 `-s` 是一回事吗?**
A: 是。`man apt-get` 里 `-s, --simulate, --just-print, --dry-run, --recon, --no-act` 是**同一串别名**,都是"只演示不动手"。
---
## 总结(50字以内,用自己的话概括今天学到了什么)
apt update 只搬货单不升软件;apt 在 dpkg 上层、两者都看得到本机账;`ii` 是装好、`rc` 是卸了留配置;remove 留配置、purge 连它一起删;孤儿包靠 autoremove 清。
---
## 复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| ---------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
| `apt` | 必学 | Ubuntu 的**软件包管理命令**(搜/看/装/卸/升) | 装软件 |
| 仓库 repository | 必学 | 网上放软件的地方;本机配了 2 个 | 理解货单哪来 |
| 索引(货单) | 必学 | "有哪些包、什么版本"的清单,存在 `/var/lib/apt/lists/` | 理解 update |
| **`apt update`** | 必学 | **只下货单,不升软件** | 最容易搞混 |
| `apt upgrade` | 必学 | 照着货单**真升级** | 升级 |
| 为什么分两步 | 必学 | 货单旧 → 算出来的结果就旧 | 理解顺序 |
| `apt list` | 必学 | **78416** 条:仓库里全部 | 看仓库有什么 |
| `apt list --installed` | 必学 | **545** 条:本机已装 | 看装了哪些 |
| `--installed` | 必学 | 一个**过滤条件**(选项 = 命令的开关) | 理解选项 |
| `dpkg` | 必学 | 下层工具,**只认本地 `.deb`** | 理解两层 |
| `dpkg --help` 的 `-i` | 必学 | 后面跟 `<.deb file name>`——**本地文件名** | 两层的证据 |
| 两层的"视野" | 必学 | **本机装了什么,apt 和 dpkg 都看得到** | 别推成"各管一头" |
| `Inst` ↔ `--unpack` | 必学 | apt 的 `Inst` 阶段 = dpkg 解包;`Conf` = 配置 | 看装包过程 |
| `dpkg -l` 三位 | 必学 | Desired(期望)· Status(实际)· Err(坏没坏) | 读状态位 |
| `ii` | 必学 | 期望装 + 已装 + 无错 | 正常已装 |
| **`rc`** | 必学 | **r**emove + **c**onffiles remain——卸了但配置还在 | 看卸干净没有 |
| `apt search` | 必学 | 在**包的描述**里搜 | 不知道名字 |
| `apt show` | 必学 | 看一个包的完整身份(版本/依赖/大小/来源) | 装之前 |
| 交易预览三样 | 必学 | 装哪些 / `Download size` / `Space needed` | 按 Y 之前 |
| `Installing` 组 | 必学 | **你点名的** | 读预览 |
| `Installing dependencies` 组 | 必学 | apt 为满足依赖**自动带上的**——**必需,不是次要** | 读预览 |
| `Suggested packages` | 必学 | 只是建议,**apt 从不自动装** | 读预览 |
| `./` 前缀 | 必学 | 告诉 apt"这是**本地文件路径**",不是包名 | 装本地 deb |
| `remove` | 必学 | 删程序、**留配置**(`rc`) | 卸包 |
| `purge` | 必学 | 删程序 **+ 删配置**(那行整个消失) | 卸干净 |
| remove 为什么留配置 | 必学 | 重装时**不用重新配置**(`man dpkg` 原文) | 理解设计 |
| 孤儿包 | 必学 | 当初**自动装上**、现在**没人依赖** | 清理 |
| `autoremove` | 必学 | 清孤儿;**先 `--dry-run` 看,再真跑** | 清理 |
| apt 不自己删孤儿 | 必学 | 只提示——"没人依赖"≠"用不着",删得人点头 | 理解设计 |
| `[Y/n]` | 必学 | **大写 = 默认值**,回车就等于选它 | 看提示 |
| `-s` / `--dry-run` | 必学 | 只演示不动手(同一串别名) | 动手前 |
| `/var/log/apt/history.log` | 必学 | 记着谁在什么时候跑过什么(含 `Requested-By`) | 查操作历史 |
| **了解层(合并一行)** | 了解 | 本轮只带出、没深挖没考:`rpm`/`dnf`/`yum` 是 Red Hat 那家的对应体系(底层 rpm、仓库级 dnf、`yum` 在现代 RHEL 上只是 dnf 的兼容别名) | 见到再查 |
---
## 旧知识回收(今天暴露出来的)
| 概念 | 一句话 | 出处 |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| **`ps` 后面为什么不能接进程名** | `ps` 的语法**只认选项和 PID 数字**;写 `ps python` 它把 `python` 当号码解析,报 `process ID list syntax error`。按名字找进程要用 `ps aux \| grep 名字` | 09-15 抽考答「记不得了」。探地基挖出断点在「**选项**」这个概念上——`ps aux` 里的 `a`/`x`/`u` 就是选项(选哪些 + 怎么显示) |
| **`crontab -r`** | **不是 read,是 remove**——把整个 crontab 删掉、**不可逆、还不问**。列出来看是 **`-l`**(list) | 09-15 抽考答成「第一个是只读」 |
| **`kill` 的用词** | `kill` 是**发信号**,不是"删"。默认 15 号(TERM,请它自己收尾再走);9 号(KILL)是立刻处决、来不及收尾 | 09-15 抽考方向对、用词需拧 |
---
## 今日产出验收
| 条 | 标准 | 结果 |
| --- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ① | 亲手装一个包,读出交易预览里的三样 | ✅ 做得出(`sudo apt install figlet`,`Installing: 1` / `Download size: 138 kB` / `Space needed: 752 kB`)+ 讲得清(点 4 答案是这三样) |
| ② | 亲手做 remove → purge 对比实验 | ✅ 做得出(`ii` → `rc` → 那行消失;配置文件 290 字节 → 还在 → `No such file or directory`)+ 讲得清(点 7 答对,并自己拆出"第一位期望、第二位实际") |
| ③ | 讲清 `apt update` / `upgrade` 两步 + `./` 不写会怎样 | ✅ 做得出(跑过两条对照:不写报 `Unable to locate package`,写了报 `Note, selecting 'figlet'`)+ 讲得清(第 1 题答 `apt upgrade`;点 6 答 A 并补「`./` 是从本地找」) |
| ④ | 说出 toilet 带的两个依赖 + 指出孤儿 + 用 autoremove 清掉 | ✅ 做得出(预览 `Installing: 3` + `Installing dependencies: libcaca0 toilet-fonts`;`apt autoremove` 真跑成功)+ 讲得清(点 5 答 B、点 9 答 D) |