سؤال

لدي بعض العمليات تظهر كما <defunct> في topps). لقد تغلبت الأشياء من البرامج النصية الحقيقية والبرامج.

في crontab:

* * * * * /tmp/launcher.sh /tmp/tester.sh

محتويات launcher.sh (وهو بالطبع ملحوظا قابل للتنفيذ):

#!/bin/bash
# the real script does a little argument processing here
"$@"

محتويات tester.sh (وهو بالطبع ملحوظا قابل للتنفيذ):

#!/bin/bash
sleep 27 & # the real script launches a compiled C program in the background

ps يظهر ما يلي:

user       24257 24256  0 18:32 ?        00:00:00 [launcher.sh] <defunct>
user       24259     1  0 18:32 ?        00:00:00 sleep 27

لاحظ أن tester.sh لا يظهر - لقد خرجت بعد إطلاق وظيفة الخلفية.

لماذا launcher.sh عصا حولها، ملحوظ <defunct>ب يبدو فقط أن تفعل هذا عند إطلاقه cron- لا عند تشغيله بنفسي.

مذكرة إضافية: launcher.sh هو برنامج نصي مشترك في النظام يتم تشغيله، وهو ما لا يتم تعديله بسهولة. الأشياء الأخرى (crontab, tester.sh, ، حتى البرنامج الذي أجري بدلا من sleep) يمكن تعديلها بسهولة أكبر.

هل كانت مفيدة؟

المحلول

لأنهم لم يكونوا موضوع wait(2) مكالمة النظام.

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

عندما تبدأ واحدة من Shell، فإن Shell الخاص بك هي محاصرة Sigchld وعمليات الانتظار المختلفة على أي حال، لذلك لا شيء يبقى باقلا لفترة طويلة.

لكن كرون ليس في حالة الانتظار، فهو نائم، لذلك قد يلتصق الطفل المنفصل لفترة من الوقت حتى يستيقظ كرون.


تحديث: الاستجابة للتعليق ... هم. لقد تمكنت من تكرار المشكلة:

 PPID   PID  PGID  SESS COMMAND
    1  3562  3562  3562 cron
 3562  1629  3562  3562  \_ cron
 1629  1636  1636  1636      \_ sh <defunct>
    1  1639  1636  1636 sleep

لذلك، ماذا حدث، أعتقد:

  • يبدأ Cron Forks و Chron Child Shell
  • شل (1636) يبدأ SID و PGID 1636 ويبدأ النوم
  • مخارج شل، Sigchld أرسلت إلى Cron 3562
  • يتم تجاهل الإشارة أو مشاركتها
  • قذيفة تحول غيبوبة. لاحظ أن النوم يعود لإحداثها، لذلك عندما يخرج النوم الإناث سيحصل على الإشارة والتنظيف. ما زلت أحاول معرفة متى يتم غياد الزومبي. ربما مع عدم وجود أطفال نشط Cron 1629 أرقام يمكن الخروج، عند تلك النقطة، سيتم إعادة إيلاء غيبوبة للتغليف والحديث. حتى الآن نحن نتساءل عن Sigchld المفقود الذي يجب أن تتم معالجة كرون.
    • انها ليست بالضرورة خطأ vixie كرون. كما ترون هنا، Libdaemon يثبت معالج SIGCHLD خلال daemon_fork(), ، وهذا يمكن أن يتداخل مع تسليم الإشارات على الخروج السريع من قبل الوسيط 1629

      الآن، لا أعرف حتى إذا تم بناء Vixie Cron على نظام Ubuntu الخاص بي مع LIBDaemon، ولكن على الأقل لدي نظرية جديدة. :-)

نصائح أخرى

أظن أن كرون ينتظر جميع الإجراءات الفرعية في الجلسة لإنهاء. انظر الانتظار (2) فيما يتعلق بحجج PID السلبية. يمكنك أن ترى Sess مع:

ps faxo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

إليك ما أراه (تم تحريره):

STAT  EUID  RUID TT       TPGID  SESS  PGRP  PPID   PID %CPU COMMAND
Ss       0     0 ?           -1  3197  3197     1  3197  0.0 cron
S        0     0 ?           -1  3197  3197  3197 18825  0.0  \_ cron
Zs    1000  1000 ?           -1 18832 18832 18825 18832  0.0      \_ sh <defunct>
S     1000  1000 ?           -1 18832 18832     1 18836  0.0 sleep

لاحظ أن SH والنوم في نفس سيس.

استخدم الأمر SetSID (1). إليك Tester.Sh:

#!/bin/bash
setsid sleep 27 # the real script launches a compiled C program in the background

لاحظ أنك لا تحتاج &, ، ساعد يضعه في الخلفية.

رأيي ناجم عن روند العمليات (ناجمة من قبل كروند لكل مهمة) في انتظار المدخلات على Stdin التي يتم ربطها إلى Stdout / Stderr من الأمر في Crontab. يتم ذلك لأن Cron قادر على إرسال الإخراج الناتج عبر البريد إلى المستخدم.

حتى لا ينتظر Crond ل EOF حتى أمر المستخدم وجميع عمليات الأطفال المستأجرة قد أغلقت الأنبوب. إذا تم ذلك، يستمر Crond مع بيان الانتظار ثم يختفي أمر المستخدم المنفصل.

لذلك أعتقد أنك يجب أن تفصل بشكل صريح عن كل الإعانات الفرعية المزروعة في البرنامج النصي الخاص بك في شكل الأنبوب (على سبيل المثال عن طريق إعادة توجيهه إلى ملف أو / dev / null.

لذلك يجب أن يعمل الخط التالي في Crontab:

* * * * * ( /tmp/launcher.sh /tmp/tester.sh &>/dev/null & ) 

أود أن أوصي بأن تحل المشكلة ببساطة عن طريق عدم وجود عمليتين منفصلين: launcher.sh القيام بذلك على السطر الأخير:

exec "$@"

سيؤدي هذا إلى القضاء على العملية الزائدة.

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

إن قتل العملية المنفذة ليست خيارا ما تحتاجه للعثور على العملية الأصلية وقتلتها. انتهى بي الأمر بقتل العمليات المنفذة بالطريقة التالية:

ps -ef | grep '<defunct>' | grep -v grep | awk '{print "kill -9 ",$3}' | sh

في "GREP" "يمكنك تضييق نطاق البحث في عملية منفصلة محددة، بعد.

لقد اختبرت نفس المشكلة عدة مرات. وأخيرا لدي الحل. فقط حدد "/ bin / bash" قبل البرنامج النصي باش كما هو موضح أدناه.

* * * * * / bin / bash / tmp/launcher.sh /tmp/tester.sh
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top