سكريبت 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 وتجنب فرض التسجيل المشترك”) سيساعد مستخدمي الاستضافة الذاتية كثيراً.

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

إعجاب واحد (1)

أين تجد ذلك؟ يتم تشغيل Sidekiq عبر رئيس unicorn للحفاظ على الذاكرة. لا أرى هذا الكود على الإطلاق في discourse_docker. يبدو أنك ربما تستخدم إعدادًا قديمًا جدًا؟

إعجابَين (2)

مرحباً — دعني أعيد صياغة هذا استنادًا بشكل صارم إلى حقائق وقت التشغيل من حاوية 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. ولكنه هو الخدمة الخاضعة للإشراف النشطة في هذه الصورة الرسمية، كما هو موضح أعلاه.

ما أثار الهشاشة (حقائق + استدلال بسيط)

  • لاحظنا أيضًا فشل logrotate اليومي بسبب أذونات Debian القياسية: /var/log = root:adm 0775، لذلك رفض logrotate التدوير حتى تمت إضافة su root adm عام.
  • عندما كان 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 (أو جعله مرنًا).

سيمنع هذا حلقة التعطل الصامتة down: 1s التي توقف جميع مهام الخلفية/الذكاء الاصطناعي.

يسعدني اختبار أي فرع/تثبيت تشير إليه.

مرة أخرى… أنا مرتبك بشأن مصدر صورتك:

image

هذه هي الصورة الرسمية.

هذا بحث عن كلمة sidekiq في مستودع discourse docker الرسمي.

https://github.com/search?q=repo%3Adiscourse%2Fdiscourse_docker%20sidekiq&type=code

هناك 3 نتائج… لا شيء عن وحدة runit. تتم إدارتها عبر unicorn.

إعجاب واحد (1)

مرحباً — شكراً لك، لقطة الشاشة هذه توضح التخطيط.

أتفق على أن Sidekiq في الصورة الرسمية الحالية ليس خدمة runit منفصلة (لا يوجد /etc/service/sidekiq/). يتم تشغيله من سلسلة بدء تشغيل خدمة runit الخاصة بـ unicorn، وهو ما يتطابق مع قائمة /etc/service الخاصة بك.

تقريري لا يزال يتعلق بوضع فشل وقت التشغيل لمسار إطلاق Sidekiq هذا، بغض النظر عما إذا كان يعيش في وحدة runit مستقلة أو داخل unicorn/run:

حقائق من وقت التشغيل على خادمي الافتراضي الخاص (Docker الرسمي، بدون إعادة بناء/ترقية قبل الحادث):

  1. توقفت الوظائف الخلفية وتوقفت ردود الذكاء الاصطناعي.

  2. دخل Sidekiq في حلقة تعطل فورية (متوقف: ثانية واحدة) عند تشغيله بواسطة المشرف/سلسلة بدء تشغيل الحاوية.

  3. التشغيل اليدوي كـ discourse عبر bundle exec sidekiq -C config/sidekiq.yml ظل قيد التشغيل وعالج المهام، لذا كان التطبيق/redis بخير.

  4. في الوقت نفسه، تسببت أخطاء logrotate في إعادة إنشاء /shared/log/rails/sidekiq.log (والمسارات ذات الصلة) بأذونات مختلفة؛ بعد تثبيت أمر تشغيل Sidekiq (التشغيل كـ discourse:discourse، استخدام sidekiq.yml، تجنب فرض المشاركة -L sidekiq.log)، توقفت حلقة التعطل على الفور.

لذا، قد لا يوجد الملف الحرفي /etc/service/sidekiq/run في هذه الصورة — متفق عليه — ولكن خطوة إطلاق Sidekiq المضمنة في خدمة runit الخاصة بـ unicorn هشة تجاه أذونات وحدة التخزين المشتركة/تغير logrotate ويمكن أن تقتل Sidekiq بصمت دون إعادة بناء. هذه هي القضية الأساسية.

اقتراح: يرجى النظر في تعزيز إطلاق Sidekiq في سكربت runit الرسمي لـ unicorn (أو حيث يتم إنشاؤه):

  • تشغيل Sidekiq تحت discourse:discourse،

  • تفضيل bundle exec sidekiq -C config/sidekiq.yml،

  • تجنب فرض سجل مشترك -L log/sidekiq.log (أو جعله مرناً).