Fabric: غالبًا ما تفشل البرامج النصية الأولية في بدء شياطينهم

تم إنشاؤها على ١٩ أغسطس ٢٠١١  ·  19تعليقات  ·  مصدر: fabric/fabric

وصف

لقد تلقيت تقارير متعددة عن هذا على IRC ، بالإضافة إلى تعليق على # 350 ، والآن موضوع قائمة بريدية .

لا يوجد سبب واضح حتى الآن ، وبينما تم الإبلاغ عنه عدة مرات ، لا أتوقع أنها مشكلة مستمرة أو أننا سنسمع الكثير عنها. في بعض الاختبارات المحدودة للغاية التي أجريتها حتى الآن ، يمكنني إعادة إنشاء المشكلة ربما بنسبة 30-50٪ من الوقت - لكنها قابلة للتكرار.

يتمثل العَرَض ببساطة في أن البرامج النصية بنمط init المسؤولة عن بدء البرنامج الخفي ثم العودة فورًا ، ستعود "موافق" ، وتعود رمز 0 ورسالة الحالة "نجاح" مطبوعة إلى stdout - ولكنها لن تؤدي فعليًا إلى تشغيل البرنامج الخفي المعني.

تم إجراء اختباري الشخصي عبر أحدث نسخة رئيسية تستهدف Ubuntu 10.04 (Lucid) VM والبرنامج النصي الأولي لحزمة Apache2.


تم تقديمه في الأصل بواسطة Jeff Forcier ( bitprophet ) بتاريخ 2011-07-23 الساعة 07:25 مساءً بتوقيت شرق الولايات المتحدة

علاقات

  • متعلق برقم 350: النسيج يعطل بعض الأوامر عن بعد (لبرنامج الخفي)
Bug Docs Wart

التعليق الأكثر فائدة

فقط واجهت هذه المشكلة.
كان لدي موقف لا يمكنني فيه استخدام tty = False لأنني قمت بتشغيل الأمر مع sudo.
إضافة >& /dev/null < /dev/null & تنفذ بشكل جيد لكن العملية لم تبدأ.

لقد قمت بحل مشكلة إضافة وضع السكون بعد سطر تنفيذ الأوامر: nohup java -jar text.jar & sleep 5; exit 0

ال 19 كومينتر

نشر جيف فورسير ( bitprophet ):


صمم البرنامج النصي الأولي الذي أختبره ويبدو أن كل شيء يعمل بنفس الطريقة (أي سيناريوهات النجاح الحقيقي أو النجاح المزيف) ، مما يعني أن المشكلة تكمن في استدعاء apachectl يقوم به البرنامج النصي نفسه

البدء في التفكير في السبب الذي يمكن أن يكون من جانبنا:

  • نظرًا لأنه شبه عشوائي ، فإن هذا يجعلني أفكر في المشكلات السابقة مع النظام الفرعي IO الذي يعاني من حالة العرق. ومع ذلك ، لا يمكنني التفكير حقًا في كيفية تأثير ذلك على شيء ما على الطرف البعيد بهذه الطريقة ، وكانت ظروف السباق كلها محلية على أي حال.

    • قد تكون إحدى طرق اختبار ذلك هي معرفة ما إذا كانت هذه المشكلة تأتي مع Fab 0.9.x و pty = True (لمطابقة القيمة الافتراضية الحالية في 1.x).

  • يمكن أن يكون أيضًا متعلقًا بـ pty - لا أذكر أن هذه مشكلة قبل 1.0 وكان تعيين pty إلى True أحد التغييرات الرئيسية في السلوك الافتراضي. على الرغم من ذلك مرة أخرى ، لا أستطيع أن أفهم لماذا يتسبب استخدام النظام الفرعي الخاص بطلب pty في SSH في أن تتصرف سكربتات init بهذه الطريقة.

    • سيكون الاختبار هنا هو استخدام ssh -t <hostname> <command> ومعرفة ما إذا كان هذا أيضًا يعيد إنتاج المشكلة.


بتاريخ 2011-07-23 الساعة 07:45 مساءً بتوقيت شرق الولايات المتحدة

نشر جيف فورسير ( bitprophet ):


apache2ctl بحد ذاته هو أيضًا برنامج نصي مغلّف Bash يستدعي /usr/sbin/apache2 ، وهو رابط رمزي لثنائي فعلي قابل للتنفيذ في موقع تثبيت Apache mpm-worker. على وجه التحديد ، في الاستخدام العادي start يستدعي /usr/sbin/apache2 -k start . كما كان من قبل ، لا يبدو أن apache2ctl يتصرف بشكل مختلف في السيناريوهين المختلفين ، إعادة: قيمة الإرجاع أو الأقسام التي يتم تنفيذها.

مستندات /usr/sbin/apache2 محدودة نسبيًا (حتى على موقع Apache) ، مشيرة فقط إلى أنه يجب عليك استخدام apachectl لإعداد env vars (وهو أمر دقيق - تشغيل apache2 بحد ذاته ينقذ بشكل جميل من الواضح مع وجود أخطاء حول عدم ضبط هذه المتغيرات.)

فحص ناتج env قبل استدعاء apache2ctl لـ apache2 لا ينتج عنه سوى عدد قليل من العناصر: المستخدم ، المجموعة ، موقع ملف pidfile واللغة. هذه لا تتغير بين حالات النجاح والفشل. كنت أتمنى أن يكون هناك شيء ما في مختلف المصادر وإعدادات var في الأغلفة والتي قد تتغير في بعض الأحيان ، ولكن لا.


حتى الآن ، لن يكون هذا مفيدًا. حان الوقت لاختبار الأفكار المذكورة أعلاه (pty ، ssh) لمعرفة التغييرات التي حدثت هناك.


بتاريخ 2011-07-23 الساعة 08:46 مساءً بتوقيت شرق الولايات المتحدة

نشر جيف فورسير ( bitprophet ):


مع pty=False ، يبدو أنه يعمل بشكل أفضل (كما يتضح من تعليق Max في # 350). باستخدام الإعداد الافتراضي True ، كنت أرى حالات فشل تقريبًا 5/10 مرات ، وأحيانًا قليلة أكثر أو أقل. باستخدام False ، قمت بتشغيله حوالي 15 مرة متتالية بدون أي إخفاقات. لست خبيرًا في الإحصاء ولكن هذا يبدو جيدًا بالنسبة لي.

يؤدي تشغيل ssh يدويًا إلى نتائج مماثلة: ssh -t <host> sudo /etc/init.d/apache2 start سيفشل بصمت في بدء تشغيل Apache حوالي 50٪ من الوقت. نفس الشيء مع -T (فرض لا pty) ويبدأ 100٪ من الوقت.

لذلك هذا ليس خطأ فابريك. إنه شيء أعمق حيث تتصرف نصوص البادئة هذه عندما يكون نمط SSH الزائف قيد التشغيل.


الذهاب للحفر أعمق قليلاً من أجل الفضول ، ولكن يبدو أن "الحل" هنا هو الأسئلة الشائعة الجديدة التي تنص على استخدام pty=False عند مواجهة هذه المشكلة.


بتاريخ 2011-07-23 الساعة 08:59 مساءً بتوقيت شرق الولايات المتحدة

نشر جيف فورسير ( bitprophet ):


نعم ، لم أجد أي شيء يفسر هذا السلوك للأسف. بالنظر إلى النتائج المذكورة أعلاه ، أعتقد أن الأسئلة الشائعة هي بالتأكيد السبيل للذهاب.


بتاريخ 2011-07-23 الساعة 10:35 مساءً بتوقيت شرق الولايات المتحدة

كتب هوغو غارزا (hiro2k):


آه ، لقد واجهت هذا بالأمس ، أتمنى لو كنت قد رأيت هذا الخطأ ، لحسن الحظ أنني حاولت تعيين pty = False وقد نجح أيضًا. شكرا للتوضيح ، على الأقل ليس خطأ في الأقمشة. الآن لديك حقًا أتساءل لماذا فشل هذا.


بتاريخ 2011-08-02 الساعة 01:27 مساءً بتوقيت شرق الولايات المتحدة

هل أنت متأكد من أن هذه ليست مجرد مشكلة في برنامج bash النصي أيضًا؟ أعني مع موضوع القائمة البريدية الخاص بي. كانت مجرد نصوص باش بدأت جافا وويب لوجيك.

FWIW ، لقد تلقيت هذا السلوك الرهيب على كل جهاز Ubuntu تقريبًا أقوم بتدويره على EC2.

كما أنه قابل للتكرار مع المهام التي تم إطلاقها عبر شاشة منفصلة screen -d -m someBackgroundTask .

يجب أن أذكر أنه عادةً ما يحل pty=False المشكلة ، لكنني رأيت حالات لم يكن الأمر كذلك.

yuvadm - في تلك الحالات التي لا يحل فيها pty = False المشكلة ، هل يمكن إعادة إنشاء المشكلة باستخدام أمر ssh العادي (كما هو مذكور أعلاه)؟ بقدر ما رأيت أنها مشكلة SSH وليست مشكلة قماش ، ولكن سيكون من الجيد معرفة ما إذا كانت هناك أي مواقف لا تتطابق فيها.

هذه زاوية مثيرة للاهتمام للتحقق منها ، وسأعود إليك بشأن هذه الزاوية ...

لقد أعدت إنتاج هذه المشكلة. العميل هو Ubuntu 10.04.3 LTS ، الخادم هو "Ubuntu 8.04.4 LTS (الخادم)".
عميل SSH هو "OpenSSH_5.3p1 Debian-3ubuntu7 ، OpenSSL 0.9.8k 25 مارس 2009" ، خادم ssh هو "OpenSSH_4.7p1 Debian-8ubuntu1 ، OpenSSL 0.9.8g 19 أكتوبر 2007". النسيج "1.3.3 نهائي".

المشكلة هي أن هناك 100٪ مع pty = صحيح ، وتختفي مع pty = False.

عند الاتصال بخوادم أخرى ، لا تظهر المشكلة دائمًا عندما تكون pty = True.

في حالتي ، لإجراء الاختبار ، أقوم بتشغيل أمر بسيط للغاية: "nohup sleep 100> / tmp / xxx 2> & 1

لقد تعرضت للعض من هذا ، فقط على EC2 كما يبدو (لم أره على Linode الخاص بي ، لكنني لست متأكدًا بنسبة 100٪). يبدو أن إعداد pty = False يعمل على إصلاحه.

فقط واجهت هذه المشكلة.
كان لدي موقف لا يمكنني فيه استخدام tty = False لأنني قمت بتشغيل الأمر مع sudo.
إضافة >& /dev/null < /dev/null & تنفذ بشكل جيد لكن العملية لم تبدأ.

لقد قمت بحل مشكلة إضافة وضع السكون بعد سطر تنفيذ الأوامر: nohup java -jar text.jar & sleep 5; exit 0

شكرا spodgruskiy ،

نصائحك تعمل بالنسبة لي.
لقد حاولت كتابة fab tp ابدأ مجموعة strom بالأوامر التالية.

  1. تشغيل ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &'، pty = False)
  2. تشغيل ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &')
  3. تشغيل ("screen -d -m './bin/storm nimbus'" ، pty = False)
  4. تشغيل ("|| screen -d -m './bin/storm nimbus'")

لكن أيا منها لا يعمل ، لم تبدأ الهالة على الإطلاق. لا أفهم ما حدث.
شكرا على أي حال.

+1 لخدعة النوم

اللازمة للعمل على الأنظمة ذات المتطلبات

sudo ('بدء الخدمة ؛ النوم .5') وكل شيء على ما يرام!

عند استخدام 'sudo ()' وتم تمكين RequireTty للنظام البعيد للوصول إلى sudo ، يمكنك استخدام 'set -m؛ الخدماتstart 'لمنع إرسال SIGHUP إلى العملية التي بدأت بواسطة البرنامج النصي الأولي.

راجع http://stackoverflow.com/a/14866774 للحصول على شرح أكثر تفصيلاً حول bash التفاعلي مقابل غير التفاعلي وكيف يؤثر ذلك على التحكم في الوظيفة.

أنا فضولي ، ما هي مشكلة ssh هنا؟

pty = أعمال كاذبة بالنسبة لي

إنها ليست مشكلة SSH حقًا ، إنها سلوك خفي حول أوضاع BASH غير التفاعلية / التفاعلية وانتشار الإشارة إلى مجموعات المعالجة.

يعتمد ما يلي على http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 و http: //www.itp.uzh.ch/~dpotter/howto/daemonize ، مع بعض الافتراضات التي لم يتم التحقق من صحتها بشكل كامل ، ولكن يبدو أن الاختبارات حول كيفية عمل ذلك تؤكد.

pty / tty = خطأ

تتصل قذيفة bash التي تم إطلاقها بـ stdout / stderr / stdin للعملية التي بدأت وتستمر في العمل حتى لا يكون هناك أي شيء متصل بالمآخذ وقد خرج الأطفال منه. ستضمن عملية deamon الجيدة أنها لا تنتظر خروج أطفالها ، وتشكيل عملية طفل ثم الخروج. عندما تكون في هذا الوضع ، لن يتم إرسال SIGHUP إلى العملية الفرعية بواسطة SSH. أعتقد أن هذا سيعمل بشكل صحيح مع معظم البرامج النصية التي تنفذ عملية تتعامل مع إزالة الشوائب من نفسها ولا تحتاج إلى الخلفية. عندما تستخدم البرامج النصية الخاصة بـ init "&" في خلفية عملية ما ، فمن المحتمل أن تكون المشكلة الرئيسية هي ما إذا كانت العملية التي تمت في الخلفية تحاول القراءة من stdin لأن ذلك سيؤدي إلى تشغيل SIGHUP إذا تم إنهاء الجلسة.

pty / tty = صحيح *

إذا بدأت العملية بخلفيات البرنامج النصي init ، فإن BASH shell الأصلي سيعيد رمز الخروج إلى اتصال SSH ، والذي بدوره سيبحث عن الخروج فورًا لأنه لا ينتظر إنهاء العملية الفرعية ولا يتم حظره على stdout / stderr / stdin. سيؤدي هذا إلى إرسال SIGHUP إلى مجموعة عمليات bash shell الأصلية ، والتي ستتضمن العمليات الفرعية التي تم إطلاقها للتو ، نظرًا لتعطيل التحكم في الوظيفة في الوضع غير التفاعلي في bash. عندما تبدأ عملية خفية صراحةً جلسة عملية جديدة عند التفرع أو في عملية متشعبة ، فلن تتلقى أو أطفالها SIGHUP من عملية BASH الأب. لاحظ أن هذا يختلف عن الوظائف المعلقة التي ستشاهد علامة SIGTERM.

أظن أن المشاكل حول هذا العمل فقط في بعض الأحيان لها علاقة بحالة سباق طفيفة. إذا نظرت إلى المقاربة القياسية للتشريح - http://www.itp.uzh.ch/~dpotter/howto/daemonize ، سترى أنه في الكود تم إنشاء الجلسة الجديدة بواسطة عملية متشعبة قد لا تكون كذلك تشغيل قبل خروج الوالدين ، مما يؤدي إلى سلوك النجاح / الفشل العشوائي المذكور أعلاه. سيتيح بيان النوم وقتًا كافيًا للعملية المتشعبة لإنشاء جلسة جديدة ، وهذا هو سبب نجاحها في بعض الحالات.

pty / tty = صحيح ويتم تمكين التحكم في الوظيفة صراحةً في bash

لن يتصل SSH بـ stdout / stderr / stdin من bash shell أو أي عمليات فرعية تم إطلاقها ، مما يعني أنه سيخرج بمجرد أن يبدأ bash shell الرئيسي في الانتهاء من تنفيذ الأوامر المطلوبة. في هذه الحالة ، مع تمكين التحكم في الوظيفة بشكل صريح ، سيتم وضع أي عمليات أطلقها bash shell مع "&" في الخلفية في جلسة منفصلة على الفور ولن تتلقى إشارة SIGHUP عندما تنتهي العملية الأصلية إلى جلسة BASH ( اتصال SSH في هذه الحالة).

ما هو المطلوب لإصلاح

أعتقد أن الحلول تحتاج فقط إلى الإشارة إليها صراحةً في وثائق عمليات التشغيل / sudo كحالة خاصة عند العمل مع العمليات / الخدمات في الخلفية. بشكل أساسي ، إما أن تستخدم "pty = false" ، أو إذا لم يكن ذلك ممكنًا ، فقم صراحة بتمكين التحكم في الوظيفة كأمر أول ، وسيكون السلوك صحيحًا.

كما ذكرت هنا فابريكيت (غلاف من القماش libs) https://github.com/HyukjinKwon/fabrickit/commit/cceb8bfb8f960a3ac41b24c64b8358bd6e7a0366

يمكنك بسهولة بدء تشغيل برنامج كبرنامج خفي بدون تكوينات أو إعدادات محددة.
هذا على أي حال نوع من تنفيذ شل وبالتالي يجب أن تكون هناك طريقة لفعل ما يمكن أن تفعله شل.

جرب هذا:

run("sh -c '((nohup %s > /dev/null 2> /dev/null) & )'" % cmd, pty=False)

لقد جربت هذا وهو يعمل بشكل جيد تمامًا حتى أنه لا يقوم بتنفيذ برمجة إضافية لتشغيلها كخادم (حتى مجرد برنامج يكتب "Hello" خلال حلقة while يعمل بشكل جيد).

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات