大家好,
报告一下官方 Docker/runit 设置中存在的一种故障模式,它可以在不进行任何重建或升级的情况下静默终止 Sidekiq(进而终止 AI/后台作业)。
环境
- 官方 Discourse Docker 安装(标准容器 + runit 服务)。
- 问题开始前没有进行重建/升级。
- Discourse AI 插件已启用,但 AI 停止回复。
症状
- 管理界面中 AI 显示为启用,但没有 AI 回复出现。
- 后台作业(AI/嵌入/自动回复)似乎卡住了。
sv status sidekiq显示 Sidekiq 在启动后反复崩溃:
down: sidekiq: 1s, normally up, want up
- 手动启动 Sidekiq 运行正常,说明应用程序本身没问题:
bundle exec sidekiq -C config/sidekiq.yml
# 保持运行,连接到 Redis,处理作业
我们发现的情况
默认的 runit 脚本是:
exec chpst -u discourse:www-data \
bash -lc 'cd /var/www/discourse && ... bundle exec sidekiq -e production -L log/sidekiq.log'
两个脆弱点:
- 主用户组 www-data 在我的容器中,典型的可写路径归 discourse:discourse 所有。当 Sidekiq 在 www-data 权限下启动时,tmp/pids 或共享路径的任何权限漂移都可能导致 Sidekiq 在启动时退出,即使以 discourse 用户手动启动是正常的。
- 强制的 -L log/sidekiq.log 写入共享日志 该日志路径是指向
/shared/log/rails/sidekiq.log的符号链接。如果该文件/目录以不同的所有权/权限重新创建,Sidekiq 可能会立即退出,而无法产生有用的日志。
相关触发因素:logrotate 每日失败
另外,logrotate 每天都会失败并报告:
error: skipping "...\log" because parent directory has insecure permissions
Set "su" directive in config file ...
原因是标准的 Debian/Ubuntu 权限设置:
/var/log是 root:adm,权限为 0775(组可写)。- 除非设置全局 su 指令,否则 logrotate 会拒绝轮换。这是预期的上游行为。
在每日 logrotate 作业失败的时刻,它也重新创建了 /shared/log/rails/ 下的文件(包括 sidekiq.log),这很可能与强制的 -L 日志记录相互作用,并导致了 Sidekiq 的“1秒崩溃”循环。
修复方法(无需重建)
- 修复 logrotate,使其停止在失败状态下触碰共享日志 添加一个全局 su 指令:
# /etc/logrotate.conf (顶部)
su root adm
之后,logrotate -v 退出代码为 0,并且不再报告父目录权限不安全。
- 用更健壮的默认值替换 Sidekiq runit 脚本 切换到 discourse:discourse 和标准的 sidekiq.yml,并且不强制 -L log/sidekiq.log,使 Sidekiq 稳定:
#!/bin/bash
exec 2>&1
cd /var/www/discourse
mkdir -p tmp/pids
chown discourse:discourse tmp/pids || true
exec chpst -u discourse:discourse \
bash -lc 'cd /var/www/discourse && rm -f tmp/pids/sidekiq*.pid; exec bundle exec sidekiq -C config/sidekiq.yml'
执行此操作后:
sv status sidekiq保持运行状态:- AI/后台作业恢复。
请求/建议
我们能否考虑默认情况下使官方 Docker/runit Sidekiq 服务更加健壮?
例如:
- 在 discourse:discourse 用户下运行 Sidekiq(与容器内典型所有权匹配)。
- 优先使用
bundle exec sidekiq -C config/sidekiq.yml。 - 避免通过
-L log/sidekiq.log强制指定共享日志文件,或者使其能够抵御 logrotate/共享卷权限漂移。
即使是添加一个文档说明(“如果 Sidekiq 显示 down: 1s 但手动启动正常,请检查 /etc/service/sidekiq/run 并避免强制共享日志记录”)也会对自托管用户有很大帮助。
如果需要更多日志,我很乐意提供。谢谢!