बश लिपि प्रसंस्करण समानांतर में सीमित संख्या में आदेश


196

मेरे पास एक बैश स्क्रिप्ट है जो इस तरह दिखती है:

#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1

लेकिन प्रत्येक पंक्ति को संसाधित करना जब तक कि कमांड समाप्त नहीं हो जाती है तब अगले एक पर जाना बहुत समय लेने वाला होता है, मैं उदाहरण के लिए 20 लाइनों को एक बार में संसाधित करना चाहता हूं जब वे एक और 20 लाइनें समाप्त हो जाती हैं।

मैंने wget LINK1 >/dev/null 2>&1 &बैकग्राउंड में कमांड भेजने और इसे आगे बढ़ाने के बारे में सोचा , लेकिन यहां 4000 लाइनें हैं इसका मतलब है कि मेरे पास प्रदर्शन के मुद्दे होंगे, यह उल्लेख करने के लिए नहीं कि मुझे एक ही समय में कितनी प्रक्रियाएं शुरू करनी चाहिए, इसलिए यह अच्छा नहीं है विचार।

एक समाधान जो मैं अभी सोच रहा हूं वह यह जांच रहा है कि क्या एक कमांड अभी भी चल रहा है या नहीं, उदाहरण के लिए 20 लाइनों के बाद मैं इस लूप को जोड़ सकता हूं:

while [  $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done

निश्चित रूप से इस मामले में मुझे लाइन के अंत में और जोड़ना होगा! लेकिन मुझे लग रहा है कि यह करने का सही तरीका नहीं है।

इसलिए मैं वास्तव में प्रत्येक 20 लाइनों को एक साथ कैसे समूहित करता हूं और अगली 20 पंक्तियों पर जाने से पहले उनके समाप्त होने की प्रतीक्षा करता हूं, यह स्क्रिप्ट गतिशील रूप से उत्पन्न होती है इसलिए मैं इसे उत्पन्न होने के दौरान इस पर जो भी गणित करना चाहता हूं वह कर सकता हूं, लेकिन यह आवश्यक नहीं है wget का उपयोग करें, यह सिर्फ एक उदाहरण था ताकि कोई भी समाधान जो wget specific हो वह मुझे किसी भी तरह से अच्छा न लगे।


1
waitयहाँ सही उत्तर है, लेकिन आपका while [ $(ps …बहुत बेहतर लिखा होगा while pkill -0 $KEYWORD…- प्रोक्टूल का उपयोग करना ... अर्थात, एक विशिष्ट नाम के साथ एक प्रक्रिया अभी भी चल रही है या नहीं यह जाँचने के लिए वैध कारणों के लिए।
कोजिरो

मुझे लगता है कि इस सवाल को फिर से खोला जाना चाहिए। "संभव डुप्लिकेट" क्यूए सभी समानांतर में कार्यक्रमों की एक सीमित संख्या चलाने के बारे में है। 2-3 कमांड की तरह। हालाँकि, यह प्रश्न उदाहरण के लिए लूप में चलने वाले कमांड पर केंद्रित है। (देखें "लेकिन 4000 लाइनें हैं")।
VasiliNovikov

@VasyaNovikov क्या आपने इस प्रश्न और डुप्लिकेट दोनों के सभी उत्तर पढ़ लिए हैं? इस सवाल का हर एक जवाब यहाँ, डुप्लिकेट प्रश्न के उत्तर में भी पाया जा सकता है। यह ठीक एक डुप्लिकेट प्रश्न की परिभाषा है। यह पूरी तरह से कोई फर्क नहीं पड़ता है कि आप एक लूप में कमांड चला रहे हैं या नहीं।
रोबिनटेकस

@robinCS के चौराहे हैं, लेकिन सवाल खुद अलग हैं। इसके अलावा, लिंक किए गए QA पर सबसे लोकप्रिय उत्तरों में से 6 केवल 2 प्रक्रियाओं से संबंधित हैं।
वासिलीनोविक

2
मैं इस प्रश्न को फिर से खोलने की सलाह देता हूं क्योंकि इसका उत्तर स्पष्ट, स्वच्छ, बेहतर, और जुड़े प्रश्न पर उत्तर की तुलना में बहुत अधिक उत्थान है, हालांकि यह तीन साल अधिक है।
डैन निसेनबूम

जवाबों:


331

waitअंतर्निहित का उपयोग करें :

process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait

उपरोक्त उदाहरण के लिए, 4 प्रक्रियाएं process1... process4पृष्ठभूमि में शुरू की जाएंगी, और शेल अगले सेट को शुरू करने से पहले पूरा होने तक इंतजार करेगी।

से जीएनयू मैनुअल :

wait [jobspec or pid ...]

प्रतीक्षा करें जब तक कि प्रत्येक प्रक्रिया आईडी पिड या जॉब स्पेसिफिकेशन जॉबस्पेक द्वारा निर्दिष्ट बच्चे की प्रक्रिया समाप्त न हो जाए और अंतिम कमांड के एक्जिट स्टेटस का इंतजार करें। यदि नौकरी की युक्ति दी जाती है, तो नौकरी में सभी प्रक्रियाओं का इंतजार किया जाता है। यदि कोई तर्क नहीं दिया जाता है, तो वर्तमान में सभी सक्रिय बाल प्रक्रियाओं का इंतजार किया जाता है, और वापसी की स्थिति शून्य है। यदि न तो जॉबस्पेक और न ही पीआईडी ​​शेल की सक्रिय बाल प्रक्रिया को निर्दिष्ट करता है, तो वापसी की स्थिति 127 है।


14
तो मूल रूप सेi=0; waitevery=4; for link in "${links[@]}"; do wget "$link" & (( i++%waitevery==0 )) && wait; done >/dev/null 2>&1
kojiro

18
जब तक आप सुनिश्चित नहीं होते कि प्रत्येक प्रक्रिया ठीक उसी समय समाप्त हो जाएगी, यह एक बुरा विचार है। आपको वर्तमान नौकरियों को एक निश्चित कैप पर रखने के लिए नए रोजगार शुरू करने की आवश्यकता है .... समानांतर उत्तर है।
rsaw

1
क्या लूप में ऐसा करने का कोई तरीका है?
डोमेसेफिएट को

मैंने यह कोशिश की है, लेकिन ऐसा लगता है कि एक ब्लॉक में किए गए चर असाइनमेंट अगले ब्लॉक में उपलब्ध नहीं हैं। क्या यह इसलिए है क्योंकि वे अलग-अलग प्रक्रियाएं हैं? क्या चर को मुख्य प्रक्रिया में वापस संचार करने का एक तरीका है?
बॉबी

97

समानांतर देखें । इसका सिंटैक्स समान है xargs, लेकिन यह समानांतर में कमांड चलाता है।


13
यह उपयोग करने से बेहतर है wait, क्योंकि यह नई नौकरियों को शुरू करने का ख्याल रखता है जैसे कि पुराने को पूरा करने के बजाय, अगले बैच को शुरू करने से पहले पूरा करने के लिए इंतजार करना।
शेपनर

5
उदाहरण के लिए, यदि आपके पास किसी फ़ाइल में लिंक की सूची है, तो आप वह कर सकते हैं cat list_of_links.txt | parallel -j 4 wget {}जो wgetएक बार में चार s चालू रखेगा ।
श्री लामा

5
शहर में एक नया बच्चा है जिसे pexec कहा जाता है जो एक प्रतिस्थापन है parallel
स्लैशबिन

2
एक उदाहरण प्रदान करना अधिक मददगार होगा
jterm

1
parallel --jobs 4 < list_of_commands.sh, जहाँ list_of_commands.sh हर लाइन पर सिंगल कमांड (उदाहरण के wget LINK1बिना नोट &) के साथ एक फाइल है । करने की आवश्यकता हो सकती है CTRL+Zऔर bgइसे पृष्ठभूमि में चलने के बाद छोड़ देना चाहिए।
वीजी १४

71

वास्तव में, आप के लिए समानांतर में कमांड चला xargs सकते हैं। उसके लिए एक विशेष -P max_procsकमांड-लाइन विकल्प है। देखते हैं man xargs


2
+100 यह बहुत अच्छा है क्योंकि इसे बनाया गया है और इसका उपयोग करने के लिए बहुत सरल है और इसे एक-लाइनर में किया जा सकता है
क्ले

छोटे कंटेनरों के लिए उपयोग करने के लिए बढ़िया है, क्योंकि अतिरिक्त पैकेज / निर्भरता की आवश्यकता नहीं है!
मार्को रॉय

1
इस प्रश्न को उदाहरणों के लिए देखें: stackoverflow.com/questions/28357997/…
मार्को रॉय

7

आप 20 प्रक्रियाएं चला सकते हैं और कमांड का उपयोग कर सकते हैं:

wait

जब आपकी सभी पृष्ठभूमि की नौकरियां समाप्त हो जाएंगी तो आपकी स्क्रिप्ट प्रतीक्षा करेगी और जारी रहेगी।

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