Sidekiq runit 脚本过于脆弱:**discourse:www-data** **+ forced** **-L log/sidekiq.log** **导致 1 秒崩溃

您好——我将严格根据官方 Docker 容器的运行时事实重述此事。

我在运行的容器中看到的情况(事实)

这是一个官方 Docker 安装,带有 runit(标准的 /var/discourse 启动器工作流程;事件发生前没有重建)。在容器内:

  1. 存在一个 runit Sidekiq 服务,并且是正在被监控的那个
ls -l /etc/service/sidekiq/run
sv status sidekiq

事件期间的输出:

down: sidekiq: 1s, normally up, want up
  1. 手动启动 Sidekiq 成功
cd /var/www/discourse
sudo -u discourse bundle exec sidekiq -C config/sidekiq.yml

这会保持运行,连接到 Redis,并处理作业。

  1. 仅修补 /etc/service/sidekiq/run (不重建)立即修复了崩溃循环 将 /etc/service/sidekiq/run 替换为:
#!/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
run: sidekiq: (pid <PID>) <SECONDS>s

因此,在这个官方镜像中,Sidekiq 不是通过 Unicorn master 启动的;它是一个 runit 服务,其运行时脚本可能会陷入崩溃循环。

为什么您可能看不到确切的代码在

discourse_docker 中

我同意确切的文本可能不在仓库中,因为 /etc/service/sidekiq/run 是在镜像构建/启动期间生成/注入的运行时工件,不一定是 discourse_docker 中逐字对应的文件。但如上所示,它这个官方镜像中活动的受监控服务。

触发脆弱性的原因(事实 + 最少推断)

  • 我们还观察到由于标准的 Debian 权限设置(/var/log = root:adm 0775),logrotate 每天都会失败,因此在添加全局 su root adm 之前,logrotate 拒绝轮换。
  • 当 logrotate 失败时,它会在 /shared/log/rails/ 下重新创建文件,包括 sidekiq.log。
  • 此镜像中默认的 runit 脚本使用 discourse:www-data 并强制将 -L log/sidekiq.log 写入 /shared/log,这使得 Sidekiq 对共享卷权限漂移非常敏感,并可能在有有用日志之前立即退出。

请求/建议

鉴于以上情况,我们能否考虑加强默认的 Docker/runit Sidekiq 服务?

建议的默认设置:

  • 以 discourse:discourse 身份运行(与容器内的典型所有权匹配),
  • 通过 bundle exec sidekiq -C config/sidekiq.yml 启动,
  • 避免强制共享的 -L log/sidekiq.log(或使其具有弹性)。

这将防止导致所有后台/AI 作业停止的静默的 down: 1s 崩溃循环。

我很乐意测试您指向我的任何分支/提交。