一、问题是怎么找上门的

一台正常运行的Polygon节点突然罢工了。同步进程退出,日志里报出一堆错。排查的时候先怀疑网络,又怀疑内存,最后发现根因是磁盘满了。磁盘满了以后,程序想写数据写不进去,就只能不断报错然后退出。很多跑区块链节点的朋友都遇到过这个坑,而且越早发现越好,拖久了可能需要重新同步,更麻烦。

1.1 同步进程为什么怕磁盘满

区块链节点说白了就是一个不停读写本地磁盘的程序。Polygon节点需要把新区块的交易记录、状态快照、共识消息都存下来,时间越久数据量越大。当磁盘空间被占满时,哪怕只是写一个小文件都会失败,而同步进程几乎每秒钟都在做写操作,一旦某个关键写操作失败,整个进程就会异常退出。这种情况不会自己恢复,因为磁盘还是满的。

1.2 怎么发现是磁盘问题

最直接的线索是日志。如果同步进程的日志里出现 no space left on device 这样的报错,基本就能锁定是磁盘。然后用一条命令确认一下使用率。

# 查看所有挂载点的磁盘占用情况
# 下面的输出里,根分区使用率已经到99%,说明磁盘快满了
df -h

再配合一段输出示例来理解:

# 示例输出
文件系统        容量  已用  可用  已用% 挂载点
/dev/vda1       100G   99G  1G   99%   /

然后去Polygon的日志目录找具体报错。假设数据目录在 /var/lib/polygon,日志在 ~/polygon/logs 下:

# 查看日志最后50行,重点找写失败/磁盘满相关错误
tail -n 50 ~/polygon/logs/bor.log

如果日志中出现包含磁盘满的错误描述,那就不用犹豫,直接进入下一步处理。

二、动手前的准备:先摸清家底

别急着删东西,先弄清楚什么文件占地方,哪些能安全处理。

2.1 查看当前磁盘占用

用磁盘占用统计命令,一层一层往下看。

# 查看Polygon数据目录下每个子目录的大小,并按从大到小排序
# -s 表示汇总,-h 显示易读大小,-x 不跨文件系统
sudo du -h -s /var/lib/polygon/* | sort -hr | head -20

这个命令能快速找出最占空间的子目录,比如 blockdata、state 或者 logs。

2.2 找到Polygon的数据目录

Polygon节点有两个主要进程:Heimdall 和 Bor。它们的数据目录可能单独配置。可以通过服务配置里的启动参数找到。

# 查看Bor服务的启动配置
systemctl cat polygon-bor.service

# 查看Heimdall服务的启动配置
systemctl cat polygon-heimdall.service

在配置文件的启动命令那一行,一般会带数据目录参数。如果服务不是用systemd托管,也可以从进程参数里找:

# 列出和polygon相关的进程,观察命令行参数
ps aux | grep -E "polygon|bor|heimdall" | grep -v grep

知道数据目录在哪以后,再确认它落在哪个磁盘分区。如果数据目录和系统都在根分区,那根分区膨胀就会影响节点。

三、对症下药:优先做安全清理

清理的核心是“先保命,再根治”。先把磁盘腾出一点空间让节点能重新启动,然后再考虑长期方案。

3.1 明确哪些数据可以动

可以动的是日志、临时文件、旧安装包、回收站内容。不可以动的是当前的区块数据、节点密钥、数据库文件。如果你用的是快照同步,那么已经解压完的快照压缩包也可以删除,腾出的空间通常很可观。

3.2 清理日志文件

日志是最大的“隐形磁盘杀手”。特别是运行半年以上的节点,日志可能比区块数据还大,而且经常被忽略。

# 查看日志目录占用
ls -lah ~/polygon/logs/

# 清空当前日志文件,但文件保留,进程不受影响
truncate -s 0 ~/polygon/logs/bor.log
truncate -s 0 ~/polygon/logs/heimdall.log

系统日志也要处理。journald 日志有时候能占到几十GB,这里顺便清理一下:

# 查看systemd日志占用的磁盘空间
journalctl --disk-usage

# 只保留3天内的日志,其余清掉
sudo journalctl --vacuum-time=3d

同时配置日志轮转,防止以后日志再次占满磁盘。用 logrotate 这类轮转工具来做很合适。

# 创建logrotate配置,每周轮转一次,保留4份压缩日志
sudo tee /etc/logrotate.d/polygon > /dev/null <<'EOF'
/var/log/polygon/*.log {
    weekly
    rotate 4
    compress
    delaycompress
    notifempty
    missingok
}
EOF

注意:上面配置里的路径需要根据你的实际日志路径调整。如果日志不在 /var/log/polygon,就把路径改成对应的,比如你的用户目录下。

3.3 清理临时文件和残留文件

系统里有一些文件被删除了,但还被运行中的进程占用,这些文件不会出现在目录里,却占用磁盘空间。可以用下面的命令查出来。

# 查找已删除但被进程占用的文件
# 如果找到很多,重启对应进程一般就能释放空间
sudo lsof | grep deleted

如果那些文件是Polygon节点创建的,重启Polygon服务一般就能释放。

3.4 用Polygon自带工具做状态裁剪

如果清理完日志和临时文件,空间还是不够,就要考虑减少区块链数据的存量。Polygon的Bor节点支持两种数据模式:归档模式(archive)和完整模式(full)。归档模式会保存所有历史状态,数据量增长特别快;完整模式只保存当前状态和历史区块头,体积小很多。如果你不需要查询很老的历史数据,可以从归档模式切到完整模式。

切换的方式是修改服务启动参数。以systemd托管的Bor服务为例:

# 编辑Bor服务的覆盖配置
sudo systemctl edit polygon-bor.service

在编辑窗口里输入以下内容:

[Service]
# 第一行ExecStart=必须写,表示清空原来的启动命令
ExecStart=
# 第二行写完整的启动命令,注意加上 --gcmode=full
ExecStart=/usr/local/bin/bor --datadir /var/lib/polygon --gcmode=full

保存退出后,重载并重启服务:

sudo systemctl daemon-reload
sudo systemctl restart polygon-bor

切换模式后,节点会清理不再需要的状态数据,这个过程可能持续很久,而且需要一定磁盘空间来跑整理任务。建议在磁盘还有20%以上空闲时操作,否则可能中途失败。另外,如果你需要保留历史状态查询能力,这个方案就不适合,最好直接扩容。

四、如果清理完还不够:扩容磁盘

清理只能解燃眉之急,区块数据还在不断增长。如果业务要求必须长期保留数据,或者切换模式会让你损失重要功能,那就得扩容。

4.1 评估扩容方式

扩容一般分两种:给现有磁盘加大容量,或者挂一块新磁盘。云服务器通常支持直接扩容云盘,物理机可能需要加硬盘。无论哪种,核心步骤都是:底层磁盘变大 -> 分区变大 -> 文件系统变大。

4.2 实际扩容步骤示例(以Linux为例)

假设原来云盘是100G,现在在云控制台扩容到了200G。系统里需要执行以下命令让操作系统感知到新容量。

# 查看当前块设备信息,确认磁盘和分区大小
lsblk
# NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# vda    253:0    0 200G  0 disk
# └─vda1 253:1    0 100G  0 part /

可以看到磁盘已经是200G,但分区还停在100G。先扩展分区。注意这里用的是 growpart 工具,它专门用来扩展分区边界。

# 扩展分区:第一个参数是磁盘名,第二个参数是分区号
sudo growpart /dev/vda 1

然后扩展文件系统。根据文件系统类型选择不同的命令,千万别用错。

# 如果是ext4系列文件系统:
sudo resize2fs /dev/vda1

# 如果是xfs文件系统:
# sudo xfs_growfs /

执行完以后,再用 df 检查一次,可用空间应该已经增加了。

4.3 把数据迁移到新磁盘

如果挂了一块全新的磁盘,比如 /dev/sdb,需要先格式化,然后挂载,再把Polygon数据复制过去。

# 格式化新磁盘为ext4文件系统(谨慎操作,确认盘符无误)
sudo mkfs.ext4 /dev/sdb

# 创建挂载点,并把新盘挂载上去
sudo mkdir -p /mnt/polygon-data
sudo mount /dev/sdb /mnt/polygon-data

在复制数据之前,先停止Polygon服务,避免复制过程中数据变化:

# 停止节点服务
sudo systemctl stop polygon-bor
sudo systemctl stop polygon-heimdall

使用 rsync 把旧数据完整复制到新盘。rsync 是 Linux 下非常常用的数据同步工具,支持断点续传和增量同步,特别适合目录迁移。

# rsync 归档模式同步,保留权限和时间戳
# -a 归档模式,-v 显示进度,--delete 删除目标端多余文件
sudo rsync -av --delete /var/lib/polygon/ /mnt/polygon-data/polygon/

复制完成后,把旧目录改名备份,再做一个软链接指向新位置。这样不用修改服务配置文件,节点启动时会自动走新路径。

# 把旧目录改名,避免和新位置冲突
sudo mv /var/lib/polygon /var/lib/polygon.bak

# 创建软链接,让 /var/lib/polygon 指向新盘上的目录
sudo ln -s /mnt/polygon-data/polygon /var/lib/polygon

最后,为了重启后自动挂载新盘,需要把挂载配置写入系统文件。

# 查看新磁盘的UUID
sudo blkid /dev/sdb

# 将挂载信息追加到 /etc/fstab
echo 'UUID=你的UUID /mnt/polygon-data ext4 defaults 0 2' | sudo tee -a /etc/fstab

写入后可以测试一下配置是否正确:

# 根据fstab重新挂载所有分区,如果没报错就代表配置成功
sudo mount -a

4.4 扩容后的验证

扩容完成后,不要急着放松。先启动服务,观察日志,确认同步进度是不是在增长。

# 启动Bor服务
sudo systemctl start polygon-bor

# 实时查看日志,观察是否有新的区块同步记录
tail -f ~/polygon/logs/bor.log

如果日志里持续出现新的区块高度,说明同步已经恢复正常。如果是复制数据到新盘的情况,建议保留旧目录一两天,确认新位置运行稳定后再删除备份。

# 确认服务正常后,删除旧备份目录(谨慎操作)
sudo rm -rf /var/lib/polygon.bak

五、长期预防:别再让磁盘悄悄爆满

问题解决后,要建立“护城河”,让类似问题不再发生。

5.1 建立监控告警

人工看磁盘不现实,写个定时脚本每天检查一次最省心。

# 创建脚本文件 /usr/local/bin/check-disk.sh
#!/bin/bash
# 设置告警阈值,这里设为90%
THRESHOLD=90
# 获取根分区当前使用率的数字部分
USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
# 如果使用率超过阈值,发送告警(示例里只是打印到控制台)
if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "磁盘使用率已达 ${USAGE}%,请及时清理或扩容" | mail -s "磁盘告警" admin@example.com
fi

还需要给脚本执行权限,并加入定时任务。

# 赋予脚本执行权限
chmod +x /usr/local/bin/check-disk.sh

# 编辑当前用户的crontab
crontab -e

在打开的编辑器里添加一行:

# 每天早上8点执行一次检查
0 8 * * * /usr/local/bin/check-disk.sh

这样即使不再手动看磁盘,系统也会在磁盘快要满的时候提醒你。

5.2 设置日志轮转

前面已经演示过logrotate。这里补充一点:如果节点进程使用的日志文件路径比较特殊,可以把logrotate配置里的路径改成实际路径。同时,最好把systemd日志也限制一下大小。

# 限制systemd日志最多占用500M
sudo journalctl --vacuum-size=500M

logrotate 的原理很简单:按周期或大小触发一次日志“搬家”,把旧日志压缩保留,再让程序写新日志,从而避免单个日志文件无限变大。配置一次,长期有效。

5.3 定期巡检与自动化清理

可以每个月手动检查一次大文件,或者用清理脚本删除过期临时文件。

# 找出 /tmp 下超过7天的文件并删除(谨慎使用)
find /tmp -type f -mtime +7 -delete

# 正式删除前建议先列出,看看会删什么
find /tmp -type f -mtime +7

对于Polygon数据目录,建议不要随便删文件。如果要瘦身,优先考虑升级磁盘或调整数据模式,而不是手动删数据文件,那样容易损坏节点状态。

六、应用场景、优缺点与注意事项

6.1 应用场景

这套方案适合下面这些情况:同步进程突然中断,日志提示磁盘写满;节点运行时间很久,数据目录越来越大,眼看着可用空间见底;日志文件占用了好几个GB;你用的是archive模式的节点,想改成full模式降低存储压力;或者你一启动节点就报错,因为磁盘没有剩余空间。在这些场景下,先清理后扩容的思路能帮你快速恢复。

6.2 清理与扩容的优缺点对比

清理的优点是快、成本低、不需要额外硬件,紧急情况下能迅速腾出空间恢复同步。缺点是只治标不治本,如果数据量增长快,过一阵可能又满了。裁剪数据模式还会丢失历史状态查询能力,业务上要能接受。另外,过度清理日志可能会丢失排查问题需要的线索,所以日志最好还是轮转而不是全部删除。

扩容的优点是从根本上解决问题,磁盘容量变大,以后数据多也不怕。缺点是需要停机操作,可能涉及数据迁移和硬件成本,云盘扩容还可能产生费用。迁移过程中如果操作失误,可能导致节点起不来。所以扩容前一定要做好备份和回滚方案。

6.3 注意事项

动手之前一定先备份密钥和配置文件,不然节点可能无法启动。清理文件时不要动正在使用的数据库文件,否则可能损坏数据。扩展分区前要确认文件系统类型,用错命令会出问题。迁移数据完成后,先保留旧目录一段时间,确认新位置运行正常再删除备份。如果磁盘已经满了,连日志都写不进去,需要先删掉一些大文件腾出空间,再执行其他命令。修改节点启动参数后,要关注日志确认同步是否恢复,不要改完就撒手不管。

七、文章总结

磁盘空间不足让同步意外中断,是区块链运维里很经典的问题。处理思路其实不复杂:先看日志定位,再清掉日志和临时文件,如果还不够就裁剪数据或者扩容磁盘。清理要懂取舍,扩容要按步骤来,最后还要用监控和日志轮转来做预防。希望这篇文章能帮你少走弯路,让节点稳定地跑下去。