เชลล์สคริปต์รอคำสั่งพื้นหลัง


12

ฉันกำลังเขียนสคริปต์ แต่มีบางสิ่งที่ฉันต้องการฉันไม่สามารถหาวิธีที่จะทำ ...

ฉันต้องสร้างคำสั่งในพื้นหลัง "command1 &" จากนั้นบางส่วนในสคริปต์ฉันต้องรอให้เสร็จก่อนที่ฉันจะ command2 โดยทั่วไปฉันต้องการสิ่งนี้:

หมายเหตุ: แต่ละคำสั่งจะทำงานในไดเรกทอรีเฉพาะ! ในตอนท้ายของ while ในขณะที่ command1 ของฉันสร้าง 4 ไดเร็กตอรี่, ซึ่งแต่ละอันรันโพรเซสเฉพาะ, ดังนั้นจำนวนโพรเซสที่กำลังทำงานอยู่คือ 4

a=1

while [$a -lt 4 ]

     . command1
   #Generates 1 Process  

     a= `export $a +1`
done

   #Wait until the 4 process end and then run the command2 

    . command2

ฉันเห็นบางสิ่งเกี่ยวกับwaitคำสั่งด้วยหมายเลขกระบวนการ pid แต่นั่นก็ไม่ได้ผล


คุณควบคุมcommand1หรือไม่ คุณสามารถแก้ไขได้เพื่อที่จะส่งคืน PID ของกระบวนการ 4 หรือไม่?
terdon

ใช่ ฉันมีอยู่แล้ว :)
Joao Macau

ฉันได้ปรับปรุงคำตอบของฉันแล้ว บอกฉันว่าตรงกับสิ่งที่คุณสงสัยหรือไม่
Laurent C.

Q นี้จะเกี่ยวข้องกับคนนี้: unix.stackexchange.com/questions/100801/... ข้อแตกต่างคือคุณต้องได้รับ PID จากกระบวนการที่อยู่เบื้องหลัง คุณสามารถใช้$!ตัวแปรเพื่อรับสิ่งนี้ส่งผ่านไปยังwaitคำสั่งตามที่ฉันแสดงให้เห็น $!มี PID ที่พื้นหลังล่าสุดในขณะที่$$มี PID ของกระบวนการทำงานล่าสุด
slm

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

คำตอบ:


22

คุณสามารถใช้คำสั่งwait PIDเพื่อรอให้กระบวนการสิ้นสุด

คุณสามารถดึงข้อมูล PID ของคำสั่งสุดท้ายด้วย $!

ในกรณีของคุณสิ่งนี้จะได้ผล:

command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended

การติดตามการแก้ไขของคุณเนื่องจากคุณมี PID หลายตัวและคุณรู้จักพวกเขาคุณสามารถทำได้:

command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended

ติดตามการแก้ไขของคุณหากคุณรู้จัก PID ที่สร้างขึ้น (xxxxx, yyyyy, xxyyy, yyxxx) คุณสามารถใช้การรอได้เช่นกันด้วยรายการ PID ที่จะรอ (ดูคน) หากคุณไม่รู้จักพวกเขาบางทีคุณอาจรวบรวมพวกเขาเป็น command1 (อะไรคือ command1 สคริปต์ของคุณเอง?)
Laurent C.

อาจดีที่สุดเพื่อให้แน่ใจว่าพวกเขากำลังจัดกลุ่มอย่างถูกต้องตั้งแต่แรก ดูคำตอบของฉันสำหรับความคิดของวิธีอาจทำ
mikeserv

4

วิธีที่สะอาดการทำเช่นนี้จะมีคุณcomamnd1กลับมา PIDs ของกระบวนการเปิดตัวและการใช้waitในแต่ละของพวกเขาตามที่แนะนำโดย @ LaurentC ของคำตอบ

แนวทางอื่นจะเป็นดังนี้:

## Create a log file
logfile=$(mktemp)

## Run your command and have it print into the log file
## when it's finsihed.
command1 && echo 1 > $logfile &

## Wait for it. The [ ! -s $logfile ] is true while the file is 
## empty. The -s means "check that the file is NOT empty" so ! -s
## means the opposite, check that the file IS empty. So, since
## the command above will print into the file as soon as it's finished
## this loop will run as long as  the previous command si runnning.
while [ ! -s $logfile ]; do sleep 1; done

## continue
command2

ขอโทษ แต่ก็ยังไม่ทำงาน .. ฉันจะปรับปรุงคำถามของฉันอีกครั้ง!
Joao Macau

0

หากคุณใช้วิธีการต่อไปนี้คุณอาจไม่จำเป็นต้องมี "การรอให้กระบวนการทั้งหมด" พิเศษหลังจากลูป while การวนซ้ำจะรอให้กระแสcommand1เสร็จสมบูรณ์ก่อนที่จะวนกลับไปด้านบน โปรดใช้ความระมัดระวังเช่นเดียวกับคำแนะนำใด ๆ แจ้งให้ทราบล่วงหน้ามีเพียงสิ่งเดียวที่ฉันไม่ได้เพิ่มที่ส่วนท้ายของคุณ& wait $!command1

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.