ขนานสคริปต์ Bash ด้วยจำนวนกระบวนการสูงสุด


87

ให้บอกว่าฉันมีวงใน Bash:

for foo in `some-command`
do
   do-something $foo
done

do-somethingซีพียูถูกผูกไว้และฉันมีโปรเซสเซอร์ 4 คอร์ที่ดี ฉันต้องการที่จะสามารถวิ่งได้ถึง 4 do-somethingครั้งในครั้งเดียว

แนวทางที่ไร้เดียงสาดูเหมือนจะ:

for foo in `some-command`
do
   do-something $foo &
done

สิ่งนี้จะทำงานทั้งหมด do-somethingพร้อมกัน แต่มีข้อเสียอยู่สองสามประการโดยส่วนใหญ่การทำบางอย่างอาจมี I / O ที่สำคัญบางอย่างซึ่งการทำงานทั้งหมดในครั้งเดียวอาจช้าลงเล็กน้อย ปัญหาอื่น ๆ คือบล็อกโค้ดนี้จะส่งคืนทันทีดังนั้นจึงไม่มีวิธีทำงานอื่น ๆ เมื่อdo-somethingเสร็จสิ้นทั้งหมด

คุณจะเขียนลูปนี้อย่างไรเพื่อให้ X do-somethings ทำงานพร้อมกันเสมอ?


2
ในฐานะที่เป็น sidenode ฉันใฝ่ฝันที่จะเพิ่มตัวเลือก make's -j ให้กับ bash สำหรับแบบดั้งเดิม มันจะไม่ได้ผลเสมอไป แต่สำหรับบางกรณีง่ายๆที่คุณรู้ว่า body ของลูปกำลังจะทำบางสิ่งที่ไม่เหมือนใครสำหรับการวนซ้ำแต่ละครั้งการพูดว่า "สำหรับ -j 4 ... " นั้นค่อนข้างชัดเจน
ผ่อนคลายใน

1
อ้างอิงโยงไปที่stackoverflow.com/questions/1537956/…สำหรับโซลูชัน bash ซึ่งช่วยลดปัญหาด้านประสิทธิภาพและช่วยให้สามารถจัดกลุ่มของกระบวนการย่อยแยกกันได้
paxdiablo

1
ฉันขอแนะนำวิธีแก้ปัญหาของฉันstackoverflow.com/a/28965927/340581
Tuttle

คำตอบ:


63

ขึ้นอยู่กับสิ่งที่คุณต้องการทำ xargs สามารถช่วยได้ (ที่นี่: การแปลงเอกสารด้วย pdf2ps):

cpus=$( ls -d /sys/devices/system/cpu/cpu[[:digit:]]* | wc -w )

find . -name \*.pdf | xargs --max-args=1 --max-procs=$cpus  pdf2ps

จากเอกสาร:

--max-procs=max-procs
-P max-procs
       Run up to max-procs processes at a time; the default is 1.
       If max-procs is 0, xargs will run as many processes as  possible  at  a
       time.  Use the -n option with -P; otherwise chances are that only one
       exec will be done.

9
ในความคิดของฉันวิธีนี้เป็นวิธีที่สง่างามที่สุด ยกเว้นตั้งแต่ฉันหวาดระแวงผมมักจะชอบที่จะใช้และfind [...] -print0 xargs -0
ยาบ้า

7
cpus=$(getconf _NPROCESSORS_ONLN)
mr.spuratic

1
จากคู่มือทำไมไม่ใช้--max-procs=0เพื่อให้ได้กระบวนการมากที่สุด
EverythingRightPlace

@EverythingRightPlace คำถามนี้ขออย่างชัดเจนว่าไม่มีกระบวนการใดมากไปกว่าโปรเซสเซอร์ที่มีอยู่ --max-procs=0เป็นเหมือนความพยายามของผู้ถาม (เริ่มต้นกระบวนการให้มากที่สุดเท่าที่ข้อโต้แย้ง)
Toby Speight

39

ด้วย GNU Parallel http://www.gnu.org/software/parallel/คุณสามารถเขียน:

some-command | parallel do-something

GNU Parallel ยังรองรับการรันงานบนคอมพิวเตอร์ระยะไกล การดำเนินการนี้จะเรียกใช้หนึ่งคอร์ต่อ CPU บนคอมพิวเตอร์ระยะไกลแม้ว่าจะมีจำนวนคอร์ที่แตกต่างกัน:

some-command | parallel -S server1,server2 do-something

ตัวอย่างขั้นสูงเพิ่มเติม: ที่นี่เราแสดงรายการไฟล์ที่เราต้องการให้ my_script ทำงาน ไฟล์มีนามสกุล (อาจเป็น. jpeg) เราต้องการให้เอาต์พุตของ my_script ติดกับไฟล์ใน basename.out (เช่น foo.jpeg -> foo.out) เราต้องการเรียกใช้ my_script หนึ่งครั้งสำหรับแต่ละคอร์ที่คอมพิวเตอร์มีและเราต้องการเรียกใช้บนคอมพิวเตอร์ในระบบด้วย สำหรับคอมพิวเตอร์ระยะไกลเราต้องการให้ไฟล์ประมวลผลโอนไปยังคอมพิวเตอร์ที่กำหนด เมื่อ my_script เสร็จสิ้นเราต้องการให้ foo.out โอนกลับจากนั้นเราต้องการลบ foo.jpeg และ foo.out ออกจากคอมพิวเตอร์ระยะไกล:

cat list_of_files | \
parallel --trc {.}.out -S server1,server2,: \
"my_script {} > {.}.out"

GNU Parallel ทำให้แน่ใจว่าเอาต์พุตจากแต่ละงานไม่ผสมกันดังนั้นคุณสามารถใช้เอาต์พุตเป็นอินพุตสำหรับโปรแกรมอื่นได้:

some-command | parallel do-something | postprocess

ดูวิดีโอสำหรับตัวอย่างเพิ่มเติม: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


1
โปรดทราบว่าสิ่งนี้มีประโยชน์มากเมื่อใช้findคำสั่งในการสร้างรายการไฟล์เพราะไม่เพียง แต่ป้องกันปัญหาเมื่อมีช่องว่างภายในชื่อไฟล์ที่เกิดขึ้นfor i in ...; doเท่านั้น แต่ยังพบว่าfind -name \*.extension1 -or -name \*.extension2GNU parallel {.} สามารถจัดการได้ดีมาก
Leo Izen

บวก 1 แม้ว่าcatแน่นอนว่าไม่มีประโยชน์
tripleee

@tripleee Re: การใช้แมวอย่างไร้ประโยชน์ ดูoletange.blogspot.dk/2013/10/useless-use-of-cat.html
Ole Tange

โอ้คุณ! อนึ่งคุณช่วยอัปเดตลิงก์ในบล็อกนั้นได้ไหม ตำแหน่ง partmaps.org ตายไปแล้วอย่างน่าเสียดาย แต่ตัวเปลี่ยนเส้นทาง Iki ควรทำงานต่อไป
tripleee

22
maxjobs = 4
ขนาน () {
        ในขณะที่ [$ # -gt 0]; ทำ
                jobcnt = (`งาน -p`)
                ถ้า [$ {# jobcnt [@]} -lt $ maxjobs]; แล้ว
                        ทำอะไร $ 1 &
                        กะ  
                อื่น
                        นอนหลับ 1
                fi
        เสร็จแล้ว
        รอ
}

ขนาน arg1 arg2 "5 args กับงานที่สาม" arg4 ...

10
ตระหนักดีว่ามีการพูดน้อยอย่างจริงจังเกิดขึ้นที่นี่ดังนั้นงานใด ๆ ที่ต้องการช่องว่างในการโต้แย้งจะล้มเหลวอย่างรุนแรง ยิ่งไปกว่านั้นสคริปต์นี้จะกิน CPU ของคุณในขณะที่รอให้งานบางอย่างเสร็จสิ้นหากมีการร้องของานมากกว่าที่ maxjobs อนุญาต
lhunath

1
นอกจากนี้โปรดทราบว่าสิ่งนี้ถือว่าสคริปต์ของคุณไม่ได้ทำสิ่งอื่นใดที่เกี่ยวข้องกับงาน ถ้าคุณเป็นเช่นนั้นก็จะนับสิ่งเหล่านั้นใน maxjobs เช่นกัน
lhunath

1
คุณอาจต้องการใช้ "jobs -pr" เพื่อ จำกัด เฉพาะงานที่กำลังทำงานอยู่
ยาบ้า

1
เพิ่มคำสั่ง sleep เพื่อป้องกันไม่ให้ while loop ทำซ้ำโดยไม่หยุดพักขณะที่รอให้คำสั่ง do-something ทำงานเสร็จแล้ว มิฉะนั้นลูปนี้จะใช้แกน CPU ตัวใดตัวหนึ่งเป็นหลัก สิ่งนี้ยังกล่าวถึงความกังวลของ @lhunath
euphoria83

12

นี่เป็นทางเลือกอื่นที่สามารถแทรกลงใน. bashrc และใช้สำหรับซับในทุกวัน:

function pwait() {
    while [ $(jobs -p | wc -l) -ge $1 ]; do
        sleep 1
    done
}

ในการใช้งานสิ่งที่ต้องทำคือวางไว้&หลังงานและการโทรแบบ pwait พารามิเตอร์จะให้จำนวนกระบวนการคู่ขนาน:

for i in *; do
    do_something $i &
    pwait 10
done

มันจะดีกว่าที่จะใช้waitแทนที่จะยุ่งกับการรอผลลัพธ์ของjobs -pแต่ดูเหมือนจะไม่มีวิธีแก้ปัญหาที่ชัดเจนในการรอจนกว่างานใด ๆ ที่กำหนดจะเสร็จสิ้นแทนที่จะเป็นงานทั้งหมด


11

แทนที่จะใช้ทุบตีธรรมดาให้ใช้ Makefile จากนั้นระบุจำนวนงานพร้อมกันโดยmake -jXที่ X คือจำนวนงานที่จะรันพร้อมกัน

หรือคุณสามารถใช้wait(" man wait"): เรียกใช้กระบวนการย่อยหลาย ๆ กระบวนการเรียกwait- มันจะออกเมื่อกระบวนการย่อยเสร็จสิ้น

maxjobs = 10

foreach line in `cat file.txt` {
 jobsrunning = 0
 while jobsrunning < maxjobs {
  do job &
  jobsrunning += 1
 }
wait
}

job ( ){
...
}

หากคุณต้องการจัดเก็บผลลัพธ์ของงานให้กำหนดผลลัพธ์ให้กับตัวแปร หลังจากที่waitคุณตรวจสอบว่าตัวแปรมีอะไรบ้าง


1
ขอบคุณสำหรับสิ่งนี้แม้ว่าโค้ดจะยังไม่เสร็จ แต่ก็ให้คำตอบสำหรับปัญหาที่ฉันพบในที่ทำงาน
gerikson

ปัญหาเดียวคือถ้าคุณฆ่าสคริปต์เบื้องหน้า (อันที่มีลูป) งานที่กำลังดำเนินอยู่จะไม่ถูกฆ่าด้วยกัน
Girardi

8

อาจลองใช้ยูทิลิตี้แบบขนานแทนการเขียนลูปใหม่? ฉันเป็นแฟนตัวยงของ xjobs ฉันใช้ xjobs ตลอดเวลาเพื่อคัดลอกไฟล์จำนวนมากในเครือข่ายของเราโดยปกติเมื่อตั้งค่าเซิร์ฟเวอร์ฐานข้อมูลใหม่ http://www.maier-komor.de/xjobs.html


7

หากคุณคุ้นเคยกับmakeคำสั่งส่วนใหญ่คุณสามารถแสดงรายการคำสั่งที่คุณต้องการเรียกใช้เป็น makefile ได้ ตัวอย่างเช่นหากคุณต้องการเรียกใช้ $ SOME_COMMAND บนไฟล์ * .input ซึ่งแต่ละไฟล์จะสร้าง * .output คุณสามารถใช้ makefile

INPUT = a. อินพุต b. อินพุต
เอาท์พุท = $ (INPUT: .input = .output)

% .output:% .input
    $ (SOME_COMMAND) $ <$ @

ทั้งหมด: $ (OUTPUT)

จากนั้นก็เรียกใช้

ทำ -j <NUMBER>

เพื่อเรียกใช้พร้อมกันได้สูงสุด NUMBER คำสั่ง


6

ในขณะที่ทำตรงbashนี้อาจเป็นไปไม่ได้ แต่คุณสามารถทำกึ่งขวาได้อย่างง่ายดาย bstarkให้การประมาณอย่างยุติธรรม แต่เขามีข้อบกพร่องดังต่อไปนี้:

  • การแบ่งคำ: คุณไม่สามารถส่งผ่านงานใด ๆ ไปยังงานที่ใช้อักขระใด ๆ ต่อไปนี้ในอาร์กิวเมนต์ของพวกเขา: ช่องว่างแท็บบรรทัดใหม่ดาวเครื่องหมายคำถาม หากคุณทำสิ่งต่างๆจะพังทลายโดยไม่คาดคิด
  • มันขึ้นอยู่กับส่วนที่เหลือของสคริปต์ของคุณเพื่อไม่ให้พื้นหลังอะไรเลย หากคุณเพิ่มหรือในภายหลังคุณเพิ่มบางสิ่งบางอย่างลงในสคริปต์ที่ถูกส่งในพื้นหลังเนื่องจากคุณลืมว่าคุณไม่ได้รับอนุญาตให้ใช้งานเบื้องหลังเนื่องจากข้อมูลโค้ดของเขาสิ่งต่างๆจะพัง

การประมาณอื่นที่ไม่มีข้อบกพร่องเหล่านี้มีดังต่อไปนี้:

scheduleAll() {
    local job i=0 max=4 pids=()

    for job; do
        (( ++i % max == 0 )) && {
            wait "${pids[@]}"
            pids=()
        }

        bash -c "$job" & pids+=("$!")
    done

    wait "${pids[@]}"
}

โปรดทราบว่าสิ่งนี้สามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อตรวจสอบรหัสออกของแต่ละงานเมื่อสิ้นสุดลงเพื่อให้คุณสามารถเตือนผู้ใช้หากงานล้มเหลวหรือตั้งรหัสออกscheduleAllตามจำนวนงานที่ล้มเหลวหรือบางอย่าง

ปัญหาเกี่ยวกับรหัสนี้มีเพียง:

  • มันกำหนดเวลางานสี่งาน (ในกรณีนี้) ในแต่ละครั้งจากนั้นรอให้ทั้งสี่งานสิ้นสุดลง งานบางอย่างอาจเสร็จเร็วกว่างานอื่นซึ่งจะทำให้งานสี่ชุดถัดไปต้องรอจนกว่างานชุดก่อนหน้าจะนานที่สุด

โซลูชันที่ดูแลปัญหาสุดท้ายนี้จะต้องใช้kill -0เพื่อสำรวจความคิดเห็นว่ามีกระบวนการใดหายไปแทนที่จะเป็นwaitและกำหนดเวลางานถัดไป อย่างไรก็ตามนั่นทำให้เกิดปัญหาใหม่เล็กน้อย: คุณมีสภาพการแข่งขันระหว่างการสิ้นสุดของงานและการkill -0ตรวจสอบว่าสิ้นสุดหรือไม่ หากงานสิ้นสุดลงและกระบวนการอื่นในระบบของคุณเริ่มต้นขึ้นพร้อมกันโดยใช้ PID แบบสุ่มซึ่งเกิดขึ้นกับงานที่เพิ่งทำเสร็จkill -0จะไม่สังเกตเห็นว่างานของคุณเสร็จสิ้นและสิ่งต่างๆจะพังอีกครั้ง

ไม่สามารถหาทางออกที่สมบูรณ์แบบได้ในbash.


3

ฟังก์ชันสำหรับทุบตี:

parallel ()
{
    awk "BEGIN{print \"all: ALL_TARGETS\\n\"}{print \"TARGET_\"NR\":\\n\\t@-\"\$0\"\\n\"}END{printf \"ALL_TARGETS:\";for(i=1;i<=NR;i++){printf \" TARGET_%d\",i};print\"\\n\"}" | make $@ -f - all
}

ใช้:

cat my_commands | parallel -j 4

การใช้งานmake -jเป็นไปอย่างชาญฉลาด แต่ไม่มีคำอธิบายใด ๆ และไม่มีรหัส Awk แบบเขียนอย่างเดียวทำให้ฉันละเว้นจากการโหวต
tripleee

2

โปรเจ็กต์ที่ฉันทำงานอยู่ใช้คำสั่งwaitเพื่อควบคุมกระบวนการเชลล์คู่ขนาน (ksh จริง) เพื่อจัดการกับข้อกังวลของคุณเกี่ยวกับ IO บนระบบปฏิบัติการสมัยใหม่การดำเนินการแบบคู่ขนานจะช่วยเพิ่มประสิทธิภาพได้จริง หากกระบวนการทั้งหมดกำลังอ่านบล็อกเดียวกันบนดิสก์กระบวนการแรกเท่านั้นที่จะต้องเข้าสู่ฮาร์ดแวร์จริง กระบวนการอื่น ๆ มักจะสามารถดึงบล็อกจากแคชดิสก์ของ OS ในหน่วยความจำได้ เห็นได้ชัดว่าการอ่านจากหน่วยความจำนั้นมีขนาดที่เร็วกว่าการอ่านจากดิสก์หลายเท่า นอกจากนี้ผลประโยชน์ไม่จำเป็นต้องมีการเปลี่ยนแปลงการเข้ารหัส


1

สิ่งนี้อาจดีพอสำหรับวัตถุประสงค์ส่วนใหญ่ แต่ไม่เหมาะสม

#!/bin/bash

n=0
maxjobs=10

for i in *.m4a ; do
    # ( DO SOMETHING ) &

    # limit jobs
    if (( $(($((++n)) % $maxjobs)) == 0 )) ; then
        wait # wait until all have finished (not optimal, but most times good enough)
        echo $n wait
    fi
done

1

นี่คือวิธีที่ฉันจัดการเพื่อแก้ปัญหานี้ในสคริปต์ทุบตี:

 #! /bin/bash

 MAX_JOBS=32

 FILE_LIST=($(cat ${1}))

 echo Length ${#FILE_LIST[@]}

 for ((INDEX=0; INDEX < ${#FILE_LIST[@]}; INDEX=$((${INDEX}+${MAX_JOBS})) ));
 do
     JOBS_RUNNING=0
     while ((JOBS_RUNNING < MAX_JOBS))
     do
         I=$((${INDEX}+${JOBS_RUNNING}))
         FILE=${FILE_LIST[${I}]}
         if [ "$FILE" != "" ];then
             echo $JOBS_RUNNING $FILE
             ./M22Checker ${FILE} &
         else
             echo $JOBS_RUNNING NULL &
         fi
         JOBS_RUNNING=$((JOBS_RUNNING+1))
     done
     wait
 done

1

มาปาร์ตี้ที่นี่สายจริงๆแต่นี่เป็นอีกวิธีแก้ปัญหา

โซลูชันจำนวนมากไม่จัดการช่องว่าง / อักขระพิเศษในคำสั่งอย่าให้งาน N ทำงานตลอดเวลากินซีพียูในลูปที่ไม่ว่างหรือพึ่งพาการอ้างอิงภายนอก (เช่น GNU parallel)

ด้วยแรงบันดาลใจในการจัดการกระบวนการที่ตายแล้ว / ซอมบี้นี่คือโซลูชันทุบตีที่แท้จริง:

function run_parallel_jobs {
    local concurrent_max=$1
    local callback=$2
    local cmds=("${@:3}")
    local jobs=( )

    while [[ "${#cmds[@]}" -gt 0 ]] || [[ "${#jobs[@]}" -gt 0 ]]; do
        while [[ "${#jobs[@]}" -lt $concurrent_max ]] && [[ "${#cmds[@]}" -gt 0 ]]; do
            local cmd="${cmds[0]}"
            cmds=("${cmds[@]:1}")

            bash -c "$cmd" &
            jobs+=($!)
        done

        local job="${jobs[0]}"
        jobs=("${jobs[@]:1}")

        local state="$(ps -p $job -o state= 2>/dev/null)"

        if [[ "$state" == "D" ]] || [[ "$state" == "Z" ]]; then
            $callback $job
        else
            wait $job
            $callback $job $?
        fi
    done
}

และตัวอย่างการใช้งาน:

function job_done {
    if [[ $# -lt 2 ]]; then
        echo "PID $1 died unexpectedly"
    else
        echo "PID $1 exited $2"
    fi
}

cmds=( \
    "echo 1; sleep 1; exit 1" \
    "echo 2; sleep 2; exit 2" \
    "echo 3; sleep 3; exit 3" \
    "echo 4; sleep 4; exit 4" \
    "echo 5; sleep 5; exit 5" \
)

# cpus="$(getconf _NPROCESSORS_ONLN)"
cpus=3
run_parallel_jobs $cpus "job_done" "${cmds[@]}"

ผลลัพธ์:

1
2
3
PID 56712 exited 1
4
PID 56713 exited 2
5
PID 56714 exited 3
PID 56720 exited 4
PID 56724 exited 5

สำหรับการจัดการเอาต์พุตต่อกระบวนการ$$สามารถใช้เพื่อล็อกไฟล์ตัวอย่างเช่น:

function job_done {
    cat "$1.log"
}

cmds=( \
    "echo 1 \$\$ >\$\$.log" \
    "echo 2 \$\$ >\$\$.log" \
)

run_parallel_jobs 2 "job_done" "${cmds[@]}"

เอาท์พุต:

1 56871
2 56872

0

คุณสามารถใช้การซ้อนอย่างง่ายสำหรับลูป (แทนจำนวนเต็มที่เหมาะสมสำหรับ N และ M ด้านล่าง):

for i in {1..N}; do
  (for j in {1..M}; do do_something; done & );
done

สิ่งนี้จะดำเนินการ do_something N * M ครั้งในรอบ M โดยแต่ละรอบจะดำเนินการ N งานควบคู่กันไป คุณสามารถทำให้ N เท่ากับจำนวน CPU ที่คุณมี


0

วิธีแก้ปัญหาของฉันในการทำให้กระบวนการจำนวนหนึ่งทำงานอยู่เสมอติดตามข้อผิดพลาดและจัดการกับกระบวนการที่ไม่สามารถป้องกันได้ / ซอมบี้:

function log {
    echo "$1"
}

# Take a list of commands to run, runs them sequentially with numberOfProcesses commands simultaneously runs
# Returns the number of non zero exit codes from commands
function ParallelExec {
    local numberOfProcesses="${1}" # Number of simultaneous commands to run
    local commandsArg="${2}" # Semi-colon separated list of commands

    local pid
    local runningPids=0
    local counter=0
    local commandsArray
    local pidsArray
    local newPidsArray
    local retval
    local retvalAll=0
    local pidState
    local commandsArrayPid

    IFS=';' read -r -a commandsArray <<< "$commandsArg"

    log "Runnning ${#commandsArray[@]} commands in $numberOfProcesses simultaneous processes."

    while [ $counter -lt "${#commandsArray[@]}" ] || [ ${#pidsArray[@]} -gt 0 ]; do

        while [ $counter -lt "${#commandsArray[@]}" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do
            log "Running command [${commandsArray[$counter]}]."
            eval "${commandsArray[$counter]}" &
            pid=$!
            pidsArray+=($pid)
            commandsArrayPid[$pid]="${commandsArray[$counter]}"
            counter=$((counter+1))
        done


        newPidsArray=()
        for pid in "${pidsArray[@]}"; do
            # Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :)
            if kill -0 $pid > /dev/null 2>&1; then
                pidState=$(ps -p$pid -o state= 2 > /dev/null)
                if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then
                    newPidsArray+=($pid)
                fi
            else
                # pid is dead, get it's exit code from wait command
                wait $pid
                retval=$?
                if [ $retval -ne 0 ]; then
                    log "Command [${commandsArrayPid[$pid]}] failed with exit code [$retval]."
                    retvalAll=$((retvalAll+1))
                fi
            fi
        done
        pidsArray=("${newPidsArray[@]}")

        # Add a trivial sleep time so bash won't eat all CPU
        sleep .05
    done

    return $retvalAll
}

การใช้งาน:

cmds="du -csh /var;du -csh /tmp;sleep 3;du -csh /root;sleep 10; du -csh /home"

# Execute 2 processes at a time
ParallelExec 2 "$cmds"

# Execute 4 processes at a time
ParallelExec 4 "$cmds"

-1

$ DOMAINS = "list of some domain in command" สำหรับ foo in some-command do

eval `some-command for $DOMAINS` &

    job[$i]=$!

    i=$(( i + 1))

เสร็จแล้ว

Ndomains =echo $DOMAINS |wc -w

สำหรับ i ใน $ (seq 1 1 $ Ndomains) ทำ echo "wait for $ {job [$ i]}" wait "$ {job [$ i]}" เสร็จสิ้น

ในแนวคิดนี้จะใช้ได้กับการขนานกัน สิ่งสำคัญคือบรรทัดสุดท้ายของ eval คือ '&' ซึ่งจะทำให้คำสั่งเป็นพื้นหลัง

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