การประมวลผลสคริปต์ Bash มีจำนวนคำสั่งที่ จำกัด ในแบบคู่ขนาน


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 จะไม่ทำอะไรให้ฉันดี


1
waitเป็นคำตอบที่ถูกต้องที่นี่ แต่คุณwhile [ $(ps …จะเขียนได้ดีขึ้นwhile pkill -0 $KEYWORD…- ใช้proctools ... นั่นคือเหตุผลที่ถูกต้องเพื่อตรวจสอบว่ากระบวนการที่มีชื่อเฉพาะยังคงทำงานอยู่หรือไม่
kojiro

ฉันคิดว่าคำถามนี้ควรเปิดใหม่ QA "ที่ซ้ำกันที่เป็นไปได้" คือทั้งหมดที่เกี่ยวกับการรันจำนวนจำกัดของโปรแกรมในแบบคู่ขนาน ชอบ 2-3 คำสั่ง อย่างไรก็ตามคำถามนี้จะเน้นไปที่การใช้คำสั่งในวงวน (ดู "แต่มี 4000 บรรทัด")
VasiliNovikov

@VasyaNovikov คุณอ่าน คำตอบทั้งหมดของคำถามนี้และคำซ้ำทั้งหมดหรือไม่ ทุกคำตอบสำหรับคำถามนี้ที่นี่สามารถพบได้ในคำตอบของคำถามที่ซ้ำกัน นั่นคือคำจำกัดความของคำถามที่ซ้ำกันอย่างแม่นยำ มันทำให้แตกต่างอย่างแน่นอนไม่ว่าคุณจะใช้คำสั่งในวง
robinCTS

@robinCTS มีจุดตัด แต่คำถามก็แตกต่างกัน นอกจากนี้ 6 คำตอบที่ได้รับความนิยมสูงสุดในการจัดการ QA ที่เชื่อมโยงกับ 2 กระบวนการเท่านั้น
VasiliNovikov

2
ฉันขอแนะนำให้เปิดคำถามนี้อีกครั้งเพราะคำตอบของคำถามนั้นชัดเจนกว่าดีกว่าและอัปเกรดสูงกว่าคำตอบของคำถามที่เชื่อมโยงถึงแม้ว่าจะเป็นสามปีที่ผ่านมาก็ตาม
Dan Nissenbaum

คำตอบ:


331

ใช้ในwaitตัว:

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

สำหรับตัวอย่างข้างต้นกระบวนการ 4 process1... process4จะเริ่มในพื้นหลังและเชลล์จะรอจนกว่าจะเสร็จสมบูรณ์ก่อนที่จะเริ่มชุดถัดไป

จากคู่มือ GNU :

wait [jobspec or pid ...]

รอจนกว่ากระบวนการลูกที่ระบุโดยแต่ละ ID กระบวนการ pid หรือ jobpec ข้อมูลจำเพาะงานออกและส่งกลับสถานะการออกของคำสั่งสุดท้ายที่รอ ถ้า spec ของงานได้รับการประมวลผลทั้งหมดในงานจะรอ หากไม่ได้ระบุอาร์กิวเมนต์กระบวนการลูกที่ใช้งานอยู่ในปัจจุบันทั้งหมดจะถูกรอและสถานะการส่งคืนจะเป็นศูนย์ ถ้าไม่ใช่ jobspec หรือ 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
มีวิธีการทำเช่นนี้ในวงหรือไม่?
DomainsFeatured

ฉันได้ลองสิ่งนี้แล้ว แต่ดูเหมือนว่าการมอบหมายตัวแปรที่ทำในหนึ่งบล็อกนั้นไม่มีในบล็อกถัดไป เป็นเพราะพวกเขาเป็นกระบวนการแยกกันหรือไม่ มีวิธีสื่อสารตัวแปรกลับไปยังกระบวนการหลักหรือไม่?
Bobby

97

ดูแบบคู่ขนาน ไวยากรณ์ของมันคล้ายกับxargsแต่มันรันคำสั่งแบบขนาน


13
สิ่งนี้ดีกว่าการใช้waitเนื่องจากจะดูแลการเริ่มงานใหม่เหมือนงานเก่าที่เสร็จสมบูรณ์แทนที่จะรอให้ทั้งชุดเสร็จสิ้นก่อนที่จะเริ่มงานต่อไป
chepner

5
ตัวอย่างเช่นหากคุณมีรายการลิงก์ในไฟล์คุณสามารถทำได้cat list_of_links.txt | parallel -j 4 wget {}ซึ่งจะทำให้การwgetทำงานสี่ครั้งต่อครั้ง
Mr. Llama

5
มีเด็กใหม่ในเมืองที่เรียกว่าเป็นpexecparallelซึ่งเป็นแทน
slashsbin

2
การให้ตัวอย่างจะเป็นประโยชน์มากขึ้น
jterm

1
parallel --jobs 4 < list_of_commands.shโดย list_of_commands.sh เป็นไฟล์ที่มีคำสั่งเดียว (เช่นwget LINK1note ที่ไม่มี&) ในทุกบรรทัด อาจต้องทำCTRL+Zและbgหลังจากปล่อยให้มันทำงานในพื้นหลัง
weiji14

71

ในความเป็นจริงxargs สามารถเรียกใช้คำสั่งแบบขนานสำหรับคุณ มี-P max_procsตัวเลือกบรรทัดคำสั่งพิเศษสำหรับสิ่งนั้น man xargsดู


2
+100 อันนี้ยอดเยี่ยมเพราะมันถูกสร้างขึ้นและใช้งานง่ายมากและสามารถทำได้ในหนึ่งซับ
Clay

เหมาะสำหรับบรรจุภัณฑ์ขนาดเล็กเนื่องจากไม่ต้องการแพ็คเกจ / การอ้างอิงเพิ่มเติม!
Marco Roy

1
ดูคำถามนี้สำหรับตัวอย่าง: stackoverflow.com/questions/28357997/…
Marco Roy

7

คุณสามารถรัน 20 กระบวนการและใช้คำสั่ง:

wait

สคริปต์ของคุณจะรอและดำเนินการต่อเมื่องานพื้นหลังทั้งหมดของคุณเสร็จสิ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.