名词解释教学工作区 · 课程 0006 · 形态 单概念 · 约 6 分钟 · 前置:0005 · 测试夹具 · 相关:0008 · CI / CD · 2026-10-01

巡检器:一遍跑完,把整批文件的毛病连位置一起报出来

你能做到:把「这套文件还讲不讲道理」写成一条条机器能判定的规则,一次跑完整批文件, 拿到「规则 · 文件:行号 · 原因」的清单,再用一个退出码让后续步骤自己决定放行还是拦下。

1 | 定义

巡检器(consistency checker,一致性检查器):把一批文件共同遵守的约定, 写成一条条可机器判定的规则 rule,一次跑完所有文件、逐条报出规则、位置与原因, 并把结论压在一个退出码 exit code 上的只读工具。它属于 静态检查 static analysis:只读文本,不运行内容,也不判断事实对不对。 就像小区保安每晚拿着同一张清单绕一圈:哪户门没关、哪盏灯不亮,连门牌号一起记在群里 —— 清单上没写的毛病,他那一圈也看不出来。

2 | 它解决什么麻烦

这类麻烦的共同点是:没有任何东西会因此报错,于是谁也没被提醒。

3 | 它怎么解决

约定 什么算「讲道理」 -> 规则 每条只盯一个可判定的特征 -> 全量扫描 每次都从零重算 -> 报告 规则 · 文件:行号 · 原因 -> 退出码 0 是过,非 0 是不过 -> 流水线 自动拦下或放行

本库自己也有一套这样跑的巡检器,常年守着库里的结构约定;它的规则清单属于库内部的事, 这里只讲这一类工具的通用形状。

4 | 用它的代价

5 | 真实使用场景

场景一:提交前就拦住,别等推上去才发现。

pipx install pre-commit
pre-commit install            # 装进 .git/hooks,以后每次 commit 前自动跑
pre-commit run --all-files    # 现在手动对全库跑一遍

markdownlint "**/*.md"        # 单跑一个:只管 Markdown 的排版(标题层级、空行、行宽)
lychee --offline "**/*.md"    # 单跑一个:只查链接的目标还在不在,不联网

每个检查器各回一个退出码;只要有一个非 0,钩子就不放这次提交过去。pre-commit 负责 「什么时候跑」和「只跑改动过的文件」,判据仍然在各自的检查器手里。

场景二:每次推送,在干净机器上跑一遍,结果贴在 PR 上。

# .github/workflows/check.yml —— 文件名随便,关键是这几行
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pipx install pre-commit && pre-commit run --all-files
      - run: lychee --offline --no-progress .

那台机器上没有你的本地状态:仓库是刚取的、检查器是新装的,跑出来的结论只看仓库里有什么 —— 这正是「每次都从零重算」想要的那个环境,也是它比「我记得跑一下」可靠的地方。

场景三:没有钩子也没有流水线,只想单独确认某一项。

markdownlint "docs/**/*.md"      # 只查排版
lychee --offline --no-progress . # 只查链接

一次性用法:单独跑那个检查器、看它回的退出码 —— 0 是干净,非 0 就带着规则名与行号去改。 Markdown 的排版检查是最常见的一例,因为它的写法松、人也最容易写歪。

6 | 和相近的东西怎么分

先问三句:它看单个文件内部,还是文件与文件之间?它管文档,还是管程序的行为? 它负责判定,还是只负责「什么时候跑」?

名称它是什么和本词什么关系
巡检器(一致性检查器) 扫一批文件、看它们之间的结构关系:链接、引用、数量、归属 本课主角,管跨文件的那一层
格式检查器 linter 只看单个文件内部的格式与排版:标题层级、空行、行宽 最容易被混为一谈的邻居:一个管这一页排得对不对,一个管这几页对得上对不对
链接检查器(如 lychee) 专查一类关系:文档里每条链接的目标还在不在 巡检器的一个窄口径实例,只做了规则里的一条
测试夹具 造出一段可控的输入,看程序的行为等不等于预期 换了个对象:它判程序的行为,不判文件的结构
CI / CD 流水线 每次推送时在干净机器上,把上面这几件事自动跑一遍 管「什么时候跑」;判据仍来自检查器自己的退出码
pre-commit 把检查挂在提交前的钩子上,不过就不许提交 把巡检器提前到本地:同一批规则,从推送后报警挪到提交前拦住

一句话分工:格式检查器管一页排得对不对,链接检查器管一条线通不通, 巡检器管整批文件对得上对不上,流水线与钩子只管「每次替我按一遍开关」。

7 | 常见误解

8 | 练习

三题自测,每题只有一个正确选项;选完立刻看到解释。

1. 巡检器能查出哪些问题,是由什么决定的?

对。覆盖面完全由写出来的规则决定:规则没写的关系,它一概不管 —— 所以「全绿」只能说明这一层过了, 说明不了内容对不对。

2. 一条规则反复报同一个老毛病,团队决定「先不管它」。这件事该落在哪份东西里?

对。已知的例外要显式写进白名单:它是一本「我知道它有、现在不修」的账。 薄薄一层没问题,厚起来就危险 —— 真问题会藏在里面,而报告看着越来越干净。

3. 想在「每次提交前」就拦住问题,而不是等推送之后才发现,靠什么?

对。pre-commit 这类工具把检查挂进提交前的钩子,不过就不许提交 —— 同一批规则, 只是在「什么时候跑」上往前挪了一步。