سكريبت Sidekiq runit هش للغاية: **discourse:www-data** **+ إجباري** **-L log/sidekiq.log** **يسبب تعطل لمدة ثانية واحدة**

مرحباً بالفريق،

أبلغ عن وضع فشل في إعداد Docker/runit الرسمي يمكن أن يقتل Sidekiq بصمت (وبالتالي وظائف الذكاء الاصطناعي/المهام الخلفية) دون أي إعادة بناء أو ترقية.

البيئة

  • تثبيت Discourse Docker الرسمي (حاوية قياسية + خدمات runit).
  • لم تتم إعادة بناء/ترقية قبل بدء المشكلة.
  • تم تمكين إضافة Discourse 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'

نقطتا ضعف:

  1. المجموعة الأساسية www-data في حاويتي، تكون المسارات القابلة للكتابة عادةً مملوكة لـ discourse:discourse. أي انحراف في tmp/pids أو المسارات المشتركة يمكن أن يتسبب في خروج Sidekiq أثناء التمهيد عند تشغيله تحت www-data، على الرغم من أن البدء اليدوي كـ discourse يعمل.
  2. فرض -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 (قابل للكتابة للمجموعة).
  • يرفض logrotate التدوير ما لم يتم تعيين توجيه su عام. هذا هو السلوك المتوقع من جهة المنبع.

في اللحظة التي فشلت فيها مهمة logrotate اليومية، قامت أيضاً بإعادة إنشاء ملفات تحت /shared/log/rails/ (بما في ذلك sidekiq.log)، والتي من المحتمل أنها تفاعلت مع التسجيل القسري لـ -L وساهمت في حلقة تعطل Sidekiq “1s crash”.

الإصلاح (لا حاجة لإعادة بناء)

  1. إصلاح logrotate بحيث يتوقف عن لمس السجلات المشتركة في حالة فشل أضف توجيهاً عاماً لـ su:
# /etc/logrotate.conf (أعلى)
su root adm

بعد ذلك، يخرج logrotate -v بالرمز 0 ولا يبلغ عن أذونات غير آمنة للمجلد الأصل بعد الآن.

  1. استبدال سكربت runit الخاص بـ Sidekiq بآخر أكثر قوة كإعداد افتراضي التبديل إلى 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 قيد التشغيل:
  • تستأنف وظائف الذكاء الاصطناعي/المهام الخلفية.

طلب / اقتراح

هل يمكننا النظر في جعل خدمة Sidekiq الرسمية لـ Docker/runit أكثر قوة كإعداد افتراضي؟

على سبيل المثال:

  • تشغيل Sidekiq تحت discourse:discourse (مطابقة للملكية النموذجية داخل الحاوية).
  • تفضيل bundle exec sidekiq -C config/sidekiq.yml.
  • تجنب فرض ملف سجل مشترك عبر -L log/sidekiq.log، أو جعله مرناً ضد انحراف أذونات logrotate/المجلد المشترك.

حتى ملاحظة توثيق (“إذا أظهر Sidekiq down: 1s ولكن البدء اليدوي يعمل، تحقق من /etc/service/sidekiq/run وتجنب فرض التسجيل المشترك”) سيساعد مستخدمي الاستضافة الذاتية كثيراً.

يسعدني تقديم المزيد من السجلات إذا لزم الأمر. شكراً!