2009-01-21 23 views
42

मेरे पास 200 कमांड की एक सूची/कतार है जिसे मुझे लिनक्स सर्वर पर खोल में चलाने की आवश्यकता है।लिनक्स पर एक कमांड कतार से समानांतर प्रसंस्करण (बैश, पायथन, रूबी ... जो कुछ भी)

मैं केवल एक बार में अधिकतम 10 प्रक्रियाओं (कतार से) चलाना चाहता हूं। कुछ प्रक्रियाओं को पूरा करने में कुछ सेकंड लगेंगे, अन्य प्रक्रियाओं में अधिक समय लगेगा।

जब कोई प्रक्रिया समाप्त होती है तो मैं चाहता हूं कि अगला आदेश कतार से "पॉप" हो और निष्पादित हो।

क्या किसी को भी इस समस्या को हल करने के लिए कोड है?

आगे विस्तार:

वहाँ काम के 200 टुकड़े, किया जाना किसी प्रकार की एक कतार में जरूरत है कि है। मैं एक ही समय में काम के लगभग 10 टुकड़े चलाना चाहता हूं। जब एक धागा काम के टुकड़े को खत्म करता है तो उसे कतार के अगले भाग के लिए पूछना चाहिए। यदि कतार में कोई और काम नहीं है, तो धागा मरना चाहिए। जब सभी धागे मर गए हैं तो इसका मतलब है कि सभी काम किए गए हैं।

वास्तविक समस्या जिसे मैं हल करने का प्रयास कर रहा हूं imapsync का उपयोग पुराने मेल सर्वर से एक नए मेल सर्वर से 200 मेलबॉक्स सिंक्रनाइज़ करने के लिए कर रहा है। कुछ उपयोगकर्ताओं के पास बड़े मेलबॉक्स होते हैं और सिंक करने में लंबा समय लगता है, दूसरों के पास बहुत छोटे मेलबॉक्स होते हैं और जल्दी सिंक होते हैं।

उत्तर

38

मुझे लगता है कि आप इसे बनाने और मेक-जे xx कमांड का उपयोग करके ऐसा कर सकते हैं।

शायद यह

all : usera userb userc.... 

usera: 
     imapsync usera 
userb: 
     imapsync userb 
.... 

मेकअप -j 10 -f makefile की तरह एक makefile

+1

है जैसा कि मैंने आशा की थी कि यह ठीक है। मैंने मेकफ़ाइल उत्पन्न करने के लिए कुछ कोड लिखा था। यह 1000 से अधिक लाइनों से समाप्त हो गया। धन्यवाद! – mlambie

+1

+1 यह वास्तव में बहुत चालाक है! – progo

+1

मैंने पाया कि यदि कोई भी आदेश किसी त्रुटि कोड से निकलता है, तो भविष्य में नौकरियों के निष्पादन को रोकने से बाहर निकलेंगे। कुछ स्थितियों में, यह समाधान आदर्श से कम है। इस परिदृश्य के लिए कोई सिफारिशें? –

2

यदि आप पायथन का उपयोग करने जा रहे हैं, तो मैं इसके लिए Twisted का उपयोग करने की सलाह देता हूं।

विशेष रूप से Twisted Runner

-3

क्या आप द्वारा समांतर में अपना मतलब बता सकते हैं? ऐसा लगता है कि आपको कतार में किसी प्रकार की लॉकिंग को लागू करने की आवश्यकता है, इसलिए आपकी प्रविष्टियों को दो बार नहीं चुना जाता है, और कमांड केवल एक बार चलते हैं।

अधिकांश कतार प्रणाली धोखा देती है - वे सिर्फ एक विशाल टू-डू सूची लिखते हैं, फिर चुनें। दस आइटम, उन्हें काम करें, और अगले दस आइटम का चयन करें। कोई समांतरता नहीं है।

यदि आप कुछ और विवरण प्रदान करते हैं, तो मुझे यकीन है कि हम आपकी मदद कर सकते हैं।

7

जीएनयू बनाने (और शायद अन्य कार्यान्वयन) में -j तर्क है, जो यह नियंत्रित करता है कि यह कितनी नौकरियों में एक बार चलेंगे। जब कोई काम पूरा हो जाता है, तो एक और शुरू कर देगा।

4

ठीक है, अगर वे एक दूसरे के काफी हद तक स्वतंत्र हैं, मैं करने के मामले में लगता है कि:

Initialize an array of jobs pending (queue, ...) - 200 entries 
Initialize an array of jobs running - empty 

while (jobs still pending and queue of jobs running still has space) 
    take a job off the pending queue 
    launch it in background 
    if (queue of jobs running is full) 
     wait for a job to finish 
     remove from jobs running queue 
while (queue of jobs is not empty) 
    wait for job to finish 
    remove from jobs running queue 

नोट मुख्य पाश में पूंछ परीक्षण का मतलब है कि 'चल नौकरियों कतार' अगर जगह है जब जबकि लूप पुनरावृत्त होता है - लूप की समय-समय पर समाप्त होने से रोकता है। मुझे लगता है कि तर्क ध्वनि है।

मैं देख सकता हूं कि सी में इसे आसानी से कैसे करना है - यह पर्ल में इतना कठिन नहीं होगा, और इसलिए अन्य स्क्रिप्टिंग भाषाओं - पायथन, रूबी, टीसीएल, आदि में बहुत मुश्किल नहीं है)। मुझे पूरा यकीन नहीं है कि मैं इसे खोल में करना चाहता हूं - wait शेल में कमांड सभी बच्चों को समाप्त करने के बजाए, सभी बच्चों को समाप्त करने की प्रतीक्षा करता है।

+0

आप एक विशिष्ट बाल प्रक्रिया के लिए प्रतीक्षा आदेश का भी उपयोग कर सकते हैं। इसे किसी भी तर्क दिया जा सकता है, जिनमें से प्रत्येक एक पिड या नौकरी आईडी हो सकता है। –

+1

@ ब्रायनमिंटन: आप सही हैं कि आप विशिष्ट पीआईडी ​​को 'प्रतीक्षा' के साथ सूचीबद्ध कर सकते हैं, लेकिन आपको अभी भी 'उन सभी मृत' व्यवहार मिलते हैं, न कि 'पहले एक मृत', जो इस कोड को वास्तव में चाहिए। –

42

खोल पर, xargs समानांतर कमांड प्रोसेसिंग कतार में उपयोग किया जा सकता है।उदाहरण के लिए, समानांतर में हमेशा 3 सोता होने, 1 सेकंड प्रत्येक के लिए सो, और कुल में 10 सोता क्रियान्वित करने के लिए

echo {1..10} | xargs -d ' ' -n1 -P3 sh -c 'sleep 1s' _ 

करना और यह कुल 4 सेकंड के लिए सोने के हैं। आप नामों की एक सूची है, और मार डाला, फिर समानांतर में 3 आदेशों को क्रियान्वित करने आदेशों का नाम पास करना चाहते हैं, करते हैं

cat names | xargs -n1 -P3 process_name 

आदेश process_name alice, process_name bob और इतने पर अमल करेंगे।

+0

वाह, मैं हर समय 'xargs' का उपयोग करता हूं और कभी उम्मीद नहीं करता कि यह विकल्प होगा! – Warrick

+0

आपके द्वारा दिए गए दूसरे उदाहरण के लिए, आप कमांड को कैसे संशोधित करते हैं ताकि 'process_name' एक से अधिक तर्क ले सके? मैं ऐसा कुछ करना चाहता हूं: 'cat command.txt | xargs -n1 -P3 eval' जहां 'command.txt' में कमांड का एक गुच्छा है (प्रत्येक पंक्ति पर एक, प्रत्येक एकाधिक तर्क के साथ)। समस्या यह है कि 'eval' काम नहीं करता है क्योंकि यह एक शेल बिल्टिन कमांड – Eddy

3

अजगर में, आप की कोशिश कर सकते:

import Queue, os, threading 

# synchronised queue 
queue = Queue.Queue(0) # 0 means no maximum size 

# do stuff to initialise queue with strings 
# representing os commands 
queue.put('sleep 10') 
queue.put('echo Sleeping..') 
# etc 
# or use python to generate commands, e.g. 
# for username in ['joe', 'bob', 'fred']: 
# queue.put('imapsync %s' % username) 

def go(): 
    while True: 
    try: 
     # False here means no blocking: raise exception if queue empty 
     command = queue.get(False) 
     # Run command. python also has subprocess module which is more 
     # featureful but I am not very familiar with it. 
     # os.system is easy :-) 
     os.system(command) 
    except Queue.Empty: 
     return 

for i in range(10): # change this to run more/fewer threads 
    threading.Thread(target=go).start() 

untested है ...

(बेशक, अजगर स्वयं एकल धागा है। आपको अभी भी वा के संदर्भ में कई धागे का लाभ मिलना चाहिए आईओ के लिए इटिंग, हालांकि।)

+0

1) ओएससिस्टम को नए उन्नत उपप्रोसेसर मॉड्यूल के साथ प्रतिस्थापित किया जा सकता है। 2) इससे कोई फर्क नहीं पड़ता कि सीपीथन में एक जीआईएल है क्योंकि आप बाहरी आदेश चला रहे हैं, पायथन कोड (फ़ंक्शंस) नहीं। –

+0

यदि आप 'multiprocessing.Process' द्वारा 'थ्रेडिंग' थ्रेड 'को बदलते हैं और' मल्टीप्रोसेसिंग। क्यूयू' द्वारा 'कतार' को बदलते हैं तो कोड एकाधिक प्रक्रियाओं का उपयोग करके चलाएगा। – jfs

+0

pssh पायथन में लिखा गया है मुझे लगता है कि – rogerdpack

1

पायथन का multiprocessing module आपकी समस्या को अच्छी तरह फिट करने लगते हैं। यह एक उच्च स्तरीय पैकेज है जो प्रक्रिया द्वारा थ्रेडिंग का समर्थन करता है।

13

इस तरह की नौकरी के लिए पीपीएसएस लिखा गया है: समांतर प्रसंस्करण खोल स्क्रिप्ट। इस नाम के लिए Google और आपको यह मिल जाएगा, मैं लिंक नहीं करूँगा।

+0

हाहा, बढ़िया। litb से वापस greets: पी –

+0

यह आदर्श लग रहा है। अगली बार जब मैं एक समान समस्या का सामना कर रहा हूं तो मैं इसे देख लूंगा। आपकी सिफारिश के साथ इस धागे को अद्यतन करने के लिए धन्यवाद। – mlambie

+0

कमाल! क्या हम इसे गतिशील थ्रेडिंग सेट कर सकते हैं उदा। 80% सीपीयू/राम अनुमति देते हैं? – Devrim

24

Parallel इस उद्देश्य के लिए exatcly बनाया गया है।

cat userlist | parallel imapsync 

अन्य समाधान की तुलना Parallel की सुंदरता की है कि यह सुनिश्चित करें कि उत्पादन नहीं मिलाया जाता है बनाता है। Parallel में traceroute कर उदाहरण के लिए ठीक काम करता है:

(echo foss.org.my; echo www.debian.org; echo www.freenetproject.org) | parallel traceroute 
+1

मैन मुझे इस उपकरण से प्यार है। मैं इसके बारे में 3h की तरह जानता हूं और मैं इसे तब तक उपयोग करने जा रहा हूं जब तक कि धरती के बहुत सारे पत्थरों को रोकने के लिए रोना न पड़े। – chiggsy

+1

फेडोरा 16 में पैकेज भंडार में उपकरण शामिल था – myroslav

0

/tmp में लॉक फ़ाइलों का उपयोग करके 4 से अधिक सबशेल्स में नौकरियों को समानांतर करने के लिए zsh में सरल कार्य।

  • #q:

    केवल गैर तुच्छ हिस्सा पहले टेस्ट में ग्लोब झंडे हैं एक परीक्षण

  • [4] में ग्लोबिंग फ़ाइल नाम सक्षम: 4 परिणाम केवल
  • N रिटर्न: पर त्रुटि को अनदेखा खाली परिणाम

इसे पॉज़िक्स में परिवर्तित करना आसान होना चाहिए, हालांकि यह थोड़ा और वर्बोज होगा।

\" के साथ नौकरियों में किसी भी उद्धरण से बचने के लिए मत भूलना।

#!/bin/zsh 

setopt extendedglob 

para() { 
    lock=/tmp/para_$$_$((paracnt++)) 
    # sleep as long as the 4th lock file exists 
    until [[ -z /tmp/para_$$_*(#q[4]N) ]] { sleep 0.1 } 
    # Launch the job in a subshell 
    (touch $lock ; eval $* ; rm $lock) & 
    # Wait for subshell start and lock creation 
    until [[ -f $lock ]] { sleep 0.001 } 
} 

para "print A0; sleep 1; print Z0" 
para "print A1; sleep 2; print Z1" 
para "print A2; sleep 3; print Z2" 
para "print A3; sleep 4; print Z3" 
para "print A4; sleep 3; print Z4" 
para "print A5; sleep 2; print Z5" 

# wait for all subshells to terminate 
wait