返回博客

2026年10月30日

Pi 节点在线但数据为空?按这三层查,十分钟定位

容器 running 不等于服务 healthy,更不等于数据可用。这篇给三层排查法,覆盖社区最高频的「在线但没数据」问题。

面向:客户端显示节点"在线"、或者容器在跑,但界面上一个数据都没有的人。
这是社区里最高频的问题之一。好消息是:绝大多数情况你自己能查出来。

先说清一件事:"在线"有三种含义

很多人说"我的节点在线",但可能是三种完全不同的状态:

| 你说的"在线" | 实际含义 | |---|---| | 客户端界面显示 running | 容器起来了 —— 只说明进程在,不代表同步好了 | | 界面上有绿色状态点 | 客户端认为服务健康 —— 但数据可能还没拉 | | 区块高度在涨 | 真的在同步 —— 这才是有效的"在线" |

关键区分:容器 running ≠ 服务 healthy ≠ 数据可用。

Pi 客户端本身有一套状态判断逻辑,它从「磁盘文件存不存在 + docker ps 状态」推导: 没有安装目录就是 deleted、没有容器就是 stopped、容器退出码非 0 就是 crashed、 健康检查不过就是 unhealthy。所以界面上显示的东西,是客户端推断出来的, 不一定等于你以为的"节点工作正常"。

数据为空,通常就卡在「容器 running 但服务没 healthy」这一段。

第一层:容器真的在跑吗(30 秒)

docker ps -a --filter name=testnet2 --format '{{.Names}}\t{{.Status}}'

看 Status:

| 显示 | 含义 | 下一步 | |---|---|---| | Up 2 hours (healthy) | 健康 | 直接看第二层 | | Up 2 hours 但没有 healthy | 起来了但健康检查没过 | 看第三层(日志) | | Up 2 hours (unhealthy) | 明确不健康 | 看第三层(日志) | | Restarting | 反复重启 | 看第三层 | | Exited | 挂了 | 看第三层 |

最常见的"数据为空"就是这个:`Up` 但没有 `(healthy)`。 容器在跑,但内部的 stellar-core 或 postgres 没起来,所以查不到数据。

第二层:服务接口通不通(1 分钟)

如果容器是 healthy 的,直接问服务本身:

# Horizon API —— 查区块数据用的接口
docker exec testnet2 curl -s localhost:8000/ | head -c 200

# stellar-core 状态
docker exec testnet2 curl -s localhost:11626/info | grep -o '"state":"[^"]*"'

判断:

  • Horizon 有返回(哪怕是 JSON 或错误信息)→ 服务活着,数据为空可能是还没同步完
  • Horizon 无返回 / 连接拒绝 → 服务没起来,去第三层看日志
  • `state` 显示 `Catching up` → 在同步中,等就行(但要看是不是卡住不动)

注意 11626 在容器内,宿主机通常没映射。从宿主机直接 curl localhost:11626 一定连不上, 这不代表服务挂了。

第三层:看日志找具体原因(5 分钟)

# stellar-core 日志
docker exec testnet2 tail -80 /tmp/stellar-core.log

# supervisor 管理的各服务日志
docker exec testnet2 ls /var/log/supervisor/
docker exec testnet2 tail -40 /var/log/supervisor/*.log

按日志关键词对照:

| 日志里出现 | 说明 | 方向 | |---|---|---| | Connection refused 大量重复,指向 5432 | postgres 没起来 | 数据为空的最常见原因 | | database system is starting up | 数据库正在启动 | 等 1-2 分钟 | | FATAL: password authentication failed | 数据库密码不对(配置损坏) | 配置问题 | | No space left on device | 磁盘满了 | 清磁盘 | | unsupported ledger version | 版本太旧,网络已升级 | 升级镜像 | | Catching up + 每秒刷 Skipping | 追块源头下不动 | 归档源问题,不是"数据为空" |

占比最高的原因是数据库没起来。 因为 Pi 节点的 stellar-core 把数据存在 PostgreSQL 里, 数据库没跑,stellar-core 起来了也读不到任何东西 —— 界面上就是"在线但空"。

一个高频误区

"数据为空 → 重装就好"

不对,而且常常更糟。

重装如果清掉了 docker_volumes 目录,节点身份和已同步的数据全没, 要从零同步几小时到几天。而真正的问题可能只是 postgres 容器没起来, 重启一下就好。

正确顺序:看容器状态 → 看服务接口 → 看日志 → 最后才考虑重建容器。

还有一种情况:服务都正常,但就是没数据

如果三层都过了 —— 容器 healthy、Horizon 有返回、日志没报错 —— 但界面上数据还是空,那大概率是:

  1. 还在同步中:区块高度在涨但还没追上,等
  2. 客户端显示问题:重启客户端(不是容器)试试
  3. 端口可达性问题:节点在跑,但入站不可达,导致拿不到完整数据

第 3 种最隐蔽:Pi 客户端会通过一个 /healthz 端点反打本机来验证"入站可达", 如果这个回验证不通(返回 502/503/504),客户端就判定不可达 —— 即使你的容器跑得好好的。

这时要查的是端口映射,不是容器。31400-31409 这一整段都要从公网可达。

排查清单(照着走)

1. docker ps -a 看 Status
   ├─ 有 (healthy)  → 第 2 步
   └─ 无 healthy / Restarting / Exited → 第 3 步

2. docker exec 查 Horizon(8000) 和 core(11626)
   ├─ 有返回 → 在同步中,等;或查端口可达性
   └─ 无返回 → 第 3 步

3. 看日志关键词
   ├─ Connection refused → postgres 没起来(最常见)
   ├─ No space left      → 磁盘满
   └─ unsupported ledger → 版本旧,升级镜像

4. 以上都不是 → 查 31400-31409 是否从公网全通

十分钟能走完。别一上来就重装,那是把可修的问题变成要几小时的恢复。

---