@weotro/dx 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/git-release/SKILL.md +2 -2
- package/skills/online-debug-guard/SKILL.md +2 -1
- package/skills/online-debug-guard/references/br-ai-prod.md +98 -0
- package/skills/online-debug-guard/references/prometheus.md +82 -0
- package/skills/online-debug-guard/references/zh-ai-prod.md +106 -0
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ description: 仅在显式调用 git-release 时使用:准备或执行版本发
|
|
|
25
25
|
|
|
26
26
|
优先从 GitHub Release 确定上次发布,必要时结合 tags 与项目策略确认基线。首次发布按项目约定确定范围。读取该基线到目标提交的日志、diff 摘要和相关 PR;仅对影响理解有必要的文件展开内容。
|
|
27
27
|
|
|
28
|
-
每个新 Release 正文以 `# vX.Y.Z` 标题开头,紧接非空的 `FOR USER` 段落,再写 `## 主要变更`。`FOR USER`
|
|
28
|
+
每个新 Release 正文以 `# vX.Y.Z` 标题开头,紧接非空的 `FOR USER` 段落,再写 `## 主要变更`。`FOR USER` 是产品公告页「版本日志」的唯一内容真源,由发布人员事后手动同步;缺失或格式不合法会使同步直接报错。即使以内部改动为主,也必须根据本次发布包含的真实变化,从用户视角写至少一条,不虚构用户收益。
|
|
29
29
|
|
|
30
30
|
### FOR USER 格式与内容
|
|
31
31
|
|
|
@@ -38,7 +38,7 @@ description: 仅在显式调用 git-release 时使用:准备或执行版本发
|
|
|
38
38
|
- 每组至少一条以 `- ` 开头的列表项;每条只写一行纯文本,不嵌套、不加链接,建议不超过 200 字。
|
|
39
39
|
- 段落内只包含上述标题、摘要和分组列表,不出现额外标题、代码块、表格、图片或其他内容。
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
用简体中文写给普通用户,只描述本次发布包含且用户能感知的变化。本次打包内容均视为将随该版本上线的内容,直接据此生成发行说明,无需额外确认上线事实,也不以上线完成作为生成条件。不写 PR/Issue 编号、分支名、提交号、接口路径、错误码、配置键、表名、迁移名、环境名、内部服务名,以及 agent、审校、验证过程等发布流程信息;不写未纳入本次发布的计划或设想。
|
|
42
42
|
|
|
43
43
|
示例(没有内容的「修复」分组已省略):
|
|
44
44
|
|
|
@@ -8,6 +8,7 @@ description: 仅在显式调用 online-debug-guard 时使用:远程在线调
|
|
|
8
8
|
## 执行边界与优先级
|
|
9
9
|
|
|
10
10
|
在宿主系统与开发者指令约束内,冲突时依次采用:当前任务的具体要求与已有授权 > 目标项目适用的 AGENTS.md > 本技能及其引用的通用流程。
|
|
11
|
+
默认在当前执行模式下直接排查、修复并验证,不主动切换 Plan 模式或把计划审批作为开工条件;用户明确要求先规划时遵从。根据证据自主选择下一步,持续推进到问题解决,或遇到需要用户补充信息或授权的具体阻塞。
|
|
11
12
|
只读检索、本地草稿、可回滚编辑和常规测试可自主推断并继续;从相关文件和直接依赖开始,仅在证据不足或影响跨模块时扩大范围,复用仍有效的验证。
|
|
12
13
|
仅在不可逆或难以回滚的修改缺少具体授权时,先完成预览、草稿与验证,再说明对象和影响并等待确认;会话中已有授权继续有效。缺少事实时先查证、标注假设并推进独立工作,确实无法确定操作目标时才询问。对外发送消息须有明确授权。
|
|
13
14
|
|
|
@@ -15,7 +16,7 @@ description: 仅在显式调用 online-debug-guard 时使用:远程在线调
|
|
|
15
16
|
|
|
16
17
|
从当前任务、已有连接信息、项目配置和 SSH Host 推断目标环境,接受项目的环境别名(如 `prod1`、`test`)。先读相关配置核实映射;目标仍不唯一时继续本地定位,在连接不明确的远程主机前询问。未知环境不默认当作 development。
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
连接优先使用项目指定的 SSH Host。按目标读取已核实的部署位置、env 路径和只读连接示例:`zh-ai-prod` 使用 [zh-ai-prod 指南](references/zh-ai-prod.md),`br-ai-prod` 使用 [br-ai-prod 指南](references/br-ai-prod.md);其他主机按实际部署定位。
|
|
19
20
|
|
|
20
21
|
## 取证
|
|
21
22
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# br-ai-prod:环境文件与数据库连接
|
|
2
|
+
|
|
3
|
+
2026-10-06 通过 SSH 只读核实。使用前重新核对 PM2 状态和 `current` 指向,尤其不要仅凭主机名推断应用环境。
|
|
4
|
+
|
|
5
|
+
## 连接与应用定位
|
|
6
|
+
|
|
7
|
+
使用本机 SSH 别名,登录用户为 `ubuntu`;地址和密钥由 SSH 配置提供。
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ssh -o BatchMode=yes -o ConnectTimeout=10 br-ai-prod
|
|
11
|
+
pm2 list
|
|
12
|
+
pm2 describe backend-br
|
|
13
|
+
readlink -f /home/ubuntu/work/ai-monorepo/current
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| 项目 | PM2 进程 | 核实状态 | 部署根目录 | env 环境 |
|
|
17
|
+
| --- | --- | --- | --- | --- |
|
|
18
|
+
| ai-monorepo | backend-br | online | /home/ubuntu/work/ai-monorepo | production |
|
|
19
|
+
| kol | kol-api、kol-worker | online | /home/ubuntu/work/kol | production |
|
|
20
|
+
| paycenter | paycenter-backend | stopped | /home/ubuntu/work/paycenter | staging |
|
|
21
|
+
|
|
22
|
+
三个项目的 `current` 都指向各自 `releases/<版本目录>`;核实当天与 PM2 cwd 一致。`paycenter` 的停止状态不是本任务要求修复的问题,不要为了连接数据库而启动服务。
|
|
23
|
+
|
|
24
|
+
此主机的 `node` 和 `pm2` 来自 `/home/ubuntu/work/ai-monorepo/runtime/bin/`。若非交互 SSH 的 PATH 缺少它们,可在该会话执行:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
export PATH=/home/ubuntu/work/ai-monorepo/runtime/bin:$PATH
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
核实时 PATH 中没有 `psql`,可直接复用主应用发布包中的 `pg`,无需安装客户端。
|
|
31
|
+
|
|
32
|
+
## env 在哪里
|
|
33
|
+
|
|
34
|
+
真实配置位于部署根目录的 `shared` 中,`current` 内同名文件通过符号链接引用:
|
|
35
|
+
|
|
36
|
+
| 项目 | 基础文件 | 覆盖文件 |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| ai-monorepo | /home/ubuntu/work/ai-monorepo/shared/.env.production | /home/ubuntu/work/ai-monorepo/shared/.env.production.local |
|
|
39
|
+
| kol | /home/ubuntu/work/kol/shared/.env.production | /home/ubuntu/work/kol/shared/.env.production.local |
|
|
40
|
+
| paycenter | /home/ubuntu/work/paycenter/shared/.env.staging | /home/ubuntu/work/paycenter/shared/.env.staging.local |
|
|
41
|
+
|
|
42
|
+
忽略 `.before-*` 等备份文件。凭据只在服务器进程内读取,不输出整份 env 或 `pm2 jlist`,不把连接串放入命令参数或文档,不直接 `source` dotenv 文件。
|
|
43
|
+
|
|
44
|
+
- `ai-monorepo`、`paycenter`:使用 `dotenv` 解析两层文件,以 `.local` 覆盖基础文件,再用 `dotenv-expand` 展开变量。数据库使用 `DATABASE_URL`,Redis 使用 `REDIS_URL`。
|
|
45
|
+
- `kol`:复用 `/home/ubuntu/work/kol/current/env-file.cjs` 的 `loadEnv(directory, environment)`。它使用 Node `util.parseEnv` 合并两层配置并校验未填写的占位符,不做 dotenv 变量展开。数据库字段是 `DATABASE_DSN`,核实时为 PostgreSQL URL;不要误用 `DATABASE_URL`。该项目没有自己的 Node 依赖目录。
|
|
46
|
+
|
|
47
|
+
核实当天,主应用与 paycenter 的数据库、Redis 文件配置展开后与 PM2 保存的配置一致;kol 的 `DATABASE_DSN` 与两个运行进程的 PM2 配置一致。后续配置可能变化,需要时在服务器内比较,只输出比较结果。
|
|
48
|
+
|
|
49
|
+
## PostgreSQL 只读连接
|
|
50
|
+
|
|
51
|
+
主应用可直接在 **br-ai-prod 的 SSH 会话**中运行 [zh-ai-prod 指南的 PostgreSQL 示例](zh-ai-prod.md#postgresql-只读连接):客户端目录与 `project = 'ai-monorepo'` 相同,连接目标取自本机 env。核实当天返回 `ok: 1`、`read_only: 'on'`。
|
|
52
|
+
|
|
53
|
+
kol 使用它自己的配置加载器,同时借用主应用的 `pg` 客户端。以下在 br-ai-prod 服务器执行,仅检查连通性,不查询业务数据:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd /home/ubuntu/work/ai-monorepo/current
|
|
57
|
+
node <<'NODE'
|
|
58
|
+
const { Client } = require('pg');
|
|
59
|
+
const { loadEnv } = require('/home/ubuntu/work/kol/current/env-file.cjs');
|
|
60
|
+
let client;
|
|
61
|
+
(async () => {
|
|
62
|
+
const env = loadEnv('/home/ubuntu/work/kol/current', 'production');
|
|
63
|
+
if (!env.DATABASE_DSN) throw new Error('DATABASE_DSN_MISSING');
|
|
64
|
+
client = new Client({
|
|
65
|
+
connectionString: env.DATABASE_DSN,
|
|
66
|
+
connectionTimeoutMillis: 5000,
|
|
67
|
+
statement_timeout: 5000,
|
|
68
|
+
options: '-c default_transaction_read_only=on',
|
|
69
|
+
});
|
|
70
|
+
await client.connect();
|
|
71
|
+
await client.query('BEGIN READ ONLY');
|
|
72
|
+
const result = await client.query(
|
|
73
|
+
"SELECT 1 AS ok, current_setting('transaction_read_only') AS read_only",
|
|
74
|
+
);
|
|
75
|
+
console.log(result.rows);
|
|
76
|
+
await client.query('ROLLBACK');
|
|
77
|
+
})().catch(error => {
|
|
78
|
+
console.error('数据库检查失败:', error.code || error.name);
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
}).finally(async () => {
|
|
81
|
+
if (client) await client.end();
|
|
82
|
+
});
|
|
83
|
+
NODE
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
kol 示例已在核实当天实际运行,返回 `ok: 1`、`read_only: 'on'`。
|
|
87
|
+
|
|
88
|
+
paycenter 本次只核实配置路径,未连接数据库。任务确实涉及它时,使用主应用示例的客户端依赖,将项目改为 `paycenter`,并将读取的文件名改为 `.env.staging`、`.env.staging.local`;不能套用 production 文件名。
|
|
89
|
+
|
|
90
|
+
## Redis
|
|
91
|
+
|
|
92
|
+
主应用和 paycenter 配置了 `REDIS_URL`,可复用主应用的 `ioredis`,连接参数从对应项目的 env 解析取得。设置有限超时、禁用自动重连,检查时只发 `PING`,结束后断开。本次未测试 Redis 连通性;kol 配置中未发现 Redis 字段。
|
|
93
|
+
|
|
94
|
+
后续业务取证保持查询范围有限,SQL 使用参数化查询;数据库写入、Redis 删除或服务重启仍遵循技能中的授权边界。
|
|
95
|
+
|
|
96
|
+
## Prometheus
|
|
97
|
+
|
|
98
|
+
该服务器已安装 Prometheus,并由 PM2 进程 `prometheus` 管理。调试指标入口、配置、数据目录和查询方法见 [Prometheus 调试参考](prometheus.md)。
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Prometheus 调试参考
|
|
2
|
+
|
|
3
|
+
`zh-ai-prod` 与 `br-ai-prod` 的 Prometheus 配置在 2026-10-11 通过 SSH 只读核实。使用前仍需检查进程状态和目标健康度。
|
|
4
|
+
|
|
5
|
+
## 运行位置
|
|
6
|
+
|
|
7
|
+
- PM2 进程:`prometheus`,脚本 `/usr/local/bin/prometheus`
|
|
8
|
+
- 配置:`/etc/prometheus/prometheus.yml`(root 持有,权限 `644`)
|
|
9
|
+
- TSDB:`/var/lib/prometheus`
|
|
10
|
+
- Web/API:`127.0.0.1:9090`,只绑定本机
|
|
11
|
+
- 数据保留:`45d`
|
|
12
|
+
- PM2 日志:`/home/ubuntu/.pm2/logs/prometheus-out.log`、`prometheus-error.log`
|
|
13
|
+
|
|
14
|
+
两台服务器均使用以下启动参数:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
--config.file=/etc/prometheus/prometheus.yml
|
|
18
|
+
--storage.tsdb.path=/var/lib/prometheus
|
|
19
|
+
--storage.tsdb.retention.time=45d
|
|
20
|
+
--web.listen-address=127.0.0.1:9090
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
不要把 9090 直接暴露到公网。远程查询时优先 SSH 到目标机,或使用经过授权的 SSH 隧道;不要为了调试修改监听地址或防火墙。
|
|
24
|
+
|
|
25
|
+
## 已配置的采集目标
|
|
26
|
+
|
|
27
|
+
配置中的抓取间隔和目标如下:
|
|
28
|
+
|
|
29
|
+
| job | 地址 | 内容 |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `ai-backend` | `127.0.0.1:9465/metrics` | 应用指标 |
|
|
32
|
+
| `host-node` | `127.0.0.1:9100/metrics` | Node Exporter 主机指标 |
|
|
33
|
+
| `host-processes` | `127.0.0.1:9256/metrics` | Process Exporter 进程指标 |
|
|
34
|
+
|
|
35
|
+
Node Exporter 和 Process Exporter 也由系统进程运行,监听本机地址。Prometheus 与三个目标的核实状态均为 `up`;目标可能随部署变化,先查询 API,不要只依赖这份文档。
|
|
36
|
+
|
|
37
|
+
## 先做健康检查
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pm2 describe prometheus
|
|
41
|
+
pm2 logs prometheus --lines 200 --nostream
|
|
42
|
+
curl -fsS --max-time 3 http://127.0.0.1:9090/-/ready
|
|
43
|
+
curl -fsS --max-time 3 http://127.0.0.1:9090/api/v1/targets
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`/api/v1/targets` 返回 JSON,重点看 `activeTargets[].labels.job`、`health`、`lastError`、`lastScrape` 和 `scrapeUrl`。输出诊断时保留 job、状态和错误摘要,不要把无关完整 JSON 或环境变量带出。
|
|
47
|
+
|
|
48
|
+
查看当前启动参数和存储权限:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
p=$(pgrep -xo prometheus)
|
|
52
|
+
tr '\0' ' ' < /proc/$p/cmdline; echo
|
|
53
|
+
stat -c '%U %G %a %n' /etc/prometheus/prometheus.yml /var/lib/prometheus
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 查询指标
|
|
57
|
+
|
|
58
|
+
Prometheus API 只读查询使用 `query` 参数。先用短时间范围和明确指标名,避免高基数的全量查询:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
curl --get -fsS --max-time 5 http://127.0.0.1:9090/api/v1/query \
|
|
62
|
+
--data-urlencode 'query=up'
|
|
63
|
+
|
|
64
|
+
curl --get -fsS --max-time 5 http://127.0.0.1:9090/api/v1/query \
|
|
65
|
+
--data-urlencode 'query=process_resident_memory_bytes{job="host-processes"}'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
后端应用是否暴露指标,先直接检查:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
curl -fsS --max-time 3 http://127.0.0.1:9465/metrics | head -80
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
再按指标名查询。不要把用户提供的内容直接拼入 PromQL;标签值使用 URL 编码,复杂表达式先在本地构造后审核。
|
|
75
|
+
|
|
76
|
+
Prometheus 适合确认服务是否存活、请求量、延迟、错误率、CPU、内存、进程重启和抓取失败。它不是应用日志库;需要堆栈、请求参数或业务错误时,回到对应 PM2 日志和应用日志。
|
|
77
|
+
|
|
78
|
+
## 时间范围与数据限制
|
|
79
|
+
|
|
80
|
+
默认 API 查询为即时值。需要趋势时使用 `/api/v1/query_range`,明确 `start`、`end`、`step`,时间窗先控制在问题发生前后,避免一次拉取 45 天数据。TSDB 查询和统计只读,不修改 Prometheus 数据。
|
|
81
|
+
|
|
82
|
+
若指标缺失,按顺序检查:应用 `/metrics`、目标 `health` 和 `lastError`、Prometheus 日志、PM2 进程状态、应用部署版本。不要直接删除 `/var/lib/prometheus`;TSDB 删除会丢失历史证据,属于不可逆操作。
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# zh-ai-prod:环境文件与数据库连接
|
|
2
|
+
|
|
3
|
+
2026-10-06 通过 SSH 只读核实。以下是该主机的部署约定,使用前核对 PM2 当前进程和 `current` 指向;不要套用到其他服务器。
|
|
4
|
+
|
|
5
|
+
## 连接与应用定位
|
|
6
|
+
|
|
7
|
+
使用本机 SSH 配置中的别名,登录用户为 `ubuntu`。主机地址和密钥由 SSH 配置提供,不复制到技能或命令中。
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ssh -o BatchMode=yes -o ConnectTimeout=10 zh-ai-prod
|
|
11
|
+
pm2 list
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
同一台服务器运行多个应用,先按任务选择项目:
|
|
15
|
+
|
|
16
|
+
| 项目 | PM2 进程 | 部署根目录 |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| ai-monorepo | backend | /home/ubuntu/work/ai-monorepo |
|
|
19
|
+
| noveai | noveai-backend | /home/ubuntu/work/noveai |
|
|
20
|
+
| paycenter | paycenter-backend | /home/ubuntu/work/paycenter |
|
|
21
|
+
|
|
22
|
+
在服务器执行以下命令核对运行位置(按项目替换参数):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pm2 describe backend
|
|
26
|
+
readlink -f /home/ubuntu/work/ai-monorepo/current
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`current` 指向 `releases/<版本目录>`。PM2 的 cwd 可能直接指向某个 release,也可能指向 `current`;两者不一致时,以实际运行进程为准继续调查。`/opt/ai-monorepo`、`/opt/noveai` 下也有源码和 env,但不能据此认定线上正在使用它们。
|
|
30
|
+
|
|
31
|
+
## env 在哪里
|
|
32
|
+
|
|
33
|
+
每个部署根目录下都有:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
shared/.env.production
|
|
37
|
+
shared/.env.production.local
|
|
38
|
+
current/.env.production -> shared/.env.production
|
|
39
|
+
current/.env.production.local -> shared/.env.production.local
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
例如主应用的真实文件是 `/home/ubuntu/work/ai-monorepo/shared/.env.production` 和 `/home/ubuntu/work/ai-monorepo/shared/.env.production.local`。另外两个项目替换目录名即可。发布目录中的 env 是符号链接;`bak` 中的文件不是当前配置来源。
|
|
43
|
+
|
|
44
|
+
用 `dotenv` 分别解析两层文件,以 `.env.production.local` 覆盖基础文件,再用 `dotenv-expand` 展开 `${...}` 引用。只在服务器进程内读取凭据,不 `cat` 整份 env,不复制到本地,也不把连接串放入命令参数、日志或报告。不要直接 `source` dotenv 文件执行其中内容。
|
|
45
|
+
|
|
46
|
+
文件配置不等于运行配置。必要时在服务器内解析 `pm2 jlist`,只输出所需字段或比较结果,避免直接输出包含凭据的完整 JSON。核实当天三组文件的数据库、Redis 连接配置与 PM2 配置展开后一致;`noveai-backend` 的 PM2 原值含占位符,直接比较未展开字符串会误判。
|
|
47
|
+
|
|
48
|
+
## PostgreSQL 只读连接
|
|
49
|
+
|
|
50
|
+
三个项目都配置了 `DATABASE_URL`。服务器已安装 `psql`;主应用发布包也有 `pg`、`dotenv` 和 `dotenv-expand`。优先在服务器连接,让凭据留在服务器内,无需额外开放数据库端口或建立隧道。
|
|
51
|
+
|
|
52
|
+
下面在服务器执行。主应用目录提供客户端依赖,`project` 决定读取哪个项目的 env,可选表中的三个项目名。示例只返回连通性与只读状态,不查询业务数据。
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd /home/ubuntu/work/ai-monorepo/current
|
|
56
|
+
node <<'NODE'
|
|
57
|
+
const fs = require('node:fs');
|
|
58
|
+
const dotenv = require('dotenv');
|
|
59
|
+
const { expand } = require('dotenv-expand');
|
|
60
|
+
const { Client } = require('pg');
|
|
61
|
+
|
|
62
|
+
const project = 'ai-monorepo';
|
|
63
|
+
let client;
|
|
64
|
+
(async () => {
|
|
65
|
+
const base = `/home/ubuntu/work/${project}/shared/`;
|
|
66
|
+
const parsed = {
|
|
67
|
+
...dotenv.parse(fs.readFileSync(base + '.env.production')),
|
|
68
|
+
...dotenv.parse(fs.readFileSync(base + '.env.production.local')),
|
|
69
|
+
};
|
|
70
|
+
const env = expand({ parsed, processEnv: {} }).parsed;
|
|
71
|
+
if (!env.DATABASE_URL) throw new Error('DATABASE_URL_MISSING');
|
|
72
|
+
client = new Client({
|
|
73
|
+
connectionString: env.DATABASE_URL,
|
|
74
|
+
connectionTimeoutMillis: 5000,
|
|
75
|
+
statement_timeout: 5000,
|
|
76
|
+
options: '-c default_transaction_read_only=on',
|
|
77
|
+
});
|
|
78
|
+
await client.connect();
|
|
79
|
+
await client.query('BEGIN READ ONLY');
|
|
80
|
+
const result = await client.query(
|
|
81
|
+
"SELECT 1 AS ok, current_setting('transaction_read_only') AS read_only",
|
|
82
|
+
);
|
|
83
|
+
console.log(result.rows);
|
|
84
|
+
await client.query('ROLLBACK');
|
|
85
|
+
})().catch(error => {
|
|
86
|
+
console.error('数据库检查失败:', error.code || error.name);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
}).finally(async () => {
|
|
89
|
+
if (client) await client.end();
|
|
90
|
+
});
|
|
91
|
+
NODE
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
核实当天三个项目均返回 `ok: 1`、`read_only: 'on'`。后续取证可在只读事务中替换为范围明确、带 LIMIT 的查询;不要把用户原始输入拼接成 SQL。连接失败时先检查配置展开、当前版本和网络,错误输出保持脱敏。
|
|
95
|
+
|
|
96
|
+
如果改用 `psql`,通过子进程环境传递连接参数和密码,并使用 `-X -w`、只读会话及语句超时。Prisma 连接串可能包含 `schema` 等参数,不能未经处理直接作为 libpq 连接串使用。
|
|
97
|
+
|
|
98
|
+
## Redis
|
|
99
|
+
|
|
100
|
+
三个项目也配置了 `REDIS_URL`,发布包包含 `ioredis`。按同样方式解析并展开 env 后,用 `ioredis` 在服务器内连接;设置有限连接超时、禁用自动重连,结束后断开。连通性检查只需 `PING`,按需用限定范围的 `SCAN` 取证,避免 `KEYS *` 和 `MONITOR`。本次核实了配置来源,未执行 Redis 连通性检查。
|
|
101
|
+
|
|
102
|
+
Redis 不提供与 PostgreSQL 只读事务等价的保护;删除键、写入和清库仍按技能的授权边界处理。
|
|
103
|
+
|
|
104
|
+
## Prometheus
|
|
105
|
+
|
|
106
|
+
该服务器已安装 Prometheus,并由 PM2 进程 `prometheus` 管理。调试指标入口、配置、数据目录和查询方法见 [Prometheus 调试参考](prometheus.md)。
|