วิธีรับรายการกระบวนการลูกทั้งหมดที่เกิดจากสคริปต์


10

บริบท:

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

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

หรือประเภทการปิดกั้นที่ไม่ใช่ประเภทที่แยกเด็กกระบวนการในพื้นหลังและออกจากสิ่งที่ชอบ

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

ฉันพยายามทำอะไรให้สำเร็จ

ผู้ใช้ให้สคริปต์สามารถเป็นหนึ่งในสองประเภทข้างต้นหรือผสมกันทั้งสอง งานของฉันคือเรียกใช้สคริปต์และรอจนกว่ากระบวนการทั้งหมดที่เริ่มต้นโดยจะออกจากนั้นปิดโหนด หากเป็นประเภทการบล็อกกรณีง่าย ๆ คือรับ PID ของกระบวนการดำเนินการสคริปต์และรอจนกระทั่ง ps -ef | grep -ef PID ไม่มีรายการอีกต่อไป สคริปต์ที่ไม่มีการบล็อกคือสิ่งที่ทำให้ฉันเดือดร้อน

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


ฉันไม่คิดว่าจะเป็นไปได้หลังจากสคริปต์หลักสิ้นสุดลงจนกว่าคุณจะสามารถจับ PID ของผู้ปกครองได้ หากคุณกำลังเปิดตัวสคริปต์คุณสามารถใช้สคริปต์ห่อหุ้มบางอย่างpid$(foo.sh; echo $!)ที่จะให้ PID แก่foo.shคุณเพื่อให้คุณสามารถใช้งานps --ppidได้ มันจะใช้ได้ไหม
terdon

2
สคริปต์ต้องทำงานภายใต้ UID ของผู้ใช้ผู้แต่งหรือไม่ ถ้าไม่คุณสามารถสร้างผู้ใช้หุ่นจำลองเพื่อจุดประสงค์นี้ได้หรือไม่? คุณจะไม่ต้องแม้แต่เพียงgrep ps –udummy_userดูที่กลุ่มกระบวนการ
Scott

นี่เป็นวิธีแก้ปัญหามากกว่าวิธีแก้ปัญหาสำหรับคำถามเริ่มต้นของคุณ: เปิดเซสชัน bash ใหม่ คุณสามารถแสดงรายการกระบวนการทั้งหมดที่เกิดจากเชลล์นี้โดยใช้psโดยไม่มีข้อโต้แย้งใด ๆ (ควรเป็นเพียงbashและpsในการเริ่มต้น) เริ่มสคริปต์ของคุณที่นั่น หลังจากเสร็จสิ้นรอจนกว่าจะps | wc -lถึงค่าที่คุณคาดหวัง
ทิม

คำตอบ:


8

เพื่อตอบคำถามของคุณโดยตรงคำสั่ง

jobs -p

ให้รายการกระบวนการลูกทั้งหมดให้คุณ

ทางเลือก # 1

แต่ในกรณีของคุณมันอาจจะง่ายกว่าที่จะใช้คำสั่งwaitโดยไม่มีพารามิเตอร์:

first_program &
second_program &
wait

สิ่งนี้จะรอจนกว่ากระบวนการลูกทั้งหมดจะเสร็จสิ้น

ทางเลือก # 2

อีกทางเลือกหนึ่งคือใช้$!เพื่อรับ PID ของโปรแกรมล่าสุดและอาจสะสมในตัวแปรเช่น:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

จากนั้นให้ใช้การรอด้วย (ในกรณีนี้คุณต้องการรอให้กระบวนการย่อยของคุณย่อย):

wait $pids

ทางเลือก # 3

หรือถ้าคุณต้องการรอจนกว่ากระบวนการใด ๆจะเสร็จสิ้นคุณสามารถใช้

wait -n $pids

ข้อมูลโบนัส

หากคุณต้องการ sigterm ในสคริปต์ bash ของคุณเพื่อปิดกระบวนการลูกของคุณเช่นกันคุณจะต้องเผยแพร่สัญญาณด้วยสิ่งนี้ (วางที่ใดที่หนึ่งที่ด้านบนก่อนที่จะเริ่มกระบวนการใด ๆ ):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT

1

ขอบคุณมากสำหรับคำตอบของคุณ .. ฉันได้รับคำตอบจาก stackoverflow

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

(source userscript; wait)

การจัดหาสคริปต์ใน subshell ชัดเจนควรจำลองการเริ่มกระบวนการใหม่อย่างใกล้ชิดพอ หากไม่เป็นเช่นนั้นคุณสามารถสร้างพื้นหลังของเชลล์ย่อยซึ่งบังคับให้กระบวนการใหม่เริ่มต้นจากนั้นรอให้กระบวนการนั้นเสร็จสิ้น

(source userscript; wait) & wait

นี่คือลิงค์สำหรับคำตอบดั้งเดิมโดย @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969


3
ฉันคิดเกี่ยวกับเรื่องนี้เช่นกัน แต่วิธีนี้จะล้มเหลวเมื่อuserscriptเริ่มตัวห้อยในพื้นหลังซึ่งเริ่มสคริปต์อื่นในพื้นหลัง waitคำสั่งของคุณจะรอให้เด็ก ๆ ของuserscriptแต่ไม่ใช่หลานของมัน
Tim

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