संक्षिप्त जवाब
में bash
और dash
) विभिन्न "नौकरी की स्थिति" संदेश सिग्नल हैंडलर से प्रदर्शित नहीं होते हैं, लेकिन एक स्पष्ट जांच की आवश्यकता होती है। यह चेक केवल नए प्रॉम्प्ट प्रदान करने से पहले किया जाता है, संभवतया उपयोगकर्ता को परेशान करने के लिए नहीं जब वह एक नया कमांड टाइप कर रहा हो।
यह kill
प्रदर्शित होने के बाद संकेत मिलने से ठीक पहले संदेश नहीं दिखाया गया है क्योंकि प्रक्रिया अभी तक मृत नहीं है - यह विशेष रूप से संभावित स्थिति है क्योंकि kill
शेल की आंतरिक कमान है, इसलिए यह निष्पादित करने के लिए बहुत तेज़ है और फोर्किंग की आवश्यकता नहीं है।
killall
इसके साथ एक ही प्रयोग करना , इसके बजाय, आमतौर पर "मारे गए" संदेश को तुरंत प्राप्त करता है, यह संकेत देता है कि समय / संदर्भ स्विच / जो किसी बाहरी कमांड को निष्पादित करने के लिए आवश्यक है, इस प्रक्रिया में देरी के लिए काफी देर हो सकती है क्योंकि नियंत्रण शेल से पहले मारा जाता है। ।
matteo@teokubuntu:~$ dash
$ sleep 60 &
$ ps
PID TTY TIME CMD
4540 pts/3 00:00:00 bash
4811 pts/3 00:00:00 sh
4812 pts/3 00:00:00 sleep
4813 pts/3 00:00:00 ps
$ kill -9 4812
$
[1] + Killed sleep 60
$ sleep 60 &
$ killall sleep
[1] + Terminated sleep 60
$
लंबा जवाब
dash
सबसे पहले, मुझे dash
सूत्रों पर एक नज़र थी , क्योंकि dash
समान व्यवहार प्रदर्शित करता है और कोड निश्चित रूप से सरल है bash
।
जैसा कि ऊपर कहा गया है, यह प्रतीत होता है कि जॉब स्टेटस मैसेज सिग्नल हैंडलर (जो "सामान्य" शेल कंट्रोल फ्लो को बाधित कर सकते हैं) से उत्सर्जित नहीं होते हैं, लेकिन वे एक स्पष्ट चेक ( showjobs(out2, SHOW_CHANGED)
कॉल इन dash
) का परिणाम होते हैं। REPL लूप में उपयोगकर्ता से नए इनपुट का अनुरोध करने से पहले।
इस प्रकार, यदि शेल उपयोगकर्ता इनपुट के इंतजार में अवरुद्ध है, तो ऐसा कोई संदेश उत्सर्जित नहीं होता है।
अब, क्यों नहीं दिखा है कि मारने के प्रदर्शन के बाद चेक प्रदर्शन किया गया था कि प्रक्रिया वास्तव में समाप्त हो गई थी? जैसा कि ऊपर बताया गया है, शायद इसलिए कि यह बहुत तेज़ है। kill
शेल का एक आंतरिक कमांड है, इसलिए इसे निष्पादित करने के लिए बहुत तेज़ है और फोर्किंग की आवश्यकता नहीं है, इस प्रकार, जब kill
चेक निष्पादित होने के तुरंत बाद , प्रक्रिया अभी भी जीवित है (या, कम से कम, अभी भी मारा जा रहा है)।
bash
जैसा कि अपेक्षित था, bash
बहुत अधिक जटिल शेल होने के नाते, पेचीदा था और कुछ-कुछ की आवश्यकता थी gdb
।
उस संदेश के उत्सर्जित होने के लिए बैकट्रेस कुछ इस तरह का होता है
(gdb) bt
#0 pretty_print_job (job_index=job_index@entry=0, format=format@entry=0, stream=0x7ffff7bd01a0 <_IO_2_1_stderr_>) at jobs.c:1630
#1 0x000000000044030a in notify_of_job_status () at jobs.c:3561
#2 notify_of_job_status () at jobs.c:3461
#3 0x0000000000441e97 in notify_and_cleanup () at jobs.c:2664
#4 0x00000000004205e1 in shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2213
#5 shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2159
#6 0x0000000000423316 in read_token (command=<optimized out>) at /Users/chet/src/bash/src/parse.y:2908
#7 read_token (command=0) at /Users/chet/src/bash/src/parse.y:2859
#8 0x00000000004268e4 in yylex () at /Users/chet/src/bash/src/parse.y:2517
#9 yyparse () at y.tab.c:2014
#10 0x000000000041df6a in parse_command () at eval.c:228
#11 0x000000000041e036 in read_command () at eval.c:272
#12 0x000000000041e27f in reader_loop () at eval.c:137
#13 0x000000000041c6fd in main (argc=1, argv=0x7fffffffdf48, env=0x7fffffffdf58) at shell.c:749
कॉल जो मृत नौकरियों और सह के लिए जाँच करता है। है notify_of_job_status
(यह कमोबेश बराबर showjobs(..., SHOW_CHANGED)
है dash
); # 0- # 1 इसके आंतरिक कामकाज से संबंधित हैं; 6-8 याक-जनित पार्सर कोड है; 10-12 आरईपीएल लूप है।
यहां दिलचस्प जगह # 4 है, जहां से notify_and_cleanup
कॉल आता है। ऐसा लगता है कि bash
इसके विपरीत dash
, कमांड लाइन से पढ़े गए प्रत्येक वर्ण पर समाप्त नौकरियों की जांच हो सकती है, लेकिन यहां मैंने जो पाया है:
/* If the shell is interatctive, but not currently printing a prompt
(interactive_shell && interactive == 0), we don't want to print
notifies or cleanup the jobs -- we want to defer it until we do
print the next prompt. */
if (interactive_shell == 0 || SHOULD_PROMPT())
{
#if defined (JOB_CONTROL)
/* This can cause a problem when reading a command as the result
of a trap, when the trap is called from flush_child. This call
had better not cause jobs to disappear from the job table in
that case, or we will have big trouble. */
notify_and_cleanup ();
#else /* !JOB_CONTROL */
cleanup_dead_jobs ();
#endif /* !JOB_CONTROL */
}
इसलिए, इंटरेक्टिव मोड में यह चेक को देरी करने के लिए जानबूझकर है जब तक कि एक नया संकेत प्रदान नहीं किया जाता है, संभवतः उपयोगकर्ता को कमांड दर्ज करने में परेशान नहीं करना है। इस बात के लिए कि जाँच के बाद नई प्रॉम्प्ट प्रदर्शित करने के तुरंत बाद मृत प्रक्रिया क्यों नहीं होती है kill
, पिछला स्पष्टीकरण (प्रक्रिया अभी मृत नहीं है) रखती है।
pid="$(sh -c 'cat "$fileName" |less & echo ${!}')"
लेकिन कम नहीं दिखा