---
type: learning-note
title: Linux:块 3 补验收——日志四段、journalctl 限定、logger、logrotate、systemd
date: 2026-10-19
description: 一行日志四段与正文局限、journalctl 四限定与 --list-boots/--disk-usage、logger 造/捞与验证边界、logrotate 四关键词与 -d/-f、unit 三段与 start/enable、stop/disable/mask、Requires/After
---
# 2026-10-19 学习笔记
> 📌 GitHub:https://github.com/AR-firefly
## 笔记区
### 核心观点
**一行日志四段:时间戳 / 主机 / 程序[PID] / 正文**
用户样本:`Oct 19 19:24:28 AR-firefly systemd-resolved[79]: Clock change detected. Flushing caches.`
- ① `Oct 19 19:24:28` = 时间戳:什么时候发生。
- ② `AR-firefly` = 主机:哪台机器写的。
- ③ `systemd-resolved[79]` = 程序[PID]:谁写的;`[79]` 是 **PID = 进程号**,系统给正在运行的程序分配的编号。
- ④ `Clock change detected. Flushing caches.` = 正文:程序自己输出的那句话。
四段是**常见形态,不是铁律**:有的行程序名不带 PID,格式随发行版变。
记忆:问四个问题——**什么时候、哪台机器、谁在说、说了什么**。
**正文不能单独当结论**
- 正文是**应用自己写的**,不是有保证的结构化事实。
- **PID 会重用**:同一个号在不同开机可能是不同程序;同一次开机里进程结束后号码也会被回收。
- 单行只知道「发生过一次」,不知道**频率、来源、时间窗、上下文**。
「这只能算是线索,具体的频率,谁,什么时间,上下文和是否成功都不能知道,那只是程序自己写的,不一定是事实」。
- 例:`Failed password for root` 可能是攻击,也可能是用户自己连错三次密码;单行证明不了意图。
**journalctl 四种限定:unit / boot / 优先级 / 时间**
| 问什么 | 选项 | 例子 |
| ------------ | --------------------- | --------------------------------- |
| 哪个**服务** | `-u 名字` | `journalctl -u systemd-resolved` |
| 哪次**开机** | `-b` / `-b -1` | `journalctl -b -1` |
| 多**严重** | `-p 等级` | `journalctl -p err` |
| 哪段**时间** | `--since` / `--until` | `journalctl --since "10 min ago"` |
- `-p` 是**门槛**:`-p err` = `err` 及更严重,不是正文里找 `err` 三个字母。
- 等级数字**越小越严重**:`emerg`(0) / `alert`(1) / `crit`(2) / `err`(3) / `warning`(4) / `notice`(5) / `info`(6) / `debug`(7)。
- `-n N` 是**最多几条**,不是必须 N 条;匹配只有 1 条就显示 1 条。
- 记忆:**谁、哪次、多严重、什么时候**。
**`--list-boots`:开机会话目录**
- 一行 = **一段「开机 → 关机」的会话**,不是一条日志,也不是一个程序。
- `0` = 本次开机,`-1` = 上一次,`-21` = 从现在往回数第 21 次。
- `BOOT ID` = 那一次开机的内部编号;日志背后带的 `_BOOT_ID` 就是它。
- `FIRST ENTRY` / `LAST ENTRY` = 那一段会话的**第一条**和**最后一条**日志时间。
- 本机 22 条记录(`-21` 到 `0`)。`-21` 那段 FIRST `23:22:51`、LAST `23:23:07`——只活了 **16 秒**;下一段 `-20` 从 `23:24:27` 开始。
- **不是总开机次数计数器**:只列**日志还留着**的场次;日志删了,对应的行就没了。
「一行 = 一段开机到关机的日志时段」。
**`--disk-usage`:journal 占多少磁盘**
`Archived and active journals take up 808.4M in the file system.` —— 归档的 + 正在写的都算。
**system 与 journal 两组名字(⭐)**
| 名字 | 角色 | 管什么 | 是不是命令 |
| -------------------------------- | ------------------- | ------------------------------------------ | -------------------- |
| `systemd` | 后台总管家(PID 1) | 启动、停止、管理服务(还有挂载、定时器等) | 不是命令,是后台进程 |
| `systemctl` | 给 systemd 的遥控器 | 查状态、起停服务、设开机自启 | 命令 |
| `systemd-journald`(`journald`) | 后台档案员 | 收集日志,存进 journal | 不是命令,是后台进程 |
| `journal` | 日志数据本身 | 存下来的日志记录 | 不是命令 |
| `journalctl` | 查日志的遥控器 | 按服务/开机/等级/时间查日志 | 命令 |
- 命名规律:**`d` = daemon(后台跑的服务);`ctl` = control(遥控器/命令行工具)**。
- `systemctl show`:查**服务属性**(`Id=...`),不是日志。
- `systemctl status`:主业是**服务状态**,顺带显示最近几行日志。
- `journalctl`:专门**查日志**。
- 记忆:**d 是后台,ctl 是遥控器;system 管服务,journal 管日志。**
**logger:造一条带 tag 的测试日志**
- `logger -t 标签 '内容'`:**写**一条测试日志;`-t` = tag(标签),给消息贴名字。
- `journalctl -t 标签`:**按标签捞回来**;`-t` 在这里 = 按 tag 筛。
- `-t` 两边都是 tag:**写的时候贴,读的时候按它找**。
- 默认值:不给 `-p` → `user.notice`;不给 `-t` → 当前用户名;内容不给则从 stdin 读。
- `-s`:同时把消息打到屏幕;**屏幕有输出 ≠ 已持久存下来**。
- **验证了什么**:写 → journald 收下 → 存 → 能按 tag 查回来,这条链路通了。
- **没验证什么**:别的日志源、轮转、远程转发、真实应用的日志格式。
- 用途:日志查不到时,先分清是**服务没写**,还是**日志系统坏了**。
「如果捞得到就是服务本身的问题,如果捞不到说明这条链路错了是日志系统的问题」;更精确:捞得到只能说问题**更可能**在服务本身,捞不到也可能是标签/命令写错。
**logrotate 四关键词**
- **轮转**:把正在写的日志换成一个新文件接着写,老的改名留下来。
- `rotate N`:最多留 **N 代老的**;活跃那个不算名额,**总文件数 = 1 + N**。本机 `rotate 4` → 5 个文件。
- `compress`:老代压缩(gzip → `.gz`)。
- `delaycompress`:刚退下来的那一代**先不压**,下一次轮转再压。
- `copytruncate`:**复制**一份当前日志,再把**原文件就地清空**;给「喊不动、不会重开日志」的程序用。
- `postrotate … endscript`:轮转后、压缩前跑一段脚本,通知程序**重新打开日志**;本机是 `/usr/lib/rsyslog/rsyslog-rotate`。
- 两条路:程序**喊得动** → 改名 + `postrotate`;程序**喊不动** → `copytruncate`。
- `copytruncate` 的代价:复制和清空之间有一小段窗口,期间新写进来的日志**可能丢**;所以它是折中,不是默认。
**logrotate `-d` vs `-f`**
- `-d`(debug / dry-run):只打印它「打算怎么做」;**不动日志文件,也不更新状态文件**。
- `-f`(force):**强行真转**,哪怕它判断「今天不该转」。
- 普通用户跑 `-d` 读不到 `/var/lib/logrotate/status` → `Permission denied; assuming empty state`;它按空状态继续算,**预演结果可能和 root 真跑不同**。
- `-d` 输出好看 ≠ 真跑一定成功:权限、脚本、磁盘空间、程序能不能重开,它验不了。
**systemd unit 三段**
| 段 | 管什么 | 常见指令 |
| ----------- | ------------------------------ | ---------------------------------------------------------- |
| `[Unit]` | 这个单元**是什么、跟谁有关系** | `Description=`、`After=`、`Before=`、`Wants=`、`Requires=` |
| `[Service]` | 它**怎么跑** | `ExecStart=`、`Type=`、`Restart=`、`User=` |
| `[Install]` | **开机时怎么挂上去** | `WantedBy=` |
- 本机 `systemd-resolved.service`:`ExecStart=/usr/lib/systemd/systemd-resolved` 在 `[Service]`;`WantedBy=sysinit.target` 在 `[Install]`。
- `[Install]` **只在 `enable` / `disable` 时被读**;平时 `start` 不看它。
- 用户原话:「unit告诉你这是什么和各文件间的关系,service告诉你怎么跑,install告诉怎么挂链接」。
**start vs enable;stop vs disable vs mask**
| 命令 | 正在跑的服务 | 开机自启 | 手动还能 `start` 吗 |
| --------- | -------------------------- | ------------------- | ------------------- |
| `stop` | **停** | 不变 | 能 |
| `disable` | **不停** | 删掉 `.wants/` 链接 | 能 |
| `mask` | **不停**(除非加 `--now`) | 禁止 | **不能** |
- `start` = **现在**立刻跑;重启后就没了。
- `enable` = **以后**开机自启,建 `.wants/` 里的符号链接;**不会顺带启动**。
- `systemctl enable --now` = 两个一起做;`disable --now` / `mask --now` = 顺带停。
- `mask` = 把 unit 名链到 `/dev/null`(黑洞);`enable` 和手动 `start` 都不行;要恢复得 `unmask`。
- 用户原话:「一个是启动,一个只是开机后建链接不启动」。
**Requires vs After:依赖与顺序正交**
| 指令 | 管什么 | 不管什么 |
| ------------ | --------------------------------------------------------------- | --------------- |
| `Wants=A` | **弱依赖**:想把 A 拉起来;A 失败,B 照跑 | 不管顺序 |
| `Requires=A` | **强依赖**:把 A 拉起来;A 被显式 stop/restart,B 也跟着停/重启 | 不管顺序 |
| `After=A` | **顺序**:B 等 A 启动之后再启动 | 不会把 A 拉进来 |
| `Before=A` | 顺序反过来(等价于在 A 里写 `After=B`) | 不会把 A 拉进来 |
- 只写 `Requires=A`:A 和 B 可能**同时启动**;A 启动失败也不一定拦住 B。
- 只写 `After=A`:B 会等 A,但**不会把 A 拉起来**;A 没被调度时,这条顺序没效果。
- 想「A 起不来 B 也不起,而且 A 先起」→ **`Requires=A` + `After=A` 两个都要写**。
- 用户原话:「只说明了依赖,谁先谁后定不下来,可能他们一起冲了」;「只写After=A,A有可能直接死在那不启动了」。
### 关键方法/流程
- 读一行:`journalctl -n 1 --no-pager`。
- 按服务:`journalctl -u 服务名`(`.service` 可省)。
- 按开机:`journalctl -b`(本次)/ `-b -1`(上次)。
- 按等级:`journalctl -p err`(`err` 及更严重)。
- 按时间:`journalctl --since "10 min ago"` / `--until`。
- 按条数:`journalctl -n 10`(上限,不是配额)。
- 拼起来:`journalctl -u 服务名 -p err -b --since "10 min ago" --no-pager`。
- 开机目录:`journalctl --list-boots --no-pager`。
- 占磁盘:`journalctl --disk-usage`。
- 造测试日志:`logger -t 标签 '内容'` → `journalctl -t 标签 -n 3 --no-pager`。
- 看轮转配置:`cat /etc/logrotate.d/rsyslog`。
- 预演轮转:`logrotate -d /etc/logrotate.d/rsyslog`;强制真转:`logrotate -f ...`。
- 看 unit:`systemctl cat 单元名`(第一行 `# /usr/lib/...` 是 `cat` 加的注释,不是文件内容)。
- 起停/自启:`systemctl start` / `stop`;`systemctl enable` / `disable`;彻底封死用 `mask`,恢复用 `unmask`。
- 问状态:`systemctl is-active 单元`(现在跑不跑);`systemctl is-enabled 单元`(开不自启)。
### 实战记录
**① 一行日志四段**
```
$ journalctl -n 1 --no-pager
Oct 19 19:24:28 AR-firefly systemd-resolved[79]: Clock change detected. Flushing caches.
```
时间戳 `Oct 19 19:24:28` / 主机 `AR-firefly` / 程序 `systemd-resolved[79]` / 正文 `Clock change detected. Flushing caches.`
**② logger 造一条、按 tag 捞回**
```
$ logger -t AIDC '自己的测试内容'
$ journalctl -t AIDC -n 3 --no-pager
Oct 19 20:08:42 AR-firefly AIDC[10017]: 自己的测试内容
```
只捞回 1 条:`-n 3` 是上限,不是必须 3 条。
**③ 开机会话目录**
```
$ journalctl --list-boots --no-pager
IDX BOOT ID FIRST ENTRY LAST ENTRY
-21 8ebd3f016c6740e59e417ec2128c8a1e Mon 2026-09-07 23:22:51 CST Mon 2026-09-07 23:23:07 CST
-20 de20ece7cd234c5999cd694cf6b2b571 Mon 2026-09-07 23:24:27 CST Thu 2026-09-10 18:34:20 CST
```
`-21` 那段只活了 16 秒;`-20` 那段活了 3 天。
---
## 线索区(学完后合上材料,自问自答)
**Q: 一行日志的四段是什么?**
A: 时间戳 / 主机 / 程序[PID] / 正文;顺序固定,PID 是进程号。
**Q: 为什么正文不能单独当结论?**
A: 正文是应用自己写的,不是保证准确的结构化事实;PID 会重用;单行不知道频率、来源、时间窗、上下文。
**Q: `journalctl` 的四种限定各是什么?**
A: `-u` 单元 / `-b` 开机 / `-p` 优先级 / `--since`、`--until` 时间窗。
**Q: `-p err` 是「只要 err」吗?**
A: 不是,是 `err` 及更严重(0–3 档);级别数字越小越严重。
**Q: `--list-boots` 列的是什么?**
A: 每一段「开机 → 关机」的会话;一行一段,`0` 是本次,`-1` 是上次。
**Q: `--list-boots` 是无上限的总开机计数器吗?**
A: 不是;只列日志还留着的场次,日志删了对应的行也会消失。
**Q: `--disk-usage` 回答什么?**
A: journal 一共占多少磁盘;归档的和正在写的都算。
**Q: `systemd`、`systemctl`、`journald`、`journal`、`journalctl` 各是什么?**
A: 两个后台(`systemd` 管服务、`journald` 收日志)+ 两个命令(`systemctl` 控服务、`journalctl` 查日志)+ `journal` 是日志数据本身。
**Q: `logger -t` 和 `journalctl -t` 各干什么?**
A: `logger -t` 写时贴标签;`journalctl -t` 读时按标签筛。
**Q: 用 `logger` 造一条再捞回来,验证了什么、没验证什么?**
A: 验证「写 → 收 → 存 → 查」这条链路通了;没验证别的日志源、轮转、远程转发、真实应用格式,`-s` 屏幕有输出也不算持久化。
**Q: logrotate 的 `rotate` / `compress` / `copytruncate` / `postrotate` 各管什么?**
A: `rotate` 留几代老的;`compress` 压老代;`copytruncate` 复制 + 原地清空;`postrotate` 轮转后通知程序重开。
**Q: `copytruncate` 的代价是什么?**
A: 复制和清空之间有一小段窗口,可能丢日志;所以只在程序喊不动时用。
**Q: `-d` 和 `-f` 差在哪?**
A: `-d` 只预演,不动日志也不更新状态文件;`-f` 强制真转。
**Q: unit 文件三段各管什么?**
A: `[Unit]` 是什么/跟谁有关系;`[Service]` 怎么跑;`[Install]` 开机怎么挂。
**Q: `start` 和 `enable` 差在哪?**
A: `start` 现在跑;`enable` 建开机自启链接、不启动。
**Q: `stop` / `disable` / `mask` 三者边界?**
A: `stop` 现在停;`disable` 取消自启但手动还能起;`mask` 链到 `/dev/null`,连手动 `start` 都不行。
**Q: `Requires` 和 `After` 为什么是两套?**
A: 依赖管要不要,顺序管先先后;只写 `Requires` 可能同时启动,只写 `After` 不会拉起对方;要写两个。
---
## 总结(50字以内,用自己的话概括今天学到了什么)
块 3 五条验收补完:日志四段看线索、journalctl 四限定、logger 验链路、logrotate 四关键词、systemd 三段与启停边界。
---
## 复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| --------------------- | --------- | --------------------------------------------------------- | -------------- |
| 一行日志四段 | 必学 | 时间 / 主机 / 程序[PID] / 正文 | 读日志 |
| 正文局限 | 必学 | 应用自己写的,不是结构化事实 | 判结论 |
| `-u` | 必学 | 按单元/服务筛 | 查某服务 |
| `-b` | 必学 | 按开机筛(`0` 本次,`-1` 上次) | 跨开机 |
| `-p` | 必学 | 按级别筛,含更严重;数字越小越严重 | 找错误 |
| `--since` / `--until` | 必学 | 时间窗 | 限定时间 |
| `-n` | 必学 | 最多几条,不是配额 | 限条数 |
| `--list-boots` | 必学 | 列开机会话,一行一段 | 选开机 |
| `--disk-usage` | 必学 | journal 占多少磁盘 | 查占用 |
| `systemd` | 必学 | 后台总管家(PID 1) | 服务管理 |
| `systemctl` | 必学 | 控制 systemd 的命令 | 起停服务 |
| `journald` | 必学 | 收日志的后台 | 日志收集 |
| `journal` | 必学 | 日志数据本身 | 存储 |
| `journalctl` | 必学 | 查 journal 的命令 | 查日志 |
| `logger -t` | 必学 | 写一条带 tag 的测试日志 | 验证链路 |
| `journalctl -t` | 必学 | 按 tag 捞日志 | 验证链路 |
| `rotate N` | 必学 | 留 N 代老的,总数 1 + N | 轮转配置 |
| `compress` | 必学 | 老代压缩(gzip → `.gz`) | 省空间 |
| `delaycompress` | 必学 | 晚一轮再压 | 程序还没松手 |
| `copytruncate` | 必学 | 复制 + 原地清空;喊不动时用 | 不能重开的程序 |
| `postrotate` | 必学 | 轮转后通知程序重开 | 能重开的程序 |
| `-d` | 必学 | 预演,不动文件/状态 | 改配置前 |
| `-f` | 必学 | 强制真转 | 测试 |
| `[Unit]` | 必学 | 是什么/关系 | unit 三段 |
| `[Service]` | 必学 | 怎么跑 | unit 三段 |
| `[Install]` | 必学 | 开机怎么挂 | enable/disable |
| `start` | 必学 | 现在跑 | 立即启动 |
| `enable` | 必学 | 建开机自启链接,不启动 | 开机自启 |
| `stop` | 必学 | 现在停 | 立即停止 |
| `disable` | 必学 | 删自启链接,手动还能起 | 取消自启 |
| `mask` | 必学 | 链到 `/dev/null`,手动也不行 | 彻底封死 |
| `Requires` | 必学 | 强依赖 | 依赖 |
| `After` | 必学 | 顺序 | 先后 |
| `Wants` | 必学 | 弱依赖,失败也照跑 | 依赖 |
| 了解层(合并一行) | 了解 | `BindsTo` / `Requisite` / `.requires/` / `mask --runtime` | 用到再查 |
---
## 旧知识回收(今天暴露出来的)
| 概念 | 一句话 | 出处 |
| ------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------- |
| inode 不存文件名 | 文件名在**目录**里(名字 → inode 号的对照表) | 今天 Q2;09-30 曾答成「存 inode 号」后重考 |
| `df` / `du` | `df` 看账本、`du` 挨家数;对不上五条:删 / 留 / 挂 / 权 / 稀 | 今天 Q3 先答不出,补地基后用「删 / 挂 / 权」三个场景通过 |
| 5% 预留 | 是文件系统的空闲空间,归 `df` 看;不是 `du` 数的文件 | 用户曾误以为 `sudo` 会把 5% 加进去 |
| `remove` vs `purge` | `remove` 留配置、`purge` 连配置删;看 `dpkg -l` 的 `rc` vs 整行消失 | 今天 Q4 答对 |
| `/var` / `/usr` | `/var` 放会变的;`/usr` 放软件;`usr` 原始 = user,现代解作 Unix System Resources | 今天 Q1 已答对,跳过不重考 |
| `-n` 两义 | `journalctl -n` = 条数;`logger -n` = 远程服务器 | 今天讲 logger 时点出 |
---
## 今日产出验收
| 条 | 标准 | 结果 / 证据 |
| --- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ② | 读懂一行日志四段,说清为什么正文不能单独当结论 | ✅ 拆对 `Oct 19 19:24:28 / AR-firefly / systemd-resolved[79] / 正文`;重考答出「只是线索,频率/谁/时间/上下文不知道,正文是程序写的,不一定事实」 |
| ③ | 会用 journalctl 按 unit / boot / 优先级 / 时间限定;知道 `--list-boots`、`--disk-usage` | ✅ 写出并跑通 `-u systemd-resolved`、`-b`、`-p err`、`--since "10 min ago"`,组合命令 `-u ... -p err -b --since ...` 跑通(`-- No entries --` 是空结果,不是报错);说清 `--list-boots` = 开机会话目录、`--disk-usage` = 占磁盘 |
| ④ | 用 `logger` 造带 tag 的日志并捞回;说清验证/没验证什么 | ✅ 亲手跑 `logger -t AIDC '自己的测试内容'` + `journalctl -t AIDC -n 3` 捞回;说清验证「写→收→存→查」,没验证其他来源/轮转/远程/真实应用 |
| ⑤ | 读懂 logrotate 配置;`rotate` / `compress` / `copytruncate` / `postrotate` 各管什么;`-d` 预演 | ✅ 读本机配置;说清 `rotate 4` = 留 4 代老的(总 5 个)、`compress`/`delaycompress`、`postrotate`;`copytruncate` 选对并纠正为「先复制再清空」;`-d` 与 `-f` 区别、`-d` 不动文件/状态说清 |
| ⑥ | unit 三段;`start` vs `enable`;`stop` vs `disable`;`disable` vs `mask`;`Requires`/`After` | ✅ 三段职责说清(「unit告诉你这是什么和各文件间的关系,service告诉你怎么跑,install告诉怎么挂链接」);`start`/`enable`、`stop`/`disable`/`mask`、`Requires`/`After` 全部答对,明确「两个都要写」 |
本文系统梳理Linux日志分析与systemd服务管理的关键技术:日志四段结构(时间戳/主机/程序[PID]/正文)及其局限性;journalctl四大限定(unit/boot/优先级/时间)及--list-boots、--disk-usage用法;logger测试日志链路验证;logrotate四大机制(rotate/compress/copytruncate/postrotate)及-d/-f行为差异;systemd unit三段结构([Unit]/[Service]/[Install])与服务启停边界(start/enable/stop/disable/mask)及依赖关系(Requires/After)。

7970

被折叠的 条评论
为什么被折叠?



