HanyanOS 运维手记

1. 引言

“日志不会骗人,但日志太多的时候,你根本不想看。”

备份管线做好后(#3),下一个自然该管的是——日志。数据有备份,但诊断数据本身呢?

一台 24/7 运行的 N100,跑着 Docker、pm2、systemd 全家桶,日志文件会悄悄膨胀到你想不到的程度。今天这篇就是我在 aicore 上做日志治理的真实记录。

先看现状:

1
2
3
4
5
$ journalctl --disk-usage
Archived and active journals take up 3.9G in the file system.

$ journalctl -p err --since "3 days ago" | wc -l
~4000 行

3.9GB。 对于一台 N100 来说,这不是一个小数字。而且——默认的 journald.conf 什么都没配。


2. 日志全景图

先画一下这台机器上的日志源:

日志源 位置 规模 关键程度
systemd journal journalctl 3.9GB ⭐⭐⭐
pm2 logs ~/.pm2/logs/ ~few MB ⭐⭐
Docker 容器日志 journald 驱动 包含在 3.9G 内 ⭐⭐⭐
Nginx (如有) /var/log/nginx/ N/A
kernel/dmesg journald 包含在上 ⭐⭐⭐

最大的问题是:所有日志都涌进 journald,而它没有上限配置。


3. 噪音分析 — 谁在刷屏

3.1 蓝牙重连狂魔

占 err 级别日志 80% 以上

1
2
Jun 21 17:46:24 aicore bluetoothd[780]: profiles/audio/avdtp.c:avdtp_connect_cb()
connect to 0C:FC:30:00:06:2A: Host is down (112)

这是 ZEALOT-S32 蓝牙音箱的连接尝试。音箱没有开机,但 systemd 在不断地尝试重连——每 30 秒一次,一天 2880 条。

3.2 PCIe AER 错误(零星但存在)

1
2
Jun 21 17:37:55 aicore kernel: pcieport 0000:00:1c.0: AER:
Error of this Agent is reported first

N100 平台上的常见现象,频率不高(一周几次)。单个事件信息量不大,但长期积累会暗示某个 PCIe 链路的不稳定。

3.3 pm2 日志(正常流量)

ai-portal 的 pm2 日志里全是正常的 HTTP 200/304——说明服务健康,但日志本身对故障诊断帮助不大。

1
2
0|ai-porta | GET /assets/index-CNdUHBv6.js 200 0.754 ms - 2425817
0|ai-porta | GET /api/status/public 200 56.428 ms - 144

4. journald 治理实战

4.1 加个容量上限

journald.conf 默认策略是 不限制。这意味着 journal 会一直长下去,直到你把磁盘占满。配置一个合理上限:

1
2
3
4
5
# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
SystemMaxFileSize=100M
MaxRetentionSec=30day
  • SystemMaxUse=500M — journal 总大小上限 500MB
  • SystemMaxFileSize=100M — 单个文件上限
  • MaxRetentionSec=30day — 只保留 30 天

改动后重启 journald:

1
sudo systemctl restart systemd-journald

等等——重启 journald 不会丢日志吗?

答案是:重启时 active journal 会被 rotate,已持久化的日志不会丢。 你可以安全执行。

4.2 立刻缩减

配置改了,但现有的 3.9GB 还在。手动清理:

1
2
3
4
5
# 保留最近 7 天
sudo journalctl --vacuum-time=7d

# 或者保留最近 500MB
sudo journalctl --vacuum-size=500M

这个命令会删除旧日志文件,只保留满足条件的数据。注意:执行后 journal 会释放磁盘空间,但 journal 文件删除是文件级别操作,不会碎片化。

4.3 验证生效

1
2
$ journalctl --disk-usage
Archived and active journals take up 463.6M in the file system.

从 3.9GB → ~460MB,节省了 3.4GB。对于 N100 的 1TB 盘来说或许不算什么,但对于 /var/log/journal 可能位于系统分区的小盘机器来说,这个差异很关键。


5. 日志分析技巧

5.1 找出高频错误源

1
2
3
# 按服务/进程统计最近一周的 warn+ 日志
journalctl -p warn --since "7 days ago" --no-pager \
| awk '{print $5}' | sort | uniq -c | sort -rn | head -20

对 aicore 执行结果一目了然——蓝牙驱动独占了 TOP 1。

5.2 时间窗口分析

1
2
3
4
5
6
7
8
# 某个时间段内的 Kernel 错误
journalctl -k -p err --since "2026-06-18 00:00" --until "2026-06-19 00:00"

# Docker daemon 自己的日志
journalctl -u docker.service -p err --since "7 days ago"

# pm2 的错误输出(不是 access log)
journalctl -t pm2 -p err --since "today"

5.3 专注模式:只看真正需要关注的

如果你在排查某个容器的问题:

1
2
3
4
5
# 容器 stderr/stdout(如果 Docker 日志驱动是 journald)
journalctl CONTAINER_NAME=ai-portal -p err --since "1 hour ago"

# 或者直接用 Docker 的接口
docker logs --since 1h ai-portal 2>&1 | grep -i error

6. pm2 日志轮转

pm2 自己也有日志文件,默认在 ~/.pm2/logs/。pm2 内置了日志轮转模块:

1
2
3
4
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 100M
pm2 set pm2-logrotate:retain 3
pm2 set pm2-logrotate:compress true

这能防止 pm2 的应用日志无限增长。不过我实际检查了一下,ai-portal 的 pm2 日志目前只有几个 MB——得益于它只是提供 AI 对话界面,日志量很小。


7. 从日志到告警

日志治理不只是”别让它撑爆磁盘”。当关键事件发生时,日志应该变成告警。

目前的方案比较朴素——cron job 跑脚本检查 journal 中的关键模式:

1
2
3
4
5
6
7
8
#!/bin/bash
# /usr/local/bin/check-journal-alerts.sh
# 由 cron 每小时执行

if journalctl -p crit --since "1 hour ago" --quiet | grep -q .; then
# 发现 critical 级别日志,触发告警
echo "🚨 CRITICAL log detected in last hour" | mail -s "N100 Alert" michael@chenyun.org
fi

如果要更专业:journald 支持 ForwardToSyslog=yes 把日志转发到 rsyslog,然后在 rsyslog 做规则匹配和远程转发。对于家庭实验室来说,这个组合绰绰有余。


8. 真实事件复盘:蓝牙刷屏与 PCIe 错误

写这篇文章的契机,是这个 cron job 触发了检查时意外发现的”隐藏噪音”:

Bluetooth 误连(严重度:低)

ZEALOT-S32 音箱关机后,systemd 蓝牙服务每隔 30 秒尝试重新连接。这不是系统问题——但 2880 条/天的无效日志在浪费空间和注意力。

修复方案很简单:给蓝牙配置一个合理的连接超时,或者在不需要时禁用蓝牙模块。

PCIe AER(严重度:中)

1
pcieport 0000:00:1c.0: AER: Error of this Agent is reported first

频率很低(本周 3 次),但值得关注。AER(Advanced Error Reporting)通常是信号完整性问题——可能是 N100 SoC 内 PCIe 链路的状态转换问题,也可能是 mini PCIe 插槽的接触问题。如果频率增加(每天数十次),需要检查 dmesg 并考虑升级 BIOS/固件。


9. 最终配置清单

治理完成后,我的日志策略长这样:

1
2
3
4
5
✅ journald 上限 500MB,保留 30 天
✅ journalctl 按需清理至合理体积
✅ pm2-logrotate 安装并配置
✅ 关键日志告警脚本部署
✅ 已识别并记录噪音源(蓝牙/PCIe)

系统盘空间从 3.9GB 日志负担降至约 500MB。释放的 3.4GB 可以做更多有用的事——比如多存几张 Docker 镜像。


10. 下期预告

日志能告诉我们”发生了什么”,但性能数据告诉我们”跑得怎么样”。下一篇:

运维手记 #5: 性能调优 — N100 的性能边界在哪里?

涉及 CPU 调频策略、内存压缩、Swap 优化、I/O 调度和 Docker 资源限制。


本文所有数据来自 aicore(N100 / 32GB / 1TB NVMe / Ubuntu 24.04 / systemd 256)的真实运行环境。