2009-10-01 21 views
13

मेरे पास कुछ प्रक्रियाएं <defunct>top (और ps) में दिखाई दे रही हैं। मैंने वास्तविक लिपियों और कार्यक्रमों से चीजों को उबलाया है।क्रॉन एंड अप निष्क्रिय द्वारा प्रसंस्कृत प्रक्रियाएं क्यों होती हैं?

मेरी crontab में:

#!/bin/bash 
# the real script does a little argument processing here 
"[email protected]" 

tester.sh की सामग्रियों (निश्चित रूप से है जो चिह्नित निष्पादन योग्य):

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

launcher.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 के बजाय चलाता हूं) को अधिक आसानी से संशोधित किया जा सकता है।

+1

वैसे, चिह्नित प्रक्रियाओं "' '" कहा जाता है "लाश"। – Teddy

+3

सम्भावित समाधान इस सूत्र में देना है: http://stackoverflow.com/questions/3748432/insane-crond-behavior-keeps-making-defunct-bash-processes –

उत्तर

10

क्योंकि वे wait(2) सिस्टम कॉल का विषय नहीं रहे हैं।

चूंकि कोई भविष्य में इन प्रक्रियाओं का इंतजार कर सकता है, इसलिए कर्नेल पूरी तरह से उनसे छुटकारा नहीं पा सकता है या यह wait सिस्टम कॉल निष्पादित करने में सक्षम नहीं होगा क्योंकि इसमें बाहर निकलने की स्थिति या सबूत नहीं होंगे इसका अस्तित्व अब और भी है।

जब आप खोल से एक शुरू करते हैं, तो आपका खोल 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 

तो, क्या हुआ था, मुझे लगता है कि:

  • क्रॉन कांटे और क्रॉन बच्चे खोल
  • खोल (1636) शुरू होता है sid शुरू होता है और 1636 pgid और शुरू होता है
  • खोल बाहर निकलता है सो, SIGCHLD क्रॉन के लिए 3562
  • संकेत नजरअंदाज कर दिया या गलत ढंग से निपटाया
  • खोल रहा है भेजा ज़ोंबी बदल जाता है। ध्यान दें कि नींद में प्रवेश करने के लिए नींद की जाती है, इसलिए जब नींद निकलती है तो सिग्नल और साफ हो जाएगा।जब भी ज़ोंबी काटा जाता है तब भी मैं यह पता लगाने की कोशिश कर रहा हूं। संभवतः कोई सक्रिय बच्चे क्रॉन 1629 के आंकड़े नहीं निकलते हैं, उस बिंदु पर ज़ोंबी को इनिट करने और रीपैड करने के लिए पुनर्निर्मित किया जाएगा। तो अब हम गायब SIGCHLD के बारे में सोचते हैं कि क्रॉन को संसाधित करना चाहिए था।
    • यह आवश्यक रूप से vixie cron की गलती नहीं है। जैसा कि आप यहाँ देख सकते हैं, libdaemon installs a SIGCHLD handlerdaemon_fork() के दौरान, और इस मध्यवर्ती 1629

      अब से एक त्वरित बाहर निकलने पर संकेत वितरण के साथ हस्तक्षेप कर सकता है, मैं भी अगर मेरी Ubuntu पर विक्सी क्रॉन भी libdaemon साथ बनाया गया है पता नहीं है, लेकिन कम से कम मैं एक नया सिद्धांत है। :-)

+0

यह वास्तव में पूरे दिन रहेंगे, न केवल क्रॉन उठता है। क्या आप उस पर टिप्पणी कर सकते हैं? असली कार्यक्रम जो मैं चलाता हूं (सो नहीं) घंटों और घंटों तक चलता है। –

+2

.. और क्या इसका कोई उचित समाधान है? क्या स्क्रिप्ट यह सुनिश्चित करने के लिए कुछ कर सकती है कि यह खत्म होने पर ज़ोंबी में नहीं बदलेगी? – Superole

+0

हाय, क्या आप मुझे बता सकते हैं कि इस समस्या को पुन: उत्पन्न कैसे करें? –

3

मुझे लगता है कि आप बस दो अलग-अलग प्रक्रियाओं नहीं होने से समस्या का समाधान की सलाह देते हैं:

exec "[email protected]" 

यह ज़रूरत से ज़्यादा समाप्त करेंगे: launcher.sh इसकी आखिरी पंक्ति पर ऐसा है प्रक्रिया।

+0

मुझे लगता है कि आप सही हैं, लेकिन मैं आसानी से ऐसा नहीं कर सकता क्योंकि 'लॉन्चर.श' का उपयोग कई चीजों द्वारा किया जाता है, जिनमें से कुछ तोड़ने पर टूट जाएंगे। मैं * एक नई लॉन्चर स्क्रिप्ट बनाने पर विचार कर सकता हूं जो निष्पादित करता है और अन्य संस्करण को बरकरार रखता है, लेकिन यह बल्कि अशिष्ट है। –

+0

@ जॉन जेविनक: मैं कल्पना नहीं कर सकता कि अगर आपने यह परिवर्तन किया तो चीजें तोड़ेंगी। यह एक कम प्रक्रिया के साथ प्रभावी रूप से एक ही बात है। – Teddy

+0

@ टेडी: जो चीज टूट जाएगी वह यह है कि कुछ लोग इसे एक इंटरैक्टिव खोल में करते हैं: '। launcher.sh foo bar' अगर लॉन्चर ने 'exec' किया था, तो उपयोगकर्ता का खोल लॉन्च प्रोग्राम के पूरा होने पर समाप्त हो जाएगा। मुझे पता है कि यह एक अजीब उपयोग मामला है, लेकिन इस तरह यह मौजूदा प्रणाली में है। –

3

मुझे लगता है कि क्रॉन सत्र में सभी subprocesses समाप्त करने के लिए इंतज़ार कर रहा है। नकारात्मक पिड तर्कों के संबंध में प्रतीक्षा (2) देखें। आप के साथ सेक्स देख सकते हैं:

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 

सूचना है कि श और नींद में ही सेक्स कर रहे हैं।

कमांड सेट (1) का उपयोग करें। setsid पृष्ठभूमि में कहते

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

सूचना आप & जरूरत नहीं है, यहाँ tester.sh है।

+0

ऐसा करने से 'launcher.sh' और' tester.sh' का कारण बनता है। मैं उन्हें दोनों को समाप्त करना चाहता हूं (कम से कम मेरी मूल स्थिति के साथ, 'tester.sh' समाप्त होता है -' सेटिड 'के साथ यह नहीं करता है, जो मैं नहीं चाहता)। –

+0

यह अजीब बात है, जब मैं इसे यहां चलाता हूं तो लॉन्चर और परीक्षक दोनों समाप्त हो जाते हैं। (लगभग तुरंत - मैंने अभी तक एक पीएस स्नैपशॉट नहीं लिया है जहां मैं उन्हें देख रहा हूं।) – bstpierre

+0

मैं उबंटू हार्डी 64-बिट का उपयोग कर रहा हूं। आप क्या? –

0

मुझे यह प्रश्न मिला, जबकि मैं इसी तरह के मुद्दे के साथ समाधान ढूंढ रहा था। दुर्भाग्यवश इस प्रश्न में जवाब ने मेरी समस्या का समाधान नहीं किया।

एक विकल्प मृत प्रक्रिया हत्या नहीं कर रहा है के रूप में आप पाते हैं और अपनी मूल प्रक्रिया को मारने के लिए की जरूरत है।

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

"grep '' 'आप एक विशिष्ट मृत प्रक्रिया आप के बाद कर रहे हैं के लिए खोज को सीमित कर सकते हैं: मैं निम्नलिखित तरीके से मृत प्रक्रियाओं की हत्या समाप्त हो गया।

-2

मैंने कई बार एक ही समस्या का परीक्षण किया है। और अंततः मुझे समाधान मिला है। नीचे दिखाए गए अनुसार बैश स्क्रिप्ट से पहले '/ bin/bash' निर्दिष्ट करें।

 
* * * * * /bin/bash /tmp/launcher.sh /tmp/tester.sh 
2
मेरी राय को

यह प्रक्रिया Crond (हर काम के लिए crond द्वारा पैदा की) stdin पर इनपुट जो crontab में आदेश की stdout/stderr को पहुंचाया जाता है के लिए इंतज़ार कर की वजह से है। ऐसा इसलिए किया जाता है क्योंकि क्रॉन उपयोगकर्ता को मेल के माध्यम से परिणामस्वरूप आउटपुट भेजने में सक्षम होता है।

तो Crond उपयोगकर्ता आदेश तक EOF के लिए इंतज़ार कर रहा है और सभी यह पैदा की है बच्चे प्रक्रियाओं पाइप बंद कर दिया है। यदि यह किया जाता है तो क्रॉइड प्रतीक्षा-कथन के साथ जारी रहता है और फिर निष्क्रिय उपयोगकर्ता कमांड गायब हो जाता है।

तो मुझे लगता है कि आप स्पष्ट रूप (अपनी स्क्रिप्ट में हर पैदा की उपप्रक्रिया पाइप फार्म डिस्कनेक्ट करने के लिए जैसे एक फ़ाइल या/dev/बातिल करने के लिए इसे पुनः निर्देशित द्वारा की है।

तो निम्न पंक्ति crontab में काम करना चाहिए:

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

हा, यह काम करता है और समझ में आता है! –