type: learning-note
title: Linux:日志全景------日志从哪来、存在哪、长什么样
date: 2026-10-08
description: 日志两个用途(排障/审计)、三个前提、链路四步、journald 与 rsyslog 并存、日志路径不能背要现查、一行四段、一行的局限、less/tail -n/tail -F 分工、--since 框时间窗、grep -n -C 3 带上下文、轮转边界;含今天拧正的点(/var 与 /usr、ps 第一列是用户、目录 x 只管通行)与旧知识回收
2026-10-08 学习笔记
> 📌 GitHub:https://github.com/AR-firefly
笔记区
核心观点
**日志的两个用途:排障 + 审计**
原文(LabEx 官方中文版 `system-logging`):
> 日志记录由内核、服务、应用程序和安全组件发出的事件。它们可以帮助**排查问题和审计**,但前提是收集功能正常、时间戳得到正确理解,并且相关来源已包含在内。
**判据不是"日志长什么样",是"你要拿它回答什么问题"**:
| 用途 | 要回答的问题 | 问的是谁 |
| ---- | ------------------------------ | ----------- |
| 排障 | 出了什么事、**为什么** | 机器 / 服务 |
| 审计 | **谁**、什么时候、做了**什么** | 人(账号) |
**同一条日志,两个用途都能用。** 用途不是日志上的标签,是**你带着的问题**决定的。
-
`session opened for user ar-26710`:审计问"谁登进来了"→答上了;排障问"连不上是**没登上**还是**登上了又断**"→有这条说明登上了,问题在别处
-
`systemd-logind: The system will power off now!`:这条是**正常**关机,但能拿来**排障**(问"机器为什么关了"→答上了:不是崩的,是走了正常关机流程)
**日志的三个前提**
> 但前提是**收集功能正常、时间戳得到正确理解,并且相关来源已包含在内**。
| 前提 | 具体 | 不满足会怎样 |
| ---------------- | -------------------------------- | ---------------------------------- |
| ① 收集在跑 | 收集器(journald / rsyslog)活着 | 那段时间日志**空白**,但事情发生了 |
| ② 时间戳理解对 | 时区设对 + 时钟同步 | 按时间找,找到的是**错位**的行 |
| ③ 相关来源被包含 | 路由规则把它收进来了 | 翻 `/var/log/` 找不到那类日志 |
**三条的共同点:都是"日志里没有 ≠ 没发生"。** 这是排查时的**第一反应规则**------看到日志空白,先问"是不是收集这一环断了"。
本机三条都满足:
```
Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
NTP service: active
systemd-journald: active
rsyslog: active
```
所以本机日志的时间戳带 `+08:00`(东八区记号)。
**日志链路四步(因果链,逐级依赖)**
原文:
> 1. 来源发出事件。2. 收集器接收事件并**补充信息**。3. **路由和保留**规则选择**存储位置或转发目的地**。4. 查看工具查询已存储的记录。
| 步 | 干什么 | 干完产生什么 |
| ---------------------- | ------------------------ | -------------------- |
| ① **来源** source | 事情发生,发出事件 | 一个**事件** |
| ② **收集器** collector | 接住它、补充信息 | **一条记录** |
| ③ **路由 / 保留** | 决定**存哪**、**留多久** | 记录**落到某个地方** |
| ④ **查看器** viewer | 查**已经存下来的**记录 | 读到的内容 |
**第 ④ 步依赖第 ③ 步**------记录没存下来,查看器看什么。
记忆锚:**发生 → 收下 → 存哪 → 去查**。
第 ② 步那个"**补充信息**"是关键:事件发出来可能只有一句话,**时间戳、主机名、`PID` 是收集器贴上去的**。
**`systemd-journald` 与 `rsyslog` 可并存,不是二选一**
| | systemd-journald | rsyslog |
| -------- | ----------------------------------------- | -------------------------------------- |
| 谁自带 | systemd 自带 | 传统 syslog 的实现 |
| 写什么 | **二进制** journal(`/var/log/journal/`) | **纯文本**文件(`/var/log/syslog` 等) |
| 本机状态 | active(跑在 **root**) | active(跑在 **syslog** 用户) |
**同一条事件,两边各有一份**:
```
journal: Oct 08 17:49:47 AR-firefly systemd1: wsl-pro.service: Deactivated successfully.
syslog: 2026-10-08T17:49:47.417405+08:00 AR-firefly systemd1: wsl-pro.service: Deactivated successfully.
```
**但两边处理不完全一样**:rsyslog 会把重复消息**合并**成 `message repeated 16 times: ...`,journal 不会。
**日志路径不能背,要现查**
原文:
> 它们是很有用的起点,但**文件名和内容取决于路由策略,并不是 Linux 的统一保证**。
> 在使用兼容路由的 Debian 系发行版上,`/var/log/syslog` 很常见;其他系统则常使用 `/var/log/messages`。**只使用 journal 的主机可能没有这两个文件。**
| 同一类事件 | Debian 系(本机 Ubuntu) | Red Hat 系 |
| ---------- | ------------------------ | ------------------- |
| 通用日志 | `/var/log/syslog` | `/var/log/messages` |
| 认证日志 | `/var/log/auth.log` | `/var/log/secure` |
本机 `/var/log/README`(官方说明,`-> ../../usr/share/doc/systemd/README.logs`):
> You are running a systemd-based OS where traditional syslog has been **replaced with the Journal**. ...simply invoke "**journalctl**", which will output the logs in the **identical text-based format** the syslog files in /var/log used to be.
> ...implementations such as syslog-ng or **rsyslog may be installed side-by-side with the journal**.
两种机器:
-
**只有 journal** → `/var/log` 里那些传统文本文件**没有**
-
**额外装了 rsyslog** → 有,且与 journal **并存**(本机是这一种)
**现查三条命令**
| 命令 | 回答什么 |
| ----------------------------------------------------------------------- | ------------------ |
| `systemctl --type=service --state=running \| grep -E 'journal\|syslog'` | **谁**在往日志里写 |
| `ls -la /var/log` | 已经有哪些日志文件 |
| `journalctl --disk-usage` | journal 占了多大 |
**一行日志四段**
原文:
> `Jan 27 07:41:32 icebox anacron4650: Job 'cron.weekly' started`
> 其中包含**时间戳、主机、程序和 PID,最后是消息**。
本机样本:
```
2026-10-08T22:29:27.099325+08:00 AR-firefly systemd1: wsl-pro.service: Deactivated successfully.
└──────── ① 时间戳 ────────┘ └② 主机┘ └③ 程序PID┘ └──────── ④ 正文 ────────┘
```
-
`systemd1` 里的 `1` 就是 **PID**
-
④ 是**整行剩下的部分**,可以很长、可以带特殊字符(如 `message repeated 16 times: ...`)
-
原文用的是"**可能如下**"(may look like)------**四段是常见形态,不是铁律**(有的行程序名不带 PID,格式随发行版变)
**一行日志的局限**
原文:
> 应把消息文本视为**应用程序输出,而不是有保证的结构化事实**。检查时**时区、时钟同步、启动 ID、PID 重用,以及事件前后的记录**。
> (认证日志)**单独一行很少能够证明用户意图或确认账户已被入侵**。
| 局限 | 说明 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| ① 正文是**应用自己写的** | 不是"事实" |
| ② **PID 会重复** | 本机 `CRON1309` `CRON1425` `CRON1741` `CRON1813` `CRON1856` ------ 同一程序名、五个不同 PID;反过来同一 PID 在不同时间可能是不同程序 |
| ③ **要看前后** | 单独一行证明不了什么 |
**为什么**:每一行都是**某个程序自己写的**,每个程序**只知道它自己那一小块**:
-
`systemd` 只知道"有个进程没了" → 写 `Deactivated successfully`
-
`wsl-pro-service` 知道"为什么退出" → 写 `Exiting... check if the Windows agent...`
**两个程序各说各的,拼起来才是完整故事。**
**三种看日志的工具**
原文:
> 使用 `less` 进行**可控浏览**,使用 `tail` 查看**最新记录**。
> 在有限时间的重现过程中,可用 `tail -F FILE` **跟踪新追加的行**。与简单快照不同,**当文件在轮转期间被替换时,`-F` 会重试**。使用 `Ctrl-C` 停止跟踪。
| 工具 | 干什么 | 什么场景 |
| ------------------ | ------------------------- | ---------------------- |
| `less 文件` | **翻阅**(上下滚、搜) | 要**通读**一段、慢慢找 |
| `tail -n 100 文件` | 看**最后 100 行**(快照) | 只关心**最近** |
| `tail -F 文件` | **跟着看**,新行实时显示 | 一边复现一边盯 |
`-F` 的关键:**日志轮转把旧文件换掉后,`-F` 会重新找到新文件继续盯**(普通 `tail -f` 会"瞎掉")。
`less` 操作:`空格` 翻页 / `b` 后退 / `/关键词` 搜 / `n` 下一个 / **`q` 退出**。
名字来历:`more` 只能往下翻,`less` 是升级版------"**less is more**"。
**先框时间窗**
原文:
> **应先使用有边界的查询,而不是倾倒整个 journal。**
> `journalctl --since '2026-08-31 09:00' --until '2026-08-31 09:15'`
| 选项 | 意思 |
| --------- | -------------------- |
| `--since` | **从**什么时候**起** |
| `--until` | **到**什么时候**止** |
时间可以写得很灵活:`"10 min ago"` / `"1 hour ago"` / `"today"` / `"2026-10-08 17:00"`。
本机实测:
```
journal 全量 52942 行
最近 10 分钟 3 行
最后 10 行 10 行
```
**两条不同的轴**:
-
`--since "10 min ago"` = 框**时间**(这 10 分钟内**所有**,条数不定)
-
`-n 10` = 框**条数**(**不管时间**,就是最后 10 条)
**`--since` 和 `--until` 方向相反**,可以一起用来"掐出某一段"。
**带上下文搜**
原文:
> `grep -n -C 3 'connection refused' /var/log/example.log`
> **既要记录成功事件,也要记录失败事件,并保留周边行,因为原因可能早于可见错误。**
| 选项 | 意思 |
| ------ | ------------------------------- |
| `-n` | 标**行号** |
| `-B 3` | 命中行**前面**带 3 行(before) |
| `-A 3` | 命中行**后面**带 3 行(after) |
| `-C 3` | **前后各带 3 行**(context) |
**本机实证**------只有带上下文才看得到:
```
89: 21:16:14 systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 8.
100: 21:47:18 systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 9.
109: 22:18:22 systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 10.
117: 22:49:27 systemd1: wsl-pro.service: Scheduled restart job, restart counter is at 11.
```
-
**不带 `-C 3`**:只看到 10 条孤立的 `Exiting`(每约 31 分钟一条)→ 会以为"它每半小时**主动**退一次"
-
**带上**:真相是 **systemd 在无限重启它**(`restart counter is at 11`)
**轮转边界(了解层,不深挖)**
原文:
> **一次事件可能跨越日志轮转边界。** 活动文件、编号归档和压缩文件可能分别包含**同一事件序列的不同部分**。
> `zgrep -n 'connection refused' /var/log/example.log*.gz`
> **应按实际时间戳排列结果,而不是只看文件后缀。**
-
`.1` / `.2.gz` / `.3.gz` 是**同一串日志被切成几段**
-
`zgrep` / `zless` 能**直接读 `.gz`**,不用先解压
-
**按时间戳排,别按文件后缀排**
本机实证:`auth.log.2.gz` 里装的是 **9 月 29 日**的日志,而当前 `auth.log` 是 **10 月 8 日**------**只搜当前那个文件就漏了**。
关键方法/流程
-
**现查日志**(到一台新机器):`systemctl --type=service --state=running | grep -E 'journal|syslog'` → `ls -la /var/log`
-
**看一行**:`tail -n N 文件` / `less 文件`
-
**跟着看**:`tail -F 文件`(`Ctrl-C` 停)
-
**框时间**:`journalctl --since "10 min ago"`(可加 `--until`)
-
**带上下文搜**:`grep -n -C 3 '关键词' 文件`
-
**读压缩档**:`zgrep '关键词' 文件*.gz`
-
**看 journal**:`journalctl`(二进制,不能 `cat`)
-
**看服务状态**:`systemctl is-active 名字` / `systemctl --type=service --state=running`
-
**看进程**:`ps aux | grep 名字 | grep -v grep`
实战记录
**① 复习抽考:目录的 `x` 只管"通行"**
```
mkdir -p /tmp/xtest/d && touch /tmp/xtest/d/a.txt /tmp/xtest/d/b.txt
chmod 100 /tmp/xtest/d → d--x------
cd /tmp/xtest/d → 进去了
ls → Permission denied (没有 r)
```
对照(`chmod 500` = `r-x`):能 `ls`,但 `rm` / `touch` 都 `Permission denied`(没有 w)。
**② 现查收集器**
```
$ systemctl is-active systemd-journald rsyslog → active / active
$ ls -d /var/log/*/ → apt/ chrony/ dist-upgrade/ journal/ landscape/ private/ unattended-upgrades/
$ ps aux | grep -E 'rsyslog|systemd-journald' → root 47 systemd-journald / syslog 210 rsyslogd
```
**③ 读 `/var/log/README`**------官方说明 journal 与 rsyslog 的关系
**④ 标四段**
```
2026-10-08T22:49:27.267866+08:00 AR-firefly systemd1: Started wsl-pro.service - Bridge to Ubuntu Pro agent on Windows.
时间戳:2026-10-08T22:49:27.267866+08:00
主机:AR-firefly
程序:systemd1
正文:Started wsl-pro.service - Bridge to Ubuntu Pro agent on Windows
```
**⑤ 一行 vs 上下文**
```
106: 21:58:22.846364 wsl-pro-service1823: WARNING Exiting after <nil>: check if the Windows agent is installed and running.
107: 21:58:22.852580 systemd1: wsl-pro.service: Deactivated successfully.
```
只看 107 → "服务停用成功,像正常";加 106 → **是它自己退出的**(连不上 Windows agent)。
**⑥ 时间窗**
```
$ journalctl --since "10 min ago" --no-pager → -- No entries --
```
(跑的时候那几条已经**出窗**了------"查不到"≠"没发生",也可能是**范围不对**)
**⑦ 带上下文搜出重启循环**------见上面"带上下文搜"
**⑧ `--until` 存在**
```
$ journalctl --until "10 min ago" --no-pager | wc -l → 52942
```
**⑨ `zgrep` 跨档搜**
```
$ zgrep -n 'session opened' /var/log/auth.log*.gz
/var/log/auth.log.2.gz:1:2026-09-20T00:17:01 ... CRON13544: ... session opened ...
```
线索区(学完后合上材料,自问自答)
**Q: 日志的两个用途是什么?判据是看日志的哪一部分?**
A: 排障 + 审计。判据**不是看日志长什么样**,是看**你要拿它回答什么问题**------排障问"出了什么事/为什么",审计问"谁/什么时候/做了什么"。
**Q: 同一条日志能同时属于两个用途吗?**
A: 能。用途不是日志上的标签,是你带着的问题决定的。`session opened` 最常见是审计,但"SSH 连不上、到底是**根本没登上**还是**登上又断**"这个问题,也用它回答。
**Q: 日志可信的三个前提是什么?三条的共同点是什么?**
A: ① 收集在跑 ② 时间戳理解对 ③ 相关来源被包含。共同点:**都是"日志里没有 ≠ 没发生"**。
**Q: 日志链路四步是哪四步?哪一步决定"存哪"?**
A: 来源 → 收集器 → 路由/保留 → 查看器。**第 ③ 步**(路由/保留)定"存哪、留多久"。
**Q: 为什么查看器必须在最后?**
A: 四步是**因果链**,第 ④ 步依赖第 ③ 步------记录没存下来,查看器看什么。
**Q: `systemd-journald` 和 `rsyslog` 是什么关系?**
A: **可并存,不是二选一**。journald 写二进制 journal、rsyslog 写纯文本文件,同一条事件两边各收一份(内容可能不同:rsyslog 会合并重复消息)。
**Q: 为什么不能背"日志在 `/var/log/syslog`"?**
A: 文件名**取决于发行版和路由配置**,不是 Linux 统一保证。Debian 系 `syslog` / RH 系 `messages`;只跑 journal 的机器两个都没有。**要现查**。
**Q: 到一台新机器,怎么现查"日志在哪、谁在写"?**
A: `systemctl --type=service --state=running | grep -E 'journal|syslog'`(谁在写)+ `ls -la /var/log`(有哪些文件)。
**Q: 一行日志的四段是什么?**
A: 时间戳 / 主机 / 程序PID / 正文。
**Q: `journalctl` 是干什么的?为什么不能直接 `cat` journal?**
A: 它是读 journal 的**查看器**。journal 是**二进制**(压缩、带索引),`cat` 出来是乱码;`journalctl` 负责解出来、用文本格式打出来。
**Q: `journalctl` 默认时间戳 `Oct 08 22:54:30` 比 syslog 里的少了哪两样?各会带来什么麻烦?**
A: 少**年份**、少**时区**。缺年份 → 跨年翻日志分不清先后;缺时区 → 换台 UTC 的机器,时间跟手表差 8 小时。
**Q: 为什么说"单独一行日志证明不了什么"?**
A: 正文是**应用自己写的输出**不是事实;每个程序**只知道它那一小块**(`systemd` 只知道"进程没了",不知道"为什么")。加上下文才拼出完整故事。
**Q: `less`、`tail -n`、`tail -F` 各什么场景?**
A: `less` 翻阅(通读、搜);`tail -n` 看最后 N 行(快照);`tail -F` 跟着看(实时,**轮转后还会重新接上**)。
**Q: `--since "10 min ago"` 和 `-n 10` 差在哪?**
A: 两条**不同的轴**------`--since` 框**时间**(这 10 分钟内所有,条数不定),`-n 10` 框**条数**(不管时间,最后 10 条)。
**Q: `--since` 和 `--until` 方向一样吗?**
A: **相反**。`--since` = 从某时刻**往后**到现在;`--until` = 从最早到某时刻(把之后的开除)。
**Q: 为什么搜日志要带 `-C 3`?**
A: **原因常出现在命中行的前后**。不带就只能看到孤立的一行、看不出因果------本机那个例子:不带只看到 10 条 `Exiting`,带上才看到 `restart counter is at 11`(**服务在无限重启**)。
**Q: 轮转档是什么?(了解层)**
A: `.1` / `.2.gz` / `.3.gz` 是**同一串日志被切成几段**;`zgrep` 能直接读 `.gz`;**按时间戳排,别按后缀排**。
总结(50字以内,用自己的话概括今天学到了什么)
日志从哪来(四步链路)、在哪(要现查不能背)、长什么样(四段)、怎么捞(框时间窗 + 带上下文搜)。
复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| --------------------- | --------- | ------------------------------------------------------ | ------------------------ |
| 日志两个用途 | 必学 | 排障 + 审计;用途由**你要问什么**决定 | 拿到日志先想"在问什么" |
| 三个前提 | 必学 | 收集在跑 / 时间戳对 / 来源被包含 | **日志没有 ≠ 没发生** |
| 链路四步 | 必学 | 来源 → 收集器 → 路由/保留 → 查看器 | 讲日志怎么流动 |
| 收集器"补充信息" | 必学 | 时间戳/主机/PID 是收集器**贴上去的** | 理解四段的来源 |
| journald vs rsyslog | 必学 | **可并存**;二进制 vs 纯文本 | 看日志服务 |
| 不能背路径 | 必学 | Debian `syslog` / RH `messages`;只跑 journal 的都没有 | 换机器 |
| 现查两条 | 必学 | `systemctl ... --state=running` + `ls -la /var/log` | 到新机器第一步 |
| 一行四段 | 必学 | 时间戳 / 主机 / 程序PID / 正文 | 读日志 |
| 一行 ≠ 事实 | 必学 | 正文是应用输出;**PID 会重复**;要看前后 | 别单行下结论 |
| `journalctl` | 必学 | 读 journal 的工具(二进制得靠它解) | 看 journal |
| journal 默认时间戳 | 必学 | `Oct 08 22:54:30` ------ **缺年份、缺时区** | 跨年/跨时区 |
| `less` | 必学 | 翻阅;`q` 退、`/` 搜 | 通读 |
| `tail -n` | 必学 | 最后 N 行(快照) | 看最近 |
| `tail -F` | 必学 | 跟着看;**轮转后重试** | 复现时盯着 |
| `--since` / `--until` | 必学 | 从...起 / 到...止;**方向相反** | 框时间 |
| `-n` vs `--since` | 必学 | 条数 vs 时间,两条轴 | 别混 |
| `grep -n -C 3` | 必学 | 前后各带 3 行 + 行号 | **日志 grep 排查的核心** |
| `-A` / `-B` / `-C` | 必学 | after / before / 前后 | 记选项 |
| `zgrep` / `zless` | 了解 | 直接读 `.gz` | 跨轮转边界 |
| 轮转档 | 了解 | `.1` / `.2.gz` 是同一串日志的片段;按时间戳排不按后缀 | 搜不到时往外找 |
旧知识回收(今天暴露出来的)
| 概念 | 一句话 | 出处 |
| ---------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------- |
| **目录的 `x` 只管"通行"** | 目录 `x` = 能进去/能穿过;**`r` 才管能不能列、`w` 才管能不能建删** | 今天抽考 09-08:答"能进去**操作**",用 `chmod 100` 反例撞破 |
| **改权限的人 = 主人 + root** | 机制是系统查"**你是不是主人**",**不看 rwx** | 今天抽考 09-08:**漏了 root**,且把机制说成目的("防止别人搞烂") |
| **`ls -ld` 看目录自己** | 加 `-d` 才不展开;`ls -l 目录` 列的是**里面** | 今天抽考 09-08:答 `ls -l`,差一个 `d` |
| **`/var` vs `/usr`** | `/var` = **会变**的(日志/缓存/spool);`/usr` = 放**软件** | 点 6 练里记反了(说"日志该放 /usr") |
| **`ps aux` 第一列是 USER** | 第 1 列 = **谁在跑**(用户名);最后一列 `COMMAND` 才是程序 | 点 6 练里把 `syslog`(用户)当成程序 |
| **`grep` 会把表头滤掉** | `ps aux \| grep xxx` 时表头那行不含关键词 → 被滤掉 → 看不到列名 | 同上,这是误读第 1 列的直接原因 |