Kibitzr 8.0.0 常用 CLI 命令与运维实践

逐条实测 Kibitzr 8.0.0 的 init/once/run/clean/stash/reload/version 等子命令与 -l 日志级别,覆盖一次执行、名称过滤、systemd 与 cron 托管、退出码、热重载自伤与升级回滚,并如实说明 --check/--verbose/--config 并不存在。

KibitzrKibitzrPython 编程监控Web 监控自动化运维2026/10/27

Kibitzr 8.0.0 常用 CLI 命令与运维实践

目标:把 Kibitzr 8.0.0 的 9 个子命令、全局日志选项、退出码与三种常驻方式(前台、systemd、cron)逐条实测,给出真实回显、运维脚本写法与踩坑规避。文中命令与输出均来自 2026-10-27 Ubuntu 22.04 真机实测,安装路径为 /opt/kibitzr/venv。

一、环境信息

项目实测值
操作系统Ubuntu 22.04.5 LTS
架构x86_64
Kibitzr8.0.0
可执行文件/opt/kibitzr/venv/bin/kibitzr
工作目录/opt/kibitzr
运行用户kibitzr(uid 999)
服务单元/etc/systemd/system/kibitzr.service
定时任务/etc/cron.d/kibitzr-once
测试站点http://127.0.0.1:8131

当前生效配置为一个 60 秒周期的检查:

checks:
  - name: Demo build
    url: http://127.0.0.1:8131/index.html
    transform:
      - css: "#status"
      - text
      - changes: verbose
    notify:
      - python: print(content)
    period: 60

二、工具概览

kibitzr --help 给出了全部子命令与全局选项:

/opt/kibitzr/venv/bin/kibitzr --help
Usage: kibitzr [OPTIONS] COMMAND [ARGS]...

  Run kibitzr COMMAND --help for detailed descriptions

Options:
  -l, --log-level [debug|info|warning|error]
                                  Logging level
  --help                          Show this message and exit.

Commands:
  clean          Clean change history
  firefox        Launch Firefox with persistent profile
  init           Create boilerplate configuration files
  once           Run kibitzr checks once and exit
  reload         Send signal to reload configuration for kibitzr process
  run            Run kibitzr in the foreground mode
  stash          Print stash contents
  telegram-chat  Return chat id for the last message sent to Telegram Bot
  version        Print version

九个命令的实际用途与本文对应小节:

命令作用常用场景本文小节
init生成骨架配置与凭据文件首次部署4.3
once [NAME]执行一轮后退出联调、cron/timer 触发4.4
run [NAME]前台常驻systemd 托管、排障4.5
clean删除变更历史重置基线4.7
stash打印键值存储查看跨检查状态4.8
reload向常驻进程发 SIGUSR1改配置后热重载4.9
firefox启动带持久配置的 Firefox浏览器抓取调试4.10
telegram-chat查询 Telegram 最近会话 IDTelegram 通知接入4.10
version打印版本升级/巡检核对4.2

💡 说明:Kibitzr 没有 check、test、--check、--verbose、--config 这些常见于其他监控工具的入口,也没有守护进程模式。判断配置是否正确只能靠 once 实跑;常驻必须依赖 systemd、cron 或 supervisor。

三、前置条件

3.1 用绝对路径调用

不要依赖登录 shell 的 PATH。systemd 单元与 cron 环境的最小 PATH 不包含虚拟环境,统一写绝对路径:

/opt/kibitzr/venv/bin/kibitzr version
8.0.0

3.2 工作目录决定状态文件位置

配置、pages/、stash.db 都相对当前目录。手工执行前先 cd 到 /opt/kibitzr,否则会出现「配置能读到、历史写到别处」的分裂状态:

cd /opt/kibitzr
ls -d pages stash.db.db 2>/dev/null
pages
stash.db.db

3.3 统一运行用户

服务以 kibitzr 用户运行,手工命令也应以同一用户执行:

su -s /bin/bash kibitzr -c 'cd /opt/kibitzr && /opt/kibitzr/venv/bin/kibitzr once'

用 root 直接运行会造成 pages/ 属主变化,后续服务启动报 PermissionError 或 git dubious ownership,排查方法与修复见第六节。

四、各工具详解

4.1 全局选项:-l / --log-level

默认级别为 info。四个取值中 debug 输出最详细,会打印配置加载路径、HTTP 缓存命中与通知器原始报告:

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
2026-10-27 14:51:26,442 [DEBUG] cachecontrol.controller: Looking up "http://127.0.0.1:8131/changed.txt" in the cache
2026-10-27 14:51:26,464 [DEBUG] kibitzr.notifier.factory: Sending report: 'VERSION=5'

warning 级别几乎不输出正常运行信息,适合生产降噪:

cd /opt/kibitzr/work/case_changes
/opt/kibitzr/venv/bin/kibitzr -l warning once
exit=0

非法级别在参数解析阶段就被拒绝,退出码 2:

/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'.

4.2 version:版本核查

/opt/kibitzr/venv/bin/kibitzr version
8.0.0

需要注意 --version 不是全局选项,会直接报错:

/opt/kibitzr/venv/bin/kibitzr --version
Usage: kibitzr [OPTIONS] COMMAND [ARGS]...
Try 'kibitzr --help' for help.

Error: No such option '--version'.

version 的成功退出码为 0:

/opt/kibitzr/venv/bin/kibitzr version >/dev/null
echo $?
0

4.3 init:生成骨架配置

在空目录执行会生成 kibitzr.yml 与 kibitzr-creds.yml:

mkdir -p /opt/kibitzr/work/d1_init
cd /opt/kibitzr/work/d1_init
/opt/kibitzr/venv/bin/kibitzr init
ls -la
2026-10-27 14:57:09,974 [INFO] kibitzr.bootstrap: Saving sample check in kibitzr.yml
2026-10-27 14:57:09,974 [INFO] kibitzr.bootstrap: Creating kibitzr-creds.yml
total 16
drwxr-xr-x  2 root    root    4096 Oct 27 14:57 .
drwxr-xr-x 24 kibitzr kibitzr 4096 Oct 27 14:57 ..
-rw-------  1 root    root     173 Oct 27 14:57 kibitzr-creds.yml
-rw-r--r--  1 root    root     308 Oct 27 14:57 kibitzr.yml

生成的骨架配置包含一个 PyPI 版本检查,可以直接跑:

# Format: http://kibitzr.readthedocs.io/en/latest/configuration.html
checks:
  - name: Kibitzr release
    url: https://pypi.python.org/pypi/kibitzr/json
    transform:
      - jinja: |
          {{ json["info"]["version"] }}
      - changes: verbose
    notify:
      - python: print(content)
    period: 5

⚠️ 注意:init 不做「已存在则跳过」判断,也没有 --force 开关。在已有配置目录执行前先备份 kibitzr.yml;生产目录不要执行 init。

4.4 once:单次执行与名称过滤

不带参数执行全部检查:

su -s /bin/bash kibitzr -c 'cd /opt/kibitzr && /opt/kibitzr/venv/bin/kibitzr once'
2026-10-27 14:57:10,150 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html

内容未变化时只有抓取日志,不产生通知,退出码 0。带名称参数只执行匹配的检查:

su -s /bin/bash kibitzr -c 'cd /opt/kibitzr && /opt/kibitzr/venv/bin/kibitzr once "Demo build"'
2026-10-27 14:51:35,107 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html

名称写错时不会执行任何检查,并以 1 退出:

cd /opt/kibitzr
/opt/kibitzr/venv/bin/kibitzr once "NoSuchCheck"
2026-10-27 14:51:35,283 [INFO] kibitzr.checker: Filtered list of checks to: ''
2026-10-27 14:51:35,283 [ERROR] kibitzr.checker: Following check(s) were not found: 'NoSuchCheck'
2026-10-27 14:51:35,283 [WARNING] kibitzr.app: No checks defined. Exiting
exit=1

once 的成功退出码统一为 0:

cd /opt/kibitzr/work/case_changes
/opt/kibitzr/venv/bin/kibitzr once >/dev/null 2>&1
echo $?
0

💡 说明:once 会在每次执行时读取配置并立即跑一轮,非常适合由 cron 或 systemd timer 触发;它不会等待 period/schedule,因此定时精度完全由外部调度器决定。

4.5 run:前台常驻与信号退出码

run 是 systemd 的 ExecStart,启动后先立刻执行一轮,再进入无限循环:

su -s /bin/bash kibitzr -c 'cd /opt/kibitzr && /opt/kibitzr/venv/bin/kibitzr run'
2026-10-27 14:56:47,266 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
2026-10-27 14:56:47,308 [INFO] kibitzr.timeline: Scheduling checks for 'Demo build' every 60 seconds
2026-10-27 14:56:47,308 [INFO] kibitzr.app: Starting infinite loop

前台进程收到 SIGTERM 时按 shell 惯例返回 143(128+15):

exit=143

而通过 systemd 停止时,Kibitzr 的内部优雅退出路径返回 1,systemd 因此把这次停止记为 failed:

systemctl stop kibitzr
echo "stop_exit=$?"
systemctl is-active kibitzr
echo "is_active_exit=$?"
stop_exit=0
failed
is_active_exit=3
systemctl status kibitzr --no-pager -l | head -6
× kibitzr.service - Kibitzr web change monitor
     Loaded: loaded (/etc/systemd/system/kibitzr.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Tue 2026-10-27 14:57:11 UTC; 8ms ago
    Process: 5945 ExecStart=/opt/kibitzr/venv/bin/kibitzr run (code=exited, status=1/FAILURE)
   Main PID: 5945 (code=exited, status=1/FAILURE)
        CPU: 322ms

再次启动即可恢复:

systemctl start kibitzr
sleep 3
systemctl is-active kibitzr
active

⚠️ 注意:systemctl stop 的返回码是 0(停止动作成功),但单元状态会变成 failed。监控平台若用 is-active 判活,会把正常的计划内停机误报为故障。规避方式:停机脚本先 systemctl disable,或在监控里把「维护窗口内的 failed」列为白名单。

run 也支持名称过滤,只启动指定检查的调度循环。

4.6 reload:热重载配置

修改 kibitzr.yml 后无需重启进程,reload 会向常驻进程发送 SIGUSR1:

su -s /bin/bash kibitzr -c '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

同一时刻 reload 命令自身也收到 SIGUSR1 并以 138 退出(User defined signal 1),因此在脚本里 set -e 会被判定为失败。

⚠️ 注意:reload 能正确找到 systemd 托管的主进程并发信号,但命令本身会「自杀」退出 138。自动化脚本不要直接调用 reload,改用精确指向主进程的方式:

kill -USR1 "$(systemctl show -p MainPID --value kibitzr)"
echo $?
0

服务端同样记录 Received SIGUSR1. Flagging configuration reload,且命令退出码为 0。若不想依赖信号,systemctl restart kibitzr 是最直观的兜底。

4.7 clean:清理变更历史

clean 删除当前目录的 pages/,下次运行会重新建立基线:

cd /opt/kibitzr/work/case_changes2
ls pages
/opt/kibitzr/venv/bin/kibitzr clean
echo "exit=$?"
ls pages
Default_diff
Word_diff
exit=0
ls: cannot access 'pages': No such file or directory

⚠️ 注意:clean 不支持按名称清理,也没有 --dry-run,会删除全部检查的历史。只想重置单个检查时,手工删除对应目录:rm -rf pages/<检查名>。删除后下一次 changes 会以当前内容为基线,不产生通知。

4.8 stash:查看键值存储

stash 通知器写入的数据可通过同名子命令查看:

cd /opt/kibitzr/work/case_script
/opt/kibitzr/venv/bin/kibitzr stash
last_build: VERSION=4

没有写入过时输出为空,退出码仍为 0:

cd /opt/kibitzr
/opt/kibitzr/venv/bin/kibitzr stash
echo "exit=$?"
exit=0

数据实际落在 stash.db(底层文件名 stash.db.db),属于 shelve 键值库,不应手工用文本编辑器修改。

4.9 firefox 与 telegram-chat:辅助命令

firefox 用持久化 profile 启动浏览器,供需要登录态的抓取场景手工预登录:

/opt/kibitzr/venv/bin/kibitzr firefox --help
Usage: kibitzr firefox [OPTIONS]

  Launch Firefox with persistent profile

Options:
  --help  Show this message and exit.

telegram-chat 用于获取 Telegram 机器人最近一条消息的 chat id,方便填写通知目标:

/opt/kibitzr/venv/bin/kibitzr telegram-chat --help
Usage: kibitzr telegram-chat [OPTIONS]

  Return chat id for the last message sent to Telegram Bot

Options:
  --help  Show this message and exit.

💡 说明:子命令名是连字符形式 telegram-chat,不是文档里常见的下划线写法 telegram_chat;写错会得到 No such command。

4.10 不存在的命令与选项

Kibitzr 8.0.0 没有独立校验命令,也没有 --check、--verbose、--config:

/opt/kibitzr/venv/bin/kibitzr check
Usage: kibitzr [OPTIONS] COMMAND [ARGS]...
Try 'kibitzr --help' for help.

Error: No such command 'check'.
exit=2
/opt/kibitzr/venv/bin/kibitzr once --check
Usage: kibitzr once [OPTIONS] [NAME]...
Try 'kibitzr once --help' for help.

Error: No such option '--check'. Did you mean '--help'?
exit=2
/opt/kibitzr/venv/bin/kibitzr once --verbose
Usage: kibitzr once [OPTIONS] [NAME]...
Try 'kibitzr once --help' for help.

Error: No such option '--verbose'.
exit=2
/opt/kibitzr/venv/bin/kibitzr --config /tmp/x.yml once
Usage: kibitzr [OPTIONS] COMMAND [ARGS]...
Try 'kibitzr --help' for help.

Error: No such option '--config'.
exit=2

替代方案:

  • 校验配置:在目标目录执行 kibitzr once,或用 kibitzr -l debug once 看加载路径与报错。
  • 详细日志:全局加 -l debug,不存在 --verbose。
  • 指定配置:先 cd 到配置目录,或由 systemd WorkingDirectory= 固定;不存在 --config。

4.11 退出码与日志

汇总实测退出码,便于写监控脚本:

场景命令退出码
正常执行一轮once0
名称过滤成功once "Demo build"0
名称不存在once "NoSuchCheck"1
缺少配置文件任意命令1
检查缺数据源once1
缺 git 但用了 changesonce1
参数/选项非法-l verbose、--check2
优雅停止(systemd)systemctl stop单元 failed,进程 1
前台被 SIGTERMrun143
reload 自伤reload138
浏览器抓取超时timeout 40 once124(timeout 返回)

日志统一走标准错误,级别前缀为 [DEBUG]/[INFO]/[WARNING]/[ERROR],格式为 时间 [级别] 模块: 消息;托管后由 systemd 收进 journal。

4.12 systemd 运维命令

systemctl status kibitzr --no-pager -l

输出节选(实测首部):

● kibitzr.service - Kibitzr web change monitor
     Loaded: loaded (/etc/systemd/system/kibitzr.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2026-10-27 14:49:19 UTC; 6s ago
   Main PID: 5945 (kibitzr)
      Tasks: 1 (limit: 2932)
     Memory: 24.7M
journalctl -u kibitzr -n 5 --no-pager
Oct 27 14:52:19 kibitzr-lab kibitzr[5945]: 2026-10-27 14:52:19,787 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
Oct 27 14:53:19 kibitzr-lab kibitzr[5945]: 2026-10-27 14:53:19,858 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
Oct 27 14:54:19 kibitzr-lab kibitzr[5945]: 2026-10-27 14:54:19,933 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
Oct 27 14:55:20 kibitzr-lab kibitzr[5945]: 2026-10-27 14:55:20,004 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
Oct 27 14:56:20 kibitzr-lab kibitzr[5945]: 2026-10-27 14:56:20,098 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
systemctl is-enabled kibitzr
enabled

常用组合:

  • 改配置后:systemctl restart kibitzr
  • 看最近错误:journalctl -u kibitzr -p err -n 50 --no-pager
  • 持续观察:journalctl -u kibitzr -f
  • 停止并禁止自启:systemctl disable --now kibitzr

4.13 systemd timer 定时触发

不用常驻进程时,可以用 oneshot service + timer 每 5 分钟执行一次 once。先写服务单元:

# /etc/systemd/system/kibitzr-once.service
[Unit]
Description=Kibitzr single check run

[Service]
Type=oneshot
User=kibitzr
Group=kibitzr
WorkingDirectory=/opt/kibitzr
ExecStart=/opt/kibitzr/venv/bin/kibitzr once

再写定时器单元:

# /etc/systemd/system/kibitzr-once.timer
[Unit]
Description=Run Kibitzr every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target

启用并查看下次/上次触发时间:

systemctl daemon-reload
systemctl enable --now kibitzr-once.timer
systemctl list-timers kibitzr-once.timer --no-pager
NEXT                        LEFT          LAST                        PASSED    UNIT               ACTIVATES
Tue 2026-10-27 15:05:00 UTC 4min 39s left Tue 2026-10-27 15:00:19 UTC 776ms ago kibitzr-once.timer kibitzr-once.service

1 timers listed.
Pass --all to see loaded but inactive timers, too.
systemctl is-active kibitzr-once.timer
active

停用后状态为 inactive(is-active 退出码 3):

systemctl disable --now kibitzr-once.timer
systemctl is-active kibitzr-once.timer
echo "after_stop_exit=$?"
Removed /etc/systemd/system/timers.target.wants/kibitzr-once.timer.
inactive
after_stop_exit=3

⚠️ 注意:timer 与常驻 kibitzr.service 只能二选一。两者同时启用会让同一检查被执行两次,通知重复。timer 方式的优点是每次都是干净进程、无内存累积;缺点是每次启动都要重新加载配置与状态。

4.14 cron 定时触发

不使用常驻进程时,可用 cron 每分钟触发一次 once。本环境使用 /etc/cron.d 方式,而不是用户 crontab:

crontab -u kibitzr -l
no crontab for kibitzr
exit=1
cat /etc/cron.d/kibitzr-once
* * * * * kibitzr cd /opt/kibitzr && /opt/kibitzr/venv/bin/kibitzr once >> /var/lib/kibitzr/cron.log 2>&1

任务按分钟执行,日志逐分钟追加:

tail -4 /var/lib/kibitzr/cron.log
2026-10-27 14:53:01,306 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
2026-10-27 14:54:01,487 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
2026-10-27 14:55:01,674 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html
2026-10-27 14:56:01,858 [INFO] kibitzr.fetcher.loader: Fetching Demo build at http://127.0.0.1:8131/index.html

⚠️ 注意:cron.d 文件必须指定运行用户,日志重定向目录必须对该用户可写。首次测试把日志指向 /var/log/kibitzr-cron.log 时因 kibitzr 无写权限而静默失败,改为 /var/lib/kibitzr/cron.log 后正常。另外 cron 与 systemd 常驻不要同时启用,否则同一检查会被执行两次、通知重复。

4.15 升级与回滚

升级前先记录当前版本,再固定版本号安装:

/opt/kibitzr/venv/bin/kibitzr version
/opt/kibitzr/venv/bin/pip install --upgrade kibitzr==8.0.0
8.0.0
Requirement already satisfied: frozenlist>=1.1.1 in ./opt/kibitzr/venv/lib/python3.10/site-packages (from aiohttp>=3.8.4->twilio->kibitzr==8.0.0) (1.8.0)
Requirement already satisfied: multidict<8.0,>=4.5 in ./opt/kibitzr/venv/lib/python3.10/site-packages (from aiohttp>=3.8.4->twilio->kibitzr==8.0.0) (7.1.0)
Requirement already satisfied: propcache>=0.2.0 in ./opt/kibitzr/venv/lib/python3.10/site-packages (from aiohttp>=3.8.4->twilio->kibitzr==8.0.0) (0.5.4)
Requirement already satisfied: yarl<2.0,>=1.25.1 in ./opt/kibitzr/venv/lib/python3.10/site-packages (from aiohttp>=3.8.4->twilio->kibitzr==8.0.0) (1.25.1)

包元数据可用于核对来源与许可:

/opt/kibitzr/venv/bin/pip show kibitzr
Name: kibitzr
Version: 8.0.0
Summary: Self hosted web page changes monitoring
Home-page: https://github.com/kibitzr/kibitzr
Author: Peter Demin
Author-email: kibitzrrr@gmail.com
License: MIT license
Location: /opt/kibitzr/venv/lib/python3.10/site-packages

回滚策略:升级前把 venv 整体打包备份,回滚时解包恢复并 systemctl restart kibitzr;或重新执行 pip install kibitzr==<旧版本>。pages/ 与 stash.db 是版本无关的数据,不需要回滚,但跨大版本升级前仍建议备份。

五、注意事项

  1. 配置文件没有覆盖机制:不存在 --config,只能靠工作目录。systemd 用 WorkingDirectory=、cron 用 cd 显式固定。
  2. 状态文件跟随工作目录:在别的目录执行 once 会生成另一套 pages/ 与 stash.db,看起来像「历史丢失」。
  3. 运行用户必须统一:root 与 kibitzr 混用会同时触发 PermissionError 与 git dubious ownership。
  4. 不要依赖 reload 的退出码:热重载本身有效,但命令退出 138;脚本用 kill -USR1 指向 MainPID。
  5. systemctl stop 后状态为 failed:这是 Kibitzr 优雅退出码 1 导致的,不代表停止失败。
  6. 可选依赖在系统层:changes 需要 git,jq 变换需要 jq,浏览器抓取需要 Firefox 与驱动,缺一个就整体失败。
  7. once 是唯一可靠的配置校验手段:没有 --check,写完配置先跑一次再交给 systemd。
  8. 常驻与定时器互斥:kibitzr.service(run)与 kibitzr-once.timer(once)只能启用一种,否则重复执行。

六、常见问题

6.1 kibitzr: command not found

Q1: 直接敲 kibitzr 提示找不到命令。

A: 没有激活虚拟环境。用绝对路径 /opt/kibitzr/venv/bin/kibitzr,或临时 source /opt/kibitzr/venv/bin/activate。systemd 与 cron 中不要依赖 PATH。

6.2 PermissionError: [Errno 13] Permission denied

Q2: 手工执行正常,systemd 启动反复失败,journal 报 pages/Demo_build/content 权限不足。

A: 手工用 root 跑过,pages/ 属主变成 root。统一属主并重启:

chown -R kibitzr:kibitzr /opt/kibitzr/pages
systemctl restart kibitzr
systemctl is-active kibitzr
active

6.3 fatal: detected dubious ownership in repository

Q3: 使用 changes 时 git 拒绝操作。

A: git 检测到仓库属主与当前用户不一致。与上一条同源,执行 chown -R kibitzr:kibitzr /opt/kibitzr/pages,不要用 safe.directory 全局放行。

6.4 sh.CommandNotFound: git / jq

Q4: once 直接抛异常退出。

A: 安装系统依赖:

apt-get install -y git jq
git --version
jq --version
git version 2.34.1
jq-1.6

6.5 once 没有输出,也没收到通知

Q5: 执行成功但看不到内容。

A: 三种可能:内容与上一版相同(changes 不报告);报告为空(Kibitzr 不通知空报告);通知器不是控制台类。用 -l debug 确认 Sending report: 是否存在:

2026-10-27 14:51:26,464 [DEBUG] kibitzr.notifier.factory: Sending report: 'VERSION=5'

6.6 systemctl stop 后 is-active 显示 failed

Q6: 正常停机却被监控判为故障。

A: Kibitzr 收到 SIGTERM 后返回退出码 1,systemd 记为 exit-code。属预期行为,不是停止失败。监控白名单需排除维护窗口,或停机前先 systemctl disable。

6.7 reload 返回 138

Q7: 执行 reload 后脚本中断。

A: 命令自身收到 SIGUSR1 被杀(User defined signal 1),服务端其实已标记重载。改用:

kill -USR1 "$(systemctl show -p MainPID --value kibitzr)"

6.8 cron 触发了但没有日志

Q8: cron.d 已配置,cron.log 不生成。

A: 重定向目标目录对运行用户不可写,cron 静默失败。改为 /var/lib/kibitzr/cron.log 并 chown kibitzr:kibitzr /var/lib/kibitzr,或在命令里用 su 切换用户。

七、参考链接