बैश, कुछ पृष्ठभूमि प्रक्रियाओं को कैसे चलाने दें लेकिन दूसरों की प्रतीक्षा करें?


11

मैं (अभी तक) एक और है wait, &, &&नियंत्रण प्रवाह सवाल ..

कहो कि मेरे पास कुछ इस तरह से एक स्क्रिप्ट है जहां मैं एक ही समय में जितना संभव हो उतना काम करना चाहता हूं:

# may take some hours
something InputA > IrrelevantA &
something InputB > IrrelevantB &

# may take an hour
(
   somethingElse InputA > OutputA &
   somethingElse InputB > OutputB &
)&& combine OutputA OutputB > Result

...morestuff

प्रश्न 1: स्क्रिप्ट में, combineदोनों somethingElseप्रक्रियाओं के समाप्त होने का इंतजार करता है जबकि दोनों somethingप्रक्रियाएं जारी रहती हैं?

प्रश्न 2: यदि नहीं - और मुझे संदेह है कि यह नहीं है - मुझे पृष्ठभूमि में दूर काम करने के लिए जारी प्रक्रियाओं के दौरान combineदोनों somethingElseप्रक्रियाओं के लिए केवल प्रतीक्षा करने के लिए कैसे मिलता है something?

जवाबों:


13

आपके उदाहरण में combineकमांड बस जैसे ही सबस्लेक्ट से बाहर निकलेगी (और अंतिम पृष्ठभूमि की प्रक्रिया बिना किसी त्रुटि के शुरू कर दी गई थी) चलाया जाएगा। waitकमांड शुरू नहीं होने के बाद सबस्क्रिप्शन तुरंत शुरू हो जाएगा ।

यदि आप दो या अधिक समकालिक पृष्ठभूमि प्रक्रियाओं के रिटर्न मूल्य के आधार पर एक कमांड निष्पादित करना चाहते हैं, तो मैं रिटर्न मानों के लिए अस्थायी फ़ाइलों का उपयोग करने के अलावा कोई अन्य तरीका नहीं देख सकता। ऐसा इसलिए है क्योंकि इसके लिए प्रतीक्षा की जाने वाली प्रक्रियाओं waitमें से केवल एक का रिटर्न वैल्यू वापस कर सकते हैं । इसके अलावा, जब पृष्ठभूमि प्रक्रियाओं को अपने रिटर्न मानों को प्राप्त करने के लिए उप-श्रेणियों में चलाया जाना चाहिए, तो उन्हें चरों में संग्रहीत नहीं किया जा सकता है। तुम यह कर सकते थे:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

tmp1=$(mktemp)
tmp2=$(mktemp)

( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!

( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!

wait "$proc1" "$proc2"

read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result

rm "$tmp1" "$tmp2"

यदि आप वास्तव में वापसी मूल्यों के बारे में परवाह नहीं करते हैं, तो आप बस सामान्य रूप से नौकरी शुरू कर सकते हैं और उपयोग कर सकते हैं wait:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

somethingElse InputA >OutputA &
proc1=$!

somethingElse InputB >OutputB &
proc2=$!

wait "$proc1" "$proc2"
combine OutputA OutputB >Result

नमस्ते, मुझे लगता है कि दूसरा विकल्प मेरे लिए काम करेगा ...
स्टीफन हेंडरसन

3

चाहेंगे प्रक्रिया प्रतिस्थापन और अधिक कुशल हो, खासकर यदि आप फ़ाइलों को बचाने के लिए की जरूरत नहीं है OutputAऔर OutputBकेवल के बारे में परवाह है, और Result? क्या यह विशेष रूप से समय की बचत होगी क्योंकि यदि आपके पास डिस्क में लिखने में धीमा I / O है, तो फ़ाइलों को सहेजना OutputAऔर OutputBदर-सीमित कदम हो सकता है?

combine  <(somethingElse InputA)  <(somethingElse InputB)  >  Result

प्रक्रिया प्रतिस्थापन आपको <(..here..)आउटपुट को एक फ़ाइल में सहेजने के बजाय कमांड को अंदर रखने की अनुमति देता है , और फिर "गठबंधन" चरण में इनपुट के रूप में इसे पढ़ने से।

यदि स्मृति एक सीमा है, और स्मृति किस आकार outputAऔर outputBउससे अधिक है, तो क्या यह पूरे उद्देश्य को हरा देगा?

combineचलने से पहले दोनों प्रक्रिया पूरी होने तक इंतजार करेंगे ?


यह "संकट" नहीं है; कृपया अपनी प्रतिक्रिया को प्रश्न के रूप में लिखें। सच में, आप एक नया विचार लेकर आए हैं, और मुझे लगता है कि यह बहुत अच्छा है। आपके कुछ बिंदुओं का जवाब देने के लिए: combineजैसे ही दोनों somethingElseकमांड शुरू हो जाएंगे, वैसे ही चलना शुरू हो जाएंगे , लेकिन यह ठीक है, क्योंकि <(…)चीजें पाइप हैं; तो combineबस अगर यह outruns डेटा के लिए इंतजार करने को मजबूर हो जाएगा somethingElseप्रक्रियाओं। और, क्योंकि वे पाइप हैं, आकार कोई समस्या नहीं है। … (Cont'd)
G-Man ने कहा कि मोनिका '

(Cont'd) ... आपके उत्तर के साथ एकमात्र एकमात्र समस्या यह है कि यह somethingElseप्रक्रियाओं की निकास स्थिति का परीक्षण करने की अनुमति नहीं देता है - और यह पूरी तरह से स्पष्ट नहीं है कि यह पूछने वाले के लिए महत्वपूर्ण है या नहीं। लेकिन, इसके अलावा, एक उत्तर की तरह सवाल नहीं पूछा जाना चाहिए।
जी-मैन का कहना है कि 'मोनिका'

2

आप waitकमांड का उपयोग कर सकते हैं :

(echo starting & sleep 10 & wait) && echo done

आप देख सकते हैं "शुरू" लाइन तुरंत होती है, और "किया" 10 सेकंड के लिए इंतजार करता है।


आम तौर पर प्रतीक्षा के लिए समान शेल की बाल प्रक्रियाओं की आवश्यकता होती है। रुको वहाँ बहुत मुश्किल है।
mikeserv

1
@mikeserv, आप किस बारे में बात कर रहे हैं? वह बात यह है: यह उस सबशेल में सभी बच्चों की प्रतीक्षा करता है।
psusi

मेरे शुरुआती परीक्षणों से यह काम करता है। मैं इसे अब बड़ी स्क्रिप्ट पर आज़माने जा रहा हूँ
स्टीफन हेंडरसन

बिल्कुल - एक ही शेल के बच्चे - उप गोले। यह किसी भी प्रक्रिया के लिए काम करना चाहिए जो भागने की कोशिश नहीं करता है - या डोनेमाइज़ या जो भी हो। थॉट्स का मेरा मतलब था - जब तक आपकी प्रक्रियाएं सम्मान प्रक्रिया के नेताओं का इंतजार करती हैं, ठीक है, लेकिन जैसे ही एक प्रक्रिया अपने स्वयं के प्रोसेस लीडर बनने का प्रयास करती है, प्रतीक्षा में समस्याएं होंगी।
mikeserv

0

मैं वास्तव में वास्तव में प्रदर्शित करता हूं कि इस प्रकार की बात यहां दूसरे उत्तर में कैसे हो सकती है । यह जवाब एक सवाल था कि पृष्ठभूमि प्रक्रिया द्वारा 2 लॉग बनाए गए थे, इसलिए मैंने इसे 10 के साथ प्रदर्शित किया।

डेमो स्क्रिप्ट

cat <<-\DEMO >|${s=/tmp/script} 
printf 'tty is %s\nparent pid is %s\npid is pid=%s\n' \
     "$(tty)" "$PPID" "$$"
exec 1>&2 ; nums=$(seq 0 9)
rm ${files=$(printf "/tmp/file%s\n" $nums)}
for n in $nums ; do { for f in $files ; do
    echo "Line $n" >>"$f" ; done
sleep 1 ; } ; done
#END
DEMO

डेमो चलाएं

s=/tmp/script ;chmod +x $s ;info="$(($s &)2>&- &)"
echo "$info" ; pid="${info##*=}" ; echo
while ps -p $pid >/dev/null ; do sleep 3 ; done
for f in /tmp/file[0-9] ; do
    printf 'path : %s\tline count : %s\n' \
        $f $(<$f wc -l)
done

आउटपुट:

tty is not a tty
parent pid is 1
pid is 12123

path : /tmp/file0    line count : 10
path : /tmp/file1    line count : 10
path : /tmp/file2    line count : 10
path : /tmp/file3    line count : 10
path : /tmp/file4    line count : 10
path : /tmp/file5    line count : 10
path : /tmp/file6    line count : 10
path : /tmp/file7    line count : 10
path : /tmp/file8    line count : 10
path : /tmp/file9    line count : 10

ऊपर दिखाया गया है। यह बनाता है और चलाता है नाम के एक स्क्रिप्ट /tmp/script, chmod's निष्पादन योग्य के रूप में यह है, और में इसे चलाता &backgroundएक की &backgrounded ( subshell )

स्क्रिप्ट rms /tmp/file0-910 फाइलें और echoesउनमें से सभी 10 में हर सेकंड एक लाइन। मैं कुछ $infoविवादास्पद प्रक्रिया से कब्जा कर लेता हूं और इसे $(command substitution). While psअभी भी आई $pidकैप्चर की रिपोर्ट के माध्यम से प्रस्तुत करता हूं, मुझे पता है कि यह अभी भी चलता है इसलिए मैं sleep.इसे पूरा करता हूं , सभी 10 फाइलों में पंक्तियों को गिना जाता है।wc.

इस तरह से एक प्रक्रिया को लागू करने के बाद आप इसकी मूल मूल प्रक्रिया को स्वतंत्र रूप से बंद कर सकते हैं और यह ट्रकिंग पर रहेगा - यह प्रभावी रूप से विख्यात है। यह भी मतलब है कि आप पारंपरिक उपयोग नहीं कर सकते waitआदेश है, लेकिन पर इंतजार कर psके बदले किसी भी मामले में और अधिक मजबूत किया जाना चाहिए।

वर्थ उल्लेख, मुझे लगता है, यह है कि प्रक्रिया वास्तव में शुरू में कहा जाता है $(command substitution)और printfsमुझे $infoमैं चाहता हूं ताकि मैं इसे प्रभावी रूप से नियंत्रित कर सकूं। लेकिन जैसे ही इसके साथ इसका टर्मिनल आउटपुट गिरता है exec 1>&2(जो2>&- इसके साथ उसी सबस्क्रिप्शन में बंद हो जाता है ), प्रक्रिया बच जाती है और मुझे दूसरे छोर पर इसके लिए इंतजार करना पड़ता है। दोनों दुनियाओं में से सबसे अच्छा Kinda, खासकर यदि आप इसका उपयोग इनपुट पाइप को संभालने के लिए करते हैं, तो जब तक आप अपने मन को सभी पुनर्निर्देशनों और प्रक्रिया के नेताओं के चारों ओर लपेट सकते हैं।

बाकी सब कुछ यहाँ प्रदर्शन के लिए है। आपको इसे चलाने की आवश्यकता है और यह शीर्ष स्क्रिप्ट है:

info="$(($script_path &)2>&- &)"    

नोट: यह केवल टर्मिनल को प्रिंट करता है जो मैंने इसे प्रदर्शित करने की इच्छा की थी। जैसा कि$PPID,इस प्रक्रिया से विख्यात है, टर्मिनल द्वारा विस्थापित है और इसका प्रत्यक्ष बच्चा है$PID 1.

यदि आप इनमें से दो को समवर्ती रूप से चलाना चाहते हैं और उनके लिए इंतजार करना चाहते हैं तो आप psउनके दोनों पलकों को हाथ लगा सकते हैं और प्रतीक्षा कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.