编程 pgbot + pgterm:只读角色读统计视图,把 Postgres 体检接进终端和 CI

2026-10-07 21:31:57

pgbot + pgterm:只读角色读统计视图,把 Postgres 体检接进终端和 CI

pgbot(GitHub / pgbot.dev)是 Go 写的静态二进制,Apache-2.0,支持 PostgreSQL 14–18(16–18 完整支持),状态 beta,--json 契约版本化,当前 1.5.0。它用只读连接读 Postgres 自己的统计视图,输出「以发现为主」的健康报告,并告诉你自上次运行以来发生了什么变化。它是个 client,像 psql 一样走 wire protocol,不在数据库里装任何东西:没有扩展、表、角色;没有 agent、没有外部服务、没有写权限。

pgterm(GitHub / pgterm.dev)是 Rust 写的终端 UI,Apache-2.0,beta,定位是「你所有 Postgres 库的 htop」。无 agent、无 daemon、无 web 面板。它读 pgbot 的版本化 --json,而不是解析终端输出。

pgbot

快速开始与连接解析

curl -fsSL https://pgbot.dev/install | sh
pgbot inspect "postgres://pgbot_ro@host:5432/db"

连接串解析顺序:参数 > $DATABASE_URL > $PGBOT_DATABASE_URL > $PGSERVICE。

只读靠角色,不靠 flag

CREATE ROLE pgbot_ro LOGIN PASSWORD '...';
GRANT pg_monitor TO pgbot_ro;
GRANT CONNECT ON DATABASE yourdb TO pgbot_ro;

这段 SQL 可以用 pgbot init "postgres://admin@host:5432/db" | psql 生成,pgbot 自己绝不执行;pgbot init --verify "..." 校验角色。会话级还有一层加固:default_transaction_read_only、statement_timeout=15s、lock_timeout=2s,每个查询包在自己的 BEGIN READ ONLY … COMMIT 里——用 COMMIT 而不是 rollback,因为 rollback 会把自己要报的 xact_rollback 计数抬高。

开销:一次运行最多开 4 个连接的池,计数器在 --interval 间隔(默认 1s)采样两次,几秒完成;自己会话/事务/临时用量会从报告里排除。

每次运行写本地 baseline,从第三次运行起会提示「什么变了、为什么重要」:某查询变慢、某表开始全表扫、某索引不再被用。发现是确定性的,全部由 Go 从 SQL 算出;可选 AI 层只负责解释,不生成发现。ask/explain 需要 OPENAI_API_KEY / GEMINI_API_KEY / ANTHROPIC_API_KEY / XAI_API_KEY 之一,或任意 OpenAI 兼容端点(PGBOT_AI_BASE_URL)。

报告与命令

默认报告:四条仪表(cache hit;lock wait 并指出肇事 query;rollbacks;idle idx 字节数占库比例)、一行 checked 列出干净子系统、健康分(如 82/100)、发现按 CRITICAL/WARNING/NOTE 分桶。pgbot inspect --full 增加子系统状态板与明细表。

命令:inspect(--full)、lint(schema-only,可对空的 CI 库跑,等价 inspect --profile=schema --no-store)、init(--verify)、diff、why(从 baseline 解释回归,symptom←mechanism←antecedent)、indexes(零扫描索引,并告诉你哪些不要 drop)、queries(按 pg_stat_statements 总耗时排,--by-calls 按调用次数)、tables(最大表 + 行数 + seq vs idx scans)、vacuum(每表死元组 + 是否 due,判据是默认 50 + live 的 20%)、logs、waits、erd(--mermaid)、activity、report(自包含 HTML)、advise(需要 hypopg 扩展 + PG16+)、ask/explain、explain-finding、mcp、config/baselines。

inspect 关键 flag:--json、--format=text|json|sarif|junit|prometheus(SARIF 可上传 GitHub Security tab)、--fail-on=critical|warn|info|none(CI 门禁)、--profile=full|schema、--fail-on-new 、--all-databases、--all-instances(Aurora,实验)、--config (.pgbot.toml 配阈值、严重级别重映射、[[ignore]])。

退出码契约与安装

退出码是脚本契约:0 clean、1 warn、2 critical、3 连接/执行失败、64 用法错误。

  • npx @pgbot/cli inspect "$DATABASE_URL"——包名是 scoped,裸 pgbot 会 E404,因为与 got 太像
  • curl -fsSL https://pgbot.dev/install | sh——校验 SHA256 + cosign keyless 签名,PGBOT_REQUIRE_SIGNATURE=1 强制
  • brew install pgrundev/tap/pgbot
  • yay -S pgbot-bin
  • go install github.com/pgrundev/pgbot/cmd/pgbot@latest
  • docker run --rm -e DATABASE_URL ghcr.io/pgrundev/pgbot inspect

私有库、依赖、MCP 与 caveat

私有库走 --ssh-tunnel bastion.example.com(或 user@host:port、~/.ssh/config 别名),环境变量 PGBOT_SSH_TUNNEL。它是 dialer,不是 ssh -L:DSN 仍写真实主机名,sslmode=verify-full 仍校验该主机。

依赖:pg_monitor 登录角色;queries 段需要 pg_stat_statements(缺了会打印各 provider 的安装步骤);advise 需要 hypopg + PG16+。

MCP:pgbot mcp 走 stdio,只暴露确定性只读工具——inspect(完整发现 JSON)、unused_indexes、top_queries(含每个 query 的 total time 占比)、vacuum_health(含计算出的 due 标记);不向模型暴露原始连接串或查询字面量。

两个边界要记住:在 primary 上 indexes 的零扫描计数是 per-node,副本可能仍在用某个看起来没用的索引;pgbot 不是监控平台,有看板/告警/长留存/多主机汇总需求时应上 pganalyze / Percona PMM / pgwatch。

pgterm

安装

curl -fsSL https://raw.githubusercontent.com/pgrundev/pgterm/main/install.sh | sh

pgbot 不在 PATH 时会一并安装,PGTERM_NO_PGBOT=1 可跳过。其他方式:

  • brew install pgrundev/tap/pgterm pgrundev/tap/pgbot
  • Windows PowerShell:irm https://pgterm.dev/install.ps1 | iex
  • 源码:cargo build --release

添加库与跳板机

export DATABASE_URL='postgresql://user:password@host:5432/dbname'
pgterm add production        # 先校验再保存
pgterm                       # 打开 UI

export STAGING_DATABASE_URL='...'
pgterm add staging --env STAGING_DATABASE_URL

--open 直接进入;--stage prod 打环境徽标;pgterm list 只列名字不列值。

pgterm add production --env PROD_DATABASE_URL --ssh deploy@bastion.example.com

--ssh 取 [user@]host[:port] 或 ~/.ssh/config 别名;DSN 仍写真实库主机,不开本地端口,sslmode=verify-full 仍生效。

配置在 ~/.config/pgterm/config.toml(或 $XDG_CONFIG_HOME/pgterm/config.toml),只存环境变量「名字」,绝不存连接串;每个库可设 name/env/stage/ssh,settings.interval_seconds=60、max_concurrent_checks=3,ui.sidebar_detail、ui.bell。

五个标签页

  • Overview:六块瓦片 + pgbot inspect 同款四条仪表,规则同源
  • PgBot:pgbot 原样报告——发现 / Queries / Indexes / Tables / Why 子页,←/→ 或 h/l 切换,不编辑、不改评级、不总结
  • SQL:只读事务里跑查询,按需 writes=true 才放开
  • Data:浏览 schema、表、行
  • Branches:若有 pgrun 项目

安全、演示与依赖

健康检查完全只读;SQL 标签页每条语句跑在 READ ONLY 事务里,由服务器拒绝写,而不是靠关键字检查;PROD 徽标 + writes=true 时写语句要求你先输入库名;statement_timeout=30s、行数有上限;Data 浏览器无论如何只读。连接串只经子进程环境变量传给 pgbot,绝不经 argv,不出现在 ps / 历史里。

演示:cargo build --release; ./demo/run.sh(三个假库,配置放 $TMPDIR/pgterm-demo,不动真实配置)。

依赖:pgbot 必需;pgrun 可选(只有 Branches 标签页);OpenSSH 可选(只有跳板机);终端最小 80×24,侧栏在 100 列出现。

按键:Tab/S-Tab 切换侧栏与主区,[/] 换库,1-5 选标签页,C-k 或 : 命令面板,/ 命令栏,a 加库,r 刷新,q 退出,? 帮助。

复制全文 生成海报 PostgreSQL pgbot pgterm 运维 可观测性 MCP

推荐文章

程序员茄子在线接单