ประมวลผลลูกหลาน


20

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

คุณสมบัติที่สำคัญที่ฉันตามมาคือเมื่อฉันฆ่าตู้คอนเทนเนอร์ทุกอย่างที่ได้รับมาจากกระบอกไม้ไผ่ควรจะถูกฆ่า ไม่เพียง แต่กำกับดูแลลูกหลาน แต่รวมถึงลูกหลานด้วย

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

ฉันเชื่อว่าสิ่งที่ฉันต้องการจะประสบความสำเร็จเพราะเมื่อคุณปิด xterm สิ่งใดก็ตามที่ทำงานอยู่ภายในมันจะถูกฆ่าเว้นแต่ว่ามันจะไม่เป็นเช่นนั้น ซึ่งรวมถึงกระบวนการที่ถูกโยงถึง นั่นคือสิ่งที่ฉันต้องการสร้างใหม่

ฉันมีความคิดว่าสิ่งที่ฉันกำลังพูดถึงเกี่ยวข้องกับเซสชันของยูนิกซ์

หากมีวิธีที่เชื่อถือได้ในการระบุการสืบทอดทั้งหมดของกระบวนการมันจะมีประโยชน์ที่จะสามารถส่งสัญญาณตามอำเภอใจได้เช่นกัน เช่น SIGUSR1


ทีนี้การฆ่าโพรเซสแม่ก็ส่งSIGHUPไปยังโพรเซสลูกโดยตรง ตัวจัดการค่าเริ่มต้นของสัญญาณวางสายจะยกเลิกการประมวลผลกระบวนการดังนั้นเส้นทางเริ่มต้นคือการฆ่าผู้สืบทอดทั้งหมด อ่านเพิ่มเติมเกี่ยวกับกระบวนการและกลุ่มกระบวนการ
alex

การปิด xterm ฆ่าทุกสิ่งที่เกิดใน xterm เพราะ TTY ถูกทำลาย หากคุณสามารถหาวิธีในการสร้าง TTY ที่กระบวนการลูกสามารถใช้คุณสามารถทำลาย TTY และทำสิ่งเดียวกันให้สำเร็จ กระบวนการใด ๆ ที่ไม่ได้ปิด TTY (nohup & เพื่อน) จะได้รับ SIGHUP
Patrick

คำตอบ:


23

หากคุณส่งสัญญาณไปยังกระบวนการกระบวนการนั้นจะถูกฆ่า ฉันสงสัยว่าข่าวลือที่ว่าการฆ่ากระบวนการนั้นยังฆ่ากระบวนการอื่น ๆ ได้เริ่มขึ้นแล้ว

อย่างไรก็ตามมีวิธีฆ่ามากกว่าหนึ่งกระบวนการ แต่คุณจะไม่ส่งสัญญาณไปยังกระบวนการเดียว คุณสามารถฆ่ากลุ่มกระบวนการทั้งหมดได้โดยส่งสัญญาณไปที่ -1234 โดยที่ 1234 คือ PGID (ID กลุ่มกระบวนการ) ซึ่งเป็น PID ของผู้นำกลุ่มกระบวนการ เมื่อคุณเรียกใช้ไปป์ไลน์ไปป์ไลน์ทั้งหมดเริ่มต้นจากกลุ่มกระบวนการ (แอปพลิเคชันอาจเปลี่ยนแปลงได้โดยการโทรsetpgidหรือsetpgrp)

เมื่อคุณเริ่มกระบวนการในพื้นหลัง ( foo &) พวกเขาจะอยู่ในกลุ่มกระบวนการของตัวเอง กลุ่มกระบวนการใช้เพื่อจัดการการเข้าถึงเทอร์มินัล โดยปกติกลุ่มกระบวนการพื้นหน้าเท่านั้นที่สามารถเข้าถึงเทอร์มินัล งานพื้นหลังยังคงอยู่ในเซสชันเดียวกันแต่ไม่มีสิ่งอำนวยความสะดวกในการฆ่าเซสชันทั้งหมดหรือแม้แต่ระบุกลุ่มกระบวนการหรือกระบวนการในเซสชันดังนั้นจึงไม่ได้ช่วยอะไรมากนัก

เมื่อคุณปิดขั้วเมล็ดจะส่งสัญญาณSIGHUPไปยังกระบวนการทั้งหมดที่มีว่าเป็นของสถานีควบคุม กระบวนการเหล่านี้สร้างเซสชันแต่ไม่ใช่ทุกเซสชันที่มีเทอร์มินัลการควบคุม สำหรับโครงการของคุณเป็นไปได้ดังนั้นจึงเป็นเรื่องที่จะเริ่มต้นกระบวนการทั้งหมดใน terminal ของตัวเองที่สร้างขึ้นโดยสคริปต์ , หน้าจอฯลฯ ฆ่ากระบวนการจำลอง terminal จะฆ่ากระบวนการที่มีอยู่ (สมมติว่าพวกเขายังไม่ได้ถอนตัวด้วยsetsid)

คุณสามารถให้ความโดดเดี่ยวมากขึ้นโดยการใช้กระบวนการเป็นผู้ใช้ของตัวเองที่ไม่ได้ทำอะไรเลย จากนั้นก็ง่ายที่จะฆ่ากระบวนการทั้งหมด: เรียกใช้kill(การเรียกระบบหรือยูทิลิตี้ ) ในฐานะผู้ใช้นั้นและใช้ -1 เป็นอาร์กิวเมนต์ PID เพื่อฆ่าซึ่งหมายถึง“ กระบวนการทั้งหมดของผู้ใช้นั้น”

คุณสามารถให้แยกมากยิ่งขึ้น แต่มีการติดตั้งมากขึ้นโดยใช้กระบวนการที่มีอยู่ในความจริงคอนเทนเนอร์


หากคุณตั้งโปรแกรมกระบวนการของคุณเองคุณสามารถใช้บางอย่างเช่น: prctl(PR_SET_PDEATHSIG, SIGHUP);, ข้อมูลเพิ่มเติม: man7.org/linux/man-pages/man2/prctl.2.html
Alexis Wilke

Gilles คุณพูดถึงสิ่งนี้ - "เมื่อคุณปิดเทอร์มินัลเคอร์เนลจะส่งสัญญาณ SIGHUP ไปยังกระบวนการทั้งหมดที่มีมันเป็นเทอร์มินัลการควบคุม" จากนี้ฉันคาดการณ์ว่าเทอร์มินัลส่ง SIGHUP ไปยังผู้นำเซสชัน (เชลล์) ซึ่งส่งต่อไปยังกลุ่มกระบวนการทั้งหมดภายในเซสชัน อันไหนของสองอันนี้ถูกต้อง?
iruvar

4

ภายในสคริปต์ผู้ปกครองจับสัญญาณการฆ่าและให้ฆ่าเด็กทั้งหมด ตัวอย่างเช่น,

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait

2

วิธีที่เชื่อถือได้ในการระบุการสืบทอดทั้งหมดของกระบวนการคือการใช้คำสั่งpstree <pid>โดยที่ pid คือ id กระบวนการหลักของคุณ

อ่านหน้าคนในที่นี่pstree

ในการส่งสัญญาณสมาชิกทั้งหมดของกลุ่มกระบวนการ: killpg(<pgrp>, <sig>);
โดยที่ pgrp คือหมายเลขกลุ่มกระบวนการและ sig คือสัญญาณ

ในการรอเด็กในกลุ่มกระบวนการที่ระบุ: waitpid(-<pgrp>, &status, ...);

อีกทางเลือกหนึ่งในสิ่งที่คุณทำคือการเรียกใช้คอนเทนเนอร์กระบวนการของคุณในเปลือกทุบตีใหม่ สร้าง bash shell ใหม่ด้วยคำสั่งbashแล้วรันกระบวนการของคุณ exitเมื่อคุณต้องการทุกกระบวนการที่จะจบออกจากเปลือกที่มีคำสั่ง


ฉันคิดว่า killpg จะอนุญาตให้ฉันทำสิ่งที่ฉันต้องทำ ขอบคุณ
Craig Turner

1

ใช้

unshare -fp --kill-child -- yourprogram

หากคุณฆ่าunshareกระบวนการลูกทั้งหมด (ที่yourprogramอาจเกิดขึ้น) จะถูกฆ่า

ตอนนี้เป็นไปได้ด้วย util-linux 2.32; ฉันใช้ต้นน้ำนี้ ต้องการเนมสเปซผู้ใช้ (ตัวเลือกกำหนดค่าเคอร์เนลCONFIG_USER_NS=y) หรือสิทธิ์ของรูท ดูที่นี่ด้วย


0

คำสั่งrkillจากแพ็คเกจpslistส่งสัญญาณที่กำหนด (หรือSIGTERMโดยค่าเริ่มต้น) ไปยังกระบวนการที่ระบุและการสืบทอดทั้งหมด:

rkill [-SIG] pid/name...

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