Kibitzr 8.0.0 配置参数详解
逐组实测 Kibitzr 8.0.0 的 checks、数据源、period/schedule 调度、CSS/XPath/Jinja/changes/jq 变换、notify/creds/templates/batch 等配置参数,记录 verify-cert 重试缺陷、creds 不插值、重复名不校验等与文档不符项及规避方法,附两套生产配置模板。
Kibitzr 8.0.0 配置参数详解
目标:把 Kibitzr 8.0.0 的
kibitzr.yml配置拆成可逐项验证的参数组,在 Ubuntu 22.04 服务器上对 checks、数据源、调度、变换、通知、凭据、模板复用、日志级别逐组实测,记录真实回显与「文档与实际不符」的坑位,给出可直接套用的生产配置模板。文中全部命令与输出均为 2026-10-27 真机实测。
一、环境信息
| 项目 | 实测值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS |
| 架构 | x86_64 |
| Python | 3.10.12 |
| Kibitzr | 8.0.0(/opt/kibitzr/venv) |
| 系统依赖 | git 2.34.1、jq 1.6 |
| 配置文件 | /opt/kibitzr/kibitzr.yml |
| 凭据文件 | /opt/kibitzr/kibitzr-creds.yml |
| 运行用户 | kibitzr(uid 999) |
| 测试 HTTP 站点 | http://127.0.0.1:8131(index.html、list.html、changed.txt、data.json) |
| 测试 HTTPS 站点 | https://127.0.0.1:8443(自签证书) |
测试站点的四个文件内容如下,后文的参数实验都基于它们:
$ curl -s http://127.0.0.1:8131/index.html
<html><head><title>Demo Site</title></head><body><div id="status">BUILD-2026-10-27-02</div><p>hello kibitzr</p></body></html>
$ cat /srv/www/list.html
<html><body>
<div class="item">Alpha</div>
<div class="item">Beta</div>
<section id="main"><p>Hello <b>World</b></p></section>
</body></html>
$ cat /srv/www/changed.txt
VERSION=4
$ cat /srv/www/data.json
{"name":"kibitzr","version":8,"tags":["monitor","python"]}
💡 说明:Kibitzr 的所有参数都写在 YAML 里,没有命令行参数可以覆盖单个检查项,也没有
--config选项指定配置文件路径。因此下文每个参数组都用一个独立工作目录 + 独立kibitzr.yml验证,互不干扰。
二、前置条件
2.1 已安装 Kibitzr 与可选依赖
/opt/kibitzr/venv/bin/kibitzr version
git --version
jq --version
8.0.0
git version 2.34.1
jq-1.6
changes 变换依赖系统 git,jq 变换依赖系统 jq,两者都不在 pip 依赖里。缺少时不是「功能降级」而是直接抛异常,详见第七节。
2.2 工作目录即配置目录
Kibitzr 只从当前工作目录和用户目录查找配置。在空目录执行会得到完整的查找路径清单(输出节选,实测省略中间调用栈):
mkdir -p /opt/kibitzr/work/case_nocfg
cd /opt/kibitzr/work/case_nocfg
/opt/kibitzr/venv/bin/kibitzr once
Traceback (most recent call last):
File "/opt/kibitzr/venv/bin/kibitzr", line 6, in <module>
sys.exit(extended_cli())
...
File "/opt/kibitzr/venv/lib/python3.10/site-packages/kibitzr/conf.py", line 43, in detect_config_dir
raise ConfigurationError(
kibitzr.exceptions.ConfigurationError: kibitzr.yml not found in following locations: kibitzr.yml, /root/.config/kibitzr/kibitzr.yml, /root/kibitzr.yml
查找顺序因此固定为:./kibitzr.yml → ~/.config/kibitzr/kibitzr.yml → ~/kibitzr.yml。同理,pages/(变更历史)与 stash.db(键值存储)也都是相对当前工作目录生成的,切换目录等于切换一整套状态。
⚠️ 注意:
kibitzr --help的选项只有-l/--log-level与--help,没有--config。想让 Kibitzr 读某个配置文件,只能cd到该文件所在目录,或用 systemd 的WorkingDirectory=固定目录。
三、参数查看与修改方式
3.1 查看当前生效的配置文件路径
配置文件没有专门的「show config」子命令,最可靠的方式是把日志级别调到 debug,它会打印实际加载的路径:
cd /opt/kibitzr/work/case_ext
/opt/kibitzr/venv/bin/kibitzr -l debug once
输出节选(实测首部):
2026-10-27 14:51:26,416 [DEBUG] kibitzr.conf: Loading credentials from /opt/kibitzr/work/case_ext/kibitzr-creds.yml
2026-10-27 14:51:26,416 [INFO] kibitzr.conf: No credentials file found at /opt/kibitzr/work/case_ext/kibitzr-creds.yml
2026-10-27 14:51:26,418 [DEBUG] kibitzr.conf: Loading settings from /opt/kibitzr/work/case_ext/kibitzr.yml
2026-10-27 14:51:26,441 [INFO] kibitzr.fetcher.loader: Fetching From template at http://127.0.0.1:8131/changed.txt
Loading settings from /opt/kibitzr/work/case_ext/kibitzr.yml 这类行就是最终生效的配置文件;同时 debug 还暴露了 HTTP 缓存、urllib3 连接、通知器发出的原始报告,排障时非常有用。
3.2 修改后的生效方式
常驻模式(kibitzr run)不会自动感知文件变化,改完 kibitzr.yml 需要重载进程。官方提供 kibitzr reload,它确实能定位 systemd 托管的主进程并发 SIGUSR1,但命令自身也会收到同一信号而退出:
cd /opt/kibitzr
/opt/kibitzr/venv/bin/kibitzr reload
2026-10-27 14:57:10,322 [INFO] kibitzr.app: Send singal SIGUSR1 to process: 5945
User defined signal 1
exit=138
服务端日志证明重载指令已生效:
Oct 27 14:57:10 kibitzr-lab kibitzr[5945]: 2026-10-27 14:57:10,322 [INFO] kibitzr.app: Received SIGUSR1. Flagging configuration reload
因此在脚本里它会被判定为失败(退出码 138)。更稳妥的做法是执行 systemctl restart kibitzr,或精确对主进程发信号:
kill -USR1 "$(systemctl show -p MainPID --value kibitzr)"
echo $?
0
💡 说明:
reload的退出码 138 是128 + 10(SIGUSR1),属于命令自身被信号终止,不是重载失败。判断重载是否成功要看服务端日志里的Received SIGUSR1. Flagging configuration reload。
四、参数总览
| 参数 | 作用 | 实测结论 |
|---|---|---|
checks | 检查项列表(顶层键) | 必填,列表元素为映射 |
name | 检查名 | 可省略,省略时自动命名为 http-127-0-0-1-8131-index-html 形式;重复名不报错 |
url | HTTP 数据源 | 与 script 二选一,都缺失直接抛 ConfigurationError |
script | Shell / Python 数据源 | 支持字符串(shell)与 python: 映射 |
delay | 浏览器渲染等待秒数 | 走 Selenium,缺驱动直接失败 |
verify-cert | 是否校验 HTTPS 证书 | false 可关闭校验;默认校验自签证书会失败 |
period | 周期秒数或人类可读时长 | 15、2 hours、37 minutes 均被接受 |
schedule | 日历调度 | 支持单条与列表,日志会逐条打印调度计划 |
transform | 变换流水线 | 支持 text/css/css-all/xpath/tag/json/jinja/changes/jq/shell 等 |
notify | 通知器列表 | 支持字符串项与映射项;空报告不通知 |
pages | checks 的历史别名 | 实测可用,兼容旧配置 |
templates | 配置模板(顶层键) | 通过 template: 引用,合并字段 |
batch / url-pattern / items | 批量生成检查 | {} 占位替换,实测可用 |
notifiers | 预定义通知器(顶层键) | 通过 python: 名称 引用 |
-l/--log-level | 日志级别 | 仅 `debug |
五、核心参数分类详解
5.1 checks 与 name:省略与重名
checks 是顶层列表,每个元素是一个检查。name 不是必填项,省略后 Kibitzr 用 URL 生成名字:
checks:
- url: http://127.0.0.1:8131/index.html
transform: [text]
notify:
- python: print("OK:"+content[:15])
- url: http://127.0.0.1:8131/index.html
transform: [text]
notify:
- python: print("OK2:"+content[:15])
$ /opt/kibitzr/venv/bin/kibitzr once
2026-10-27 14:51:11,589 [INFO] kibitzr.fetcher.loader: Fetching http-127-0-0-1-8131-index-html at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,613 [INFO] kibitzr.notifier.custom: Executing Python notifier
2026-10-27 14:51:11,613 [INFO] kibitzr.fetcher.loader: Fetching http-127-0-0-1-8131-index-html at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,615 [INFO] kibitzr.notifier.custom: Executing Python notifier
OK:Demo Site
BUILD
OK2:Demo Site
BUILD
两个检查都正常执行,但日志里名字完全相同,无法区分。重复的显式 name 同样不会被校验:
checks:
- name: Same
url: http://127.0.0.1:8131/index.html
notify: [python: print(content)]
- name: Same
url: http://127.0.0.1:8131/index.html
notify: [python: print(content)]
$ /opt/kibitzr/venv/bin/kibitzr once
2026-10-27 14:51:11,462 [INFO] kibitzr.fetcher.loader: Fetching Same at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,464 [INFO] kibitzr.notifier.custom: Executing Python notifier
2026-10-27 14:51:11,464 [INFO] kibitzr.fetcher.loader: Fetching Same at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,466 [INFO] kibitzr.notifier.custom: Executing Python notifier
⚠️ 注意:重复
name不报错、不告警,但pages/<name>/会被两个检查共用,一旦同时使用changes变换会互相覆盖历史。生产配置必须保证name唯一,建议用「业务-对象-指标」命名法(如pay-api-version)。
5.2 数据源:url、script、delay
url 抓取 HTTP(S) 页面;script 从命令输出或 Python 变量取值;两者都没有时直接失败:
checks:
- name: No source
transform: [text]
notify: [python: print(content)]
$ /opt/kibitzr/venv/bin/kibitzr once
kibitzr.exceptions.ConfigurationError: No fetcher is applicable for "{conf["name"]}"
这条报错把未插值的源码片段 {conf["name"]} 原样打印出来,看不出是哪个检查出错。检查数据源缺失时,请结合 -l debug 的加载路径与配置顺序人工定位。
script 支持两种形态,shell 用字符串,Python 用 python: 映射:
checks:
- name: Shell fetch
script: |
echo "SCRIPT-OK"
notify:
- python: print("FETCH=" + content.strip())
- name: Python fetch
script:
python: |
content = "PY-" + conf["name"]
ok = True
notify:
- python: print("FETCH=" + content)
2026-10-27 14:51:12,764 [INFO] kibitzr.fetcher.loader: Fetching 'Shell fetch' using script
2026-10-27 14:51:12,769 [INFO] kibitzr.fetcher.loader: Fetching 'Python fetch' using script
2026-10-27 14:51:12,769 [INFO] kibitzr.fetcher.script: Fetch using Python script
FETCH=SCRIPT-OK
FETCH=PY-Python fetch
Python 脚本必须给 content 赋值并把 ok 设为 True,否则本次视为失败、不进入变换与通知。
delay 会让抓取走 Selenium 浏览器路径。当前环境没有 Firefox 驱动,实测 40 秒后超时退出(输出节选,实测尾部):
checks:
- name: Browser delay
url: http://127.0.0.1:8131/list.html
delay: 2
transform: [text]
notify:
- python: print(content[:20])
$ timeout 40 /opt/kibitzr/venv/bin/kibitzr once
...
selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for firefox; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location
exit=124
⚠️ 注意:
delay不是「等待 2 秒」这么简单,它会切换到浏览器抓取,需要可用的 Firefox 与 geckodriver,并由selenium-manager在线获取驱动。纯 HTTP 场景不要配置delay;需要登录态或 JS 渲染时,先预装浏览器与驱动并验证驱动获取链路。
verify-cert 控制 HTTPS 证书校验。对自签证书默认校验会失败,关闭后可抓取成功:
checks:
- name: TLS insecure
url: https://127.0.0.1:8443/
verify-cert: false
transform: [text]
notify:
- python: print("INSECURE OK")
2026-10-27 14:52:12,231 [INFO] kibitzr.fetcher.loader: Fetching TLS insecure at https://127.0.0.1:8443/
/opt/kibitzr/venv/lib/python3.10/site-packages/urllib3/connectionpool.py:1129: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
2026-10-27 14:52:12,255 [INFO] kibitzr.notifier.custom: Executing Python notifier
INSECURE OK
而开启校验(默认)时,抓取失败后的重试逻辑会触发 Python 3.10 不兼容代码:
$ /opt/kibitzr/venv/bin/kibitzr once "TLS strict"
File "/opt/kibitzr/venv/lib/python3.10/site-packages/kibitzr/fetcher/simple.py", line 54, in sleep_on_exception
if isinstance(seconds, collections.Callable):
AttributeError: module 'collections' has no attribute 'Callable'
exit=1
⚠️ 注意:这是 Kibitzr 8.0.0 在 Python 3.10 上的真实缺陷——
collections.Callable在 Python 3.10 已移除,抓取失败进入重试时必然抛AttributeError,真正的证书错误被掩盖。规避方式:对内网自签站点配置verify-cert: false;对公网站点保持默认校验,并在证书到期前更换证书,避免走到失败重试分支。
5.3 调度:period 与 schedule
period 支持纯秒数与人类可读时长,三种写法实测都被接受:
checks:
- name: Period seconds
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content)]
period: 15
- name: Period human
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content)]
period: 2 hours
- name: Period minutes
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content)]
period: 37 minutes
2026-10-27 14:51:11,151 [INFO] kibitzr.fetcher.loader: Fetching Period seconds at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,176 [INFO] kibitzr.fetcher.loader: Fetching Period human at http://127.0.0.1:8131/index.html
2026-10-27 14:51:11,178 [INFO] kibitzr.fetcher.loader: Fetching Period minutes at http://127.0.0.1:8131/index.html
Demo Site
BUILD-2026-10-27-02
hello kibitzr
Demo Site
BUILD-2026-10-27-02
hello kibitzr
Demo Site
BUILD-2026-10-27-02
hello kibitzr
schedule 提供日历式控制,支持单条与列表,也支持把 every: day 写成单数:
checks:
- name: Daily noon
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content[:20])]
schedule:
every: 1
unit: days
at: "12:00"
- name: Thursday
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content[:20])]
schedule:
every: thursday
at: "12:00"
- name: Multi schedule
url: http://127.0.0.1:8131/index.html
transform: [text]
notify: [python: print(content[:20])]
schedule:
- every: day
at: "15:30"
- every: hour
常驻模式启动时,调度计划会逐条打印:
$ timeout 4 /opt/kibitzr/venv/bin/kibitzr run
2026-10-27 14:53:34,073 [INFO] kibitzr.fetcher.loader: Fetching Daily noon at http://127.0.0.1:8131/index.html
2026-10-27 14:53:34,094 [INFO] kibitzr.fetcher.loader: Fetching Thursday at http://127.0.0.1:8131/index.html
2026-10-27 14:53:34,096 [INFO] kibitzr.fetcher.loader: Fetching Multi schedule at http://127.0.0.1:8131/index.html
2026-10-27 14:53:34,098 [INFO] kibitzr.timeline: Scheduling checks for 'Daily noon' every 1 days at '12:00'
2026-10-27 14:53:34,098 [INFO] kibitzr.timeline: Scheduling checks for 'Thursday' every 1 thursday at '12:00'
2026-10-27 14:53:34,098 [INFO] kibitzr.timeline: Scheduling checks for 'Multi schedule' every 1 day at '15:30'
2026-10-27 14:53:34,098 [INFO] kibitzr.timeline: Scheduling checks for 'Multi schedule' every 1 hour
2026-10-27 14:53:34,098 [INFO] kibitzr.app: Starting infinite loop
要点:
run启动时会先立即执行一轮全部检查,再进入调度循环。- 一个检查可以配置多条
schedule,日志会为每条各打印一行。 period与schedule同时配置时,两者都会生效,容易造成重复通知,生产配置二选一。once与once NAME只执行一轮,不等待调度时间。
💡 技术拓展:调度语义有三种常见实现——固定间隔(每 N 秒)、固定时刻(每天 12:00)、日历表达式(cron)。固定间隔实现简单但会漂移;固定时刻适合日报类;cron 表达力最强但可读性差。Kibitzr 用
period覆盖固定间隔、用schedule覆盖固定时刻与星期,且不支持 cron 表达式,需要 cron 语义时请配合 systemd timer 或 crontab 在外部触发kibitzr once。
5.4 变换:text、css、css-all、xpath、tag、json
transform 是按顺序执行的流水线,前一步的输出是后一步的输入。六种选择器实测:
checks:
- name: T text
url: http://127.0.0.1:8131/list.html
transform:
- text
notify:
- python: print("TEXT=" + repr(content))
- name: T css
url: http://127.0.0.1:8131/list.html
transform:
- css: "section#main"
- text
notify:
- python: print("CSS=" + repr(content))
- name: T cssall
url: http://127.0.0.1:8131/list.html
transform:
- css-all: "div.item"
- text
notify:
- python: print("CSSALL=" + repr(content))
- name: T xpath
url: http://127.0.0.1:8131/list.html
transform:
- xpath: "//section[@id=\"main\"]/p"
- text
notify:
- python: print("XPATH=" + repr(content))
- name: T tag
url: http://127.0.0.1:8131/list.html
transform:
- tag: section
- text
notify:
- python: print("TAG=" + repr(content))
- name: T json
url: http://127.0.0.1:8131/data.json
transform:
- json
notify:
- python: print("JSON=" + content)
TEXT='Alpha\nBeta\nHello\nWorld'
CSS='Hello\nWorld'
CSSALL='Alpha\nBeta'
XPATH='Hello\nWorld'
TAG='Hello\nWorld'
JSON={
"name": "kibitzr",
"tags": [
"monitor",
"python"
],
"version": 8
}
逐项说明:
text提取页面全部文本并压成多行字符串,噪声最多,通常要配合选择器。css取第一个匹配元素;css-all取全部匹配元素并拼接。xpath与 CSS 等价能力,适合复杂层级;tag按标签名取第一个。json把响应体解析成 Python 对象并格式化输出,后续可直接交给jinja或jq。
5.5 变换:jinja
jinja 变换的上下文提供 env(环境变量)与 css() 等函数,并支持 Jinja 过滤器:
checks:
- name: Jinja env
url: http://127.0.0.1:8131/list.html
transform:
- jinja: "BUILD={{ env.MY_BUILD }}"
notify:
- python: print(content)
- name: Jinja filters
url: http://127.0.0.1:8131/list.html
transform:
- css: "section#main"
- jinja: "TEXT={{ css(\"section#main\") | text | upper }} NUM={{ \"12.34 USD\" | float | int }}"
notify:
- python: print(content)
MY_BUILD=REL-42 /opt/kibitzr/venv/bin/kibitzr once
BUILD=REL-42
TEXT=HELLO
WORLD NUM=12
但凭据不在 Jinja 上下文里,引用会直接渲染失败:
checks:
- name: Jinja creds
url: http://127.0.0.1:8131/changed.txt
transform:
- jinja: "CREDS=[{{ creds.service.username }}]"
notify:
- python: print(content)
2026-10-27 14:53:33,847 [WARNING] kibitzr.transformer.jinja_transform: Jinja render failed
jinja2.exceptions.UndefinedError: 'creds' is undefined
⚠️ 注意:凭据(creds)只在 Python 脚本抓取/变换里可用,Jinja 模板拿不到,且渲染失败仅告警、该检查后续流水线中断。需要把凭据拼进 URL 或请求头时,用
script: python:自行构造请求。
5.6 变换:changes
changes 通过与 pages/<name>/ 中的上一版比较产生报告,依赖系统 git。三种形态实测:
checks:
- name: Default diff
url: http://127.0.0.1:8131/changed.txt
transform:
- changes
notify:
- python: print("DEFAULT>>>\n" + content)
- name: Word diff
url: http://127.0.0.1:8131/changed.txt
transform:
- changes: word
notify:
- python: print("WORD>>>\n" + content)
把页面从 VERSION=4 改成 VERSION=5 后运行:
DEFAULT>>>
Default diff at http://127.0.0.1:8131/changed.txt
@@ -1 +1 @@
-VERSION=4
+VERSION=5
WORD>>>
[-VERSION=4-]{+VERSION=5+}
last change was 18 minutes ago
verbose 形态输出新旧值两段,适合只看最终值:
NOTIFY>>>
Build number at http://127.0.0.1:8131/changed.txt
New value:
VERSION=5
Old value:
VERSION=4
缺 git 时的报错:
cd /opt/kibitzr/work/case_changes
PATH=/opt/kibitzr/venv/bin /opt/kibitzr/venv/bin/kibitzr once
File "/opt/kibitzr/venv/lib/python3.10/site-packages/kibitzr/storage.py", line 42, in __init__
self.git = sh.Command('git').bake(
File "/opt/kibitzr/venv/lib/python3.10/site-packages/sh.py", line 1310, in __init__
raise CommandNotFound(path)
sh.CommandNotFound: git
exit=1
历史目录属主与当前运行用户不一致时,git 会拒绝操作:
fatal: detected dubious ownership in repository at '/opt/kibitzr/pages/Demo_build'
To add an exception for this directory, call:
git config --global --add safe.directory /opt/kibitzr/pages/Demo_build
⚠️ 注意:
pages/是 git 仓库,属主必须与运行用户一致。手工调试用 root、托管用kibitzr用户时,会同时踩到PermissionError与dubious ownership两类错误。统一用服务用户执行,或chown -R kibitzr:kibitzr /opt/kibitzr/pages。
5.7 变换与通知:jq、shell、python、stash
jq 变换把 JSON 交给系统 jq 处理:
checks:
- name: JQ
url: http://127.0.0.1:8131/data.json
transform:
- jq: ".tags[]"
notify:
- python: print("JQ=" + repr(content))
JQ='monitor\npython'
shell 变换对内容执行外部命令;python 通知器执行任意 Python;stash 通知器把值写入键值库:
checks:
- name: Shell transform
url: http://127.0.0.1:8131/changed.txt
transform:
- shell: "tr a-z A-Z"
notify:
- python: print("UPPER=" + content.strip())
- name: Shell notify
url: http://127.0.0.1:8131/changed.txt
notify:
- shell: "cat > /opt/kibitzr/work/case_script/notify.out"
- name: Stash notify
url: http://127.0.0.1:8131/changed.txt
notify:
- stash:
last_build: "{{ content | trim }}"
2026-10-27 14:51:12,789 [INFO] kibitzr.fetcher.loader: Fetching Shell transform at http://127.0.0.1:8131/changed.txt
2026-10-27 14:51:12,802 [INFO] kibitzr.notifier.custom: Executing Python notifier
2026-10-27 14:51:12,803 [INFO] kibitzr.fetcher.loader: Fetching Shell notify at http://127.0.0.1:8131/changed.txt
2026-10-27 14:51:12,812 [INFO] kibitzr.fetcher.loader: Fetching Stash notify at http://127.0.0.1:8131/changed.txt
UPPER=VERSION=4
查看 stash 实际写入的内容:
cd /opt/kibitzr/work/case_script
/opt/kibitzr/venv/bin/kibitzr stash
last_build: VERSION=4
stash 落在当前目录的 stash.db(底层文件实际名为 stash.db.db),可用于跨检查传递状态。
5.8 通知:notify 的两种写法
块式写法最清晰,也便于加多个通知器:
notify:
- python: print(content)
单行 flow 写法同样可用(实测两个检查均正常通知):
notify: [python: print(content)]
💡 说明:单行写法在 YAML 里是「字符串列表」,Kibitzr 会把它按
键: 值再解析一次,因此可用但可读性差。多通知器、多行 Python 时务必用块式。
5.9 creds:读取方式与「不插值」
凭据文件与 kibitzr.yml 同目录,默认权限 600。YAML 里的值按字面量读取,不做环境变量插值:
# kibitzr-creds.yml
service:
username: ${ KZ_USER }
password: ${ KZ_PASS }
# kibitzr.yml
checks:
- name: Creds lookup
script:
python: |
content = "USER=" + str(creds["service"]["username"]) + " PASS=" + str(creds["service"]["password"])
ok = True
notify:
- python: print(content)
导出真实环境变量后运行:
KZ_USER=alice KZ_PASS=s3cret /opt/kibitzr/venv/bin/kibitzr once
2026-10-27 14:51:12,166 [INFO] kibitzr.fetcher.loader: Fetching 'Creds lookup' using script
2026-10-27 14:51:12,166 [INFO] kibitzr.fetcher.script: Fetch using Python script
2026-10-27 14:51:12,166 [INFO] kibitzr.notifier.custom: Executing Python notifier
USER=${ KZ_USER } PASS=${ KZ_PASS }
⚠️ 注意:这是实测中最容易踩的坑——文档示例里的花括号变量写法只是占位符,Kibitzr 不会替换成环境变量,而是原样当作凭据值。凭据文件里必须写明文实际值(配合 600 权限与服务用户),或在 Python 脚本中自行
os.environ读取。凭据文件的路径固定为同目录的kibitzr-creds.yml,不能改名。
5.10 复用与扩展:templates、batch、notifiers、pages
四个顶层扩展能力一次实测:
notifiers:
common: |
print("SHARED=" + content.strip())
templates:
base:
url: http://127.0.0.1:8131/changed.txt
transform:
- text
notify:
- python: common
checks:
- name: From template
template: base
- name: Batch {}
batch: "Batch {}"
url-pattern: "http://127.0.0.1:8131/{}.txt"
items:
- changed
transform:
- text
notify:
- python: common
2026-10-27 14:51:12,957 [INFO] kibitzr.fetcher.loader: Fetching From template at http://127.0.0.1:8131/changed.txt
2026-10-27 14:51:12,977 [INFO] kibitzr.fetcher.loader: Fetching Batch changed at http://127.0.0.1:8131/changed.txt
SHARED=VERSION=4
SHARED=VERSION=4
templates定义公共字段,检查用template: 名称引用。batch中{}被items逐项替换,生成Batch changed;url-pattern同步替换。notifiers定义命名通知器,python: common直接引用。pages是checks的旧别名,同样可用:
pages:
- name: Legacy pages key
url: http://127.0.0.1:8131/changed.txt
notify:
- python: print("PAGES=" + content.strip())
2026-10-27 14:51:13,107 [INFO] kibitzr.fetcher.loader: Fetching Legacy pages key at http://127.0.0.1:8131/changed.txt
PAGES=VERSION=4
💡 说明:
templates与batch在官方配置文档中着墨不多,但 8.0.0 实测可用,适合「同站点多页面、同结构多环境」的批量监控。pages别名主要用于兼容旧配置,新配置统一写checks。
5.11 日志级别:-l / --log-level
可用值只有四个,非法值在参数解析阶段就被拒绝:
/opt/kibitzr/venv/bin/kibitzr -l verbose once
Usage: kibitzr [OPTIONS] COMMAND [ARGS]...
Try 'kibitzr --help' for help.
Error: Invalid value for '-l' / '--log-level': 'verbose' is not one of 'debug', 'info', 'warning', 'error'.
exit=2
默认 info;debug 会额外输出配置加载、HTTP 缓存与原始报告,适合排障;warning/error 适合生产降噪。日志默认输出到标准错误,systemd 托管后进入 journal。
5.12 状态目录:pages 与 stash.db
changes 生成的历史在 pages/<name>/(内部是 git 仓库),stash 通知器生成 stash.db.db:
/opt/kibitzr/pages
/opt/kibitzr/pages/Demo_build
/opt/kibitzr/pages/Demo_build/content
/opt/kibitzr/pages/Demo_build/.git
清理变更历史用 kibitzr clean,它删除当前目录下的 pages/:
cd /opt/kibitzr/work/case_changes2
ls pages
/opt/kibitzr/venv/bin/kibitzr clean
ls pages
Default_diff
Word_diff
exit=0
ls: cannot access 'pages': No such file or directory
六、生产配置模板
6.1 周期轮询型(适合版本号、库存、价格)
适用场景:2 核 4GB 以上、单机、检查项 20 个以内、允许 5 分钟级延迟。
notifiers:
log: |
print("[{name}] {content}".format(name=conf["name"], content=content.strip()))
templates:
web-text:
transform:
- text
notify:
- python: log
period: 5 minutes
checks:
- name: pay-api-version
template: web-text
url: https://pay.example.com/health
- name: order-page-build
template: web-text
url: https://order.example.com/version.txt
transform:
- text
- changes: verbose
逐项说明:templates 复用抓取与通知,period: 5 minutes 统一节奏;使用 changes 的检查会自动得到 git 历史,clean 前注意备份 pages/。
6.2 日历调度型(适合日报、活动页)
适用场景:检查项少、只关心固定时间点的变化。
checks:
- name: daily-report-page
url: https://ops.example.com/daily
transform:
- css: "#summary"
- text
- changes
schedule:
every: day
at: "08:30"
notify:
- python: |
print(content)
- name: weekly-activity
url: https://ops.example.com/activity
transform:
- text
- changes: word
schedule:
every: monday
at: "09:00"
notify:
- python: |
print(content)
调度会先立即执行一轮再进入循环,因此部署当天会立刻产生一次基线报告,这是正常现象。
七、常见问题
7.1 启动报 kibitzr.yml not found
Q1: 明明有配置文件,却提示找不到。
A: 只按 ./kibitzr.yml → ~/.config/kibitzr/kibitzr.yml → ~/kibitzr.yml 查找,且不支持 --config。用 -l debug 看 Loading settings from 的实际路径,或 cd 到配置目录再执行。
7.2 ConfigurationError: No fetcher is applicable
Q2: 检查项没写 url 也没写 script。
A: 每个检查必须至少有一个数据源。补充 url 或 script 后重试:
kibitzr.exceptions.ConfigurationError: No fetcher is applicable for "{conf["name"]}"
报错信息不会显示具体检查名,建议按配置顺序逐个注释排查。
7.3 changes 报 sh.CommandNotFound: git
Q3: 使用 changes 变换立即失败。
A: 安装系统 git:
apt-get install -y git
git --version
git version 2.34.1
7.4 fatal: detected dubious ownership
Q4: 手工用 root 跑过,切到 kibitzr 用户后 changes 失败。
A: pages/ 是 git 仓库,属主不一致会触发 git 的安全检查。统一属主:
chown -R kibitzr:kibitzr /opt/kibitzr/pages
不要用 git config --global --add safe.directory 绕过,这会把所有同名目录都放行,削弱安全检查。
7.5 creds 里的环境变量没有被替换
Q5: 凭据文件里写了花括号包裹的环境变量名,脚本拿到的是字面量。
A: Kibitzr 不做环境变量插值。直接在 kibitzr-creds.yml 写实际值并保持 600 权限,或在 Python 脚本里用 os.environ["KZ_USER"] 读取。
7.6 Jinja 报 'creds' is undefined
Q6: 想在 Jinja 模板里引用凭据。
A: Jinja 上下文只有 env、css() 与内容本身,没有 creds。把需要凭据的请求放到 script: python: 里完成。
7.7 浏览器检查卡住或报 NoSuchDriverException
Q7: 配置 delay 后长时间无输出,最终超时。
A: delay 需要 Firefox 与 geckodriver,首次运行由 selenium-manager 获取驱动。纯 HTTP 场景删掉 delay;确有需要时预装浏览器并保证驱动获取链路可用。
7.8 kibitzr reload 把命令自己杀掉了
Q8: 执行 reload 后当前命令异常退出,退出码 138。
A: 重载指令本身已生效,138 是命令自身收到 SIGUSR1(User defined signal 1)被终止的结果。脚本中改用:
kill -USR1 "$(systemctl show -p MainPID --value kibitzr)"
该命令退出码 0,服务端日志同样出现 Received SIGUSR1. Flagging configuration reload。不需要热重载时直接 systemctl restart kibitzr。
7.9 通知重复发送
Q9: 同一个检查在固定时间前后连续收到两次通知。
A: 同时配置了 period 与 schedule,两套调度都在生效。只保留一种,并确认 once 不是常驻调度。
八、参考链接
- 官方配置文档:
https://kibitzr.readthedocs.io/en/latest/configuration.html - 官方变换文档:
https://kibitzr.readthedocs.io/en/latest/transforms.html - 官方调度文档:
https://kibitzr.readthedocs.io/en/latest/schedule.html - 官方凭据文档:
https://kibitzr.readthedocs.io/en/latest/credentials.html - 官方仓库:
https://github.com/kibitzr/kibitzr - 本专栏安装篇:《Kibitzr 8.0.0 安装与首个监控任务》
- 本专栏认知篇:《Kibitzr 8.0.0 完整部署与实战指南》