انتظرت حلقة الانتظار لدينا 35 ساعة لنفسها: pgrep -f و pkill -f عبر SSH

العمليات

في 31 أكتوبر بدأنا حلقة صغيرة عبر SSH: انتظر حتى تنتهي مهمة ترجمة على جهاز آخر، ثم شغّل مهمة تابعة. انتهت مهمة الترجمة تلك الليلة. عندما نظرنا مرة أخرى بعد يومين، كانت الحلقة تنتظر منذ 35 ساعة، ولم تُشغَّل المهمة التابعة أبدًا.

ما كانت عليه الحلقة

ssh build-host 'while pgrep -f "i18n_job.py example.com" >/dev/null; do sleep 30; done; ./follow-up.sh'

تطابق pgrep -f نمطًا مع سطر الأوامر الكامل لكل عملية. يشغّل SSH الأمر المقتبس كـ bash -c 'while pgrep -f "i18n_job.py example.com" …'، ويحتوي سطر الأوامر هذا على النمط. تستثني pgrep عمليتها الخاصة من النتائج، لكنها لا تستثني الصدفة التي بدأتها. لذا، طالما كانت الحلقة نشطة، كانت تجد تطابقًا: نفسها.

نظيرتها: pkill -f تقتل الصدفة التي تعمل فيها

يحدث الشيء نفسه مع pkill -f، بنتائج أسوأ:

ssh build-host 'pkill -f "worker.py --queue a"; nohup python3 worker.py --queue a &'

يحتوي سطر الأوامر الخاص بالصدفة نفسها على النمط، لذا تقتل pkill الصدفة. يتوقف العامل ولا يُشغَّل مرة أخرى أبدًا، ويخرج SSH برمز 255 دون رسالة خطأ. يبدو الأمر وكأنه مشكلة اقتباس، وهو ما اعتقدناه في المرة الأولى.

بين سبتمبر ونهاية أكتوبر، وقعنا في أحدهما أو الآخر ما لا يقل عن اثنتي عشرة مرة: عمليات إعادة تشغيل لم تحدث أبدًا، وحلقة احتجزت فحصًا لمدة ثلاث ساعات ونصف، وأخرى احتجزت قائمة انتظار الترجمة لمدة 50 دقيقة، وهذه الحلقة.

ما نفعله الآن

Factory Floor، الحزمة التي تشغّل أجهزتنا، تعمل عبر وحدات systemd: فهي لا تبحث أبدًا عن عملية عبر سطر أوامرها. الحلقات التي سببت لنا مشاكل كانت تلك التي كتبناها يدويًا.

محدّث: