กระบวนการ <defunct> คืออะไรและเหตุใดจึงไม่ถูกฆ่า


180

เบราว์เซอร์ chrome ไม่ตอบสนองและฉันพยายามจะฆ่า แต่แทนที่จะหายไปจากกระบวนการ<defunct>ทางด้านขวาและไม่ถูกฆ่า:

ป้อนคำอธิบายรูปภาพที่นี่

อะไรคือสิ่งที่<defunct>สำหรับกระบวนการและทำไมมันไม่ได้รับการฆ่า?


3
คำตอบที่ได้รับการยอมรับกล่าวว่า " kill -9 PIDไม่ทำงาน" เป็นจริงบางส่วน: ในความเป็นจริงไม่มีการฆ่าจะทำงาน นอกจากนี้ควรใช้ -9 เป็นทางเลือกสุดท้าย 99% ของเวลาที่การทำลายเริ่มต้นของกระบวนการหลักจะฆ่ามันและเก็บเกี่ยวเด็กทั้งหมด "default kill" คือ SIGTERM (-15) ฉันขอแนะนำให้แฟน ๆ ของ -9 (SIGKILL) อ่านstackoverflow.com/questions/690415/…
Mike S

คำตอบ:


172

จากผลลัพธ์ของคุณเราจะเห็นคำว่า "หมดอายุ" ซึ่งหมายความว่ากระบวนการทำงานเสร็จสมบูรณ์หรือเสียหายหรือถูกทำลาย แต่กระบวนการลูกยังทำงานอยู่หรือกระบวนการหลักเหล่านี้กำลังตรวจสอบกระบวนการลูก เพื่อฆ่ากระบวนการชนิดนี้ kill -9 PID ไม่ทำงาน คุณสามารถพยายามที่จะฆ่าพวกเขาด้วยคำสั่งนี้ แต่มันจะแสดงให้เห็นอีกครั้งและอีกครั้ง

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

ps -ef | grep defunct

UID          PID     PPID       C    STIME      TTY          TIME              CMD
1000       637      27872      0   Oct12      ?        00:00:04 [chrome] <defunct>
1000      1808      1777       0    Oct04     ?        00:00:00 [zeitgeist-datah] <defunct>

จากkill -9 637 27872นั้นตรวจสอบว่ากระบวนการที่หายไปนั้นผ่านไปps -ef | grep defunctแล้ว


13
คุณไม่สามารถฆ่ากระบวนการ "หมดอายุ" คุณสามารถเพิ่มความเร็วในการลบรายการในตารางกระบวนการโดยฆ่าผู้ปกครอง
jfs

57
เกิดอะไรขึ้นถ้า ppid คือ1( init) สมมติว่าฉันจะต้องรอ?
ลั

7
เพื่อทำให้การฆ่าที่คุณสามารถทำเช่นนี้ได้อีกด้วย (อาจต้องเปลี่ยนไบต์คุณกำลังตัดจากการส่งออก):ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9
วอร์เรน

3
@warren ขอบคุณ คุณสามารถทำให้สั้นลงได้เล็กน้อยและ (imo) ง่ายขึ้นโดยไม่ทำการ grep ตัวที่สอง เพียงแค่เปลี่ยน grep แรกเป็นgrep [d]efunctหรือคล้ายกันและจะไม่ตรงกับตัวเอง
Thor84no

4
@warren คุณไม่สามารถฆ่ากระบวนการที่ตายแล้วได้แม้ด้วย SIGKILL นอกจากนี้คุณกำลังใช้งาน kill -9 โดยไม่เลือกปฏิบัติ ดูstackoverflow.com/questions/690415/... หากคุณต้องการฆ่าเด็กที่ตายแล้วคุณอาจลอง: parents_of_dead_kids=$(ps -ef | grep [d]efunct | awk '{print $3}' | sort | uniq | egrep -v '^1$'); echo "$parents_of_dead_kids" | xargs kill. รันสคริปต์อีกครั้งหลังจาก 30 วินาทีหรือมากกว่านั้นkill -9หากคุณต้องการ (โปรดทราบว่าฉันไม่ได้รับอนุญาตให้ฆ่าโดยเฉพาะInit)
Mike S

60

หน้าคู่มือ ps (1) พูดว่า :

กระบวนการที่ทำเครื่องหมาย<defunct>เป็นกระบวนการที่ตายแล้ว (ที่เรียกว่า"ซอมบี้" ) ที่ยังคงอยู่เพราะผู้ปกครองไม่ได้ทำลายอย่างถูกต้อง กระบวนการเหล่านี้จะถูกทำลายโดยinit(8)ถ้ากระบวนการหลักออกจาก

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

บนระบบปฏิบัติการคอมพิวเตอร์ Unix และ Unix like กระบวนการ zombie หรือกระบวนการ defunct เป็นกระบวนการที่ดำเนินการเสร็จสมบูรณ์ แต่ยังมีรายการในตารางกระบวนการ รายการนี้ยังต้องการให้กระบวนการผู้ปกครองสามารถอ่านสถานะการออกของเด็ก

ไม่มีอันตรายใด ๆ ในการปล่อยให้กระบวนการดังกล่าวเป็นเว้นแต่จะมีหลายกระบวนการ ในที่สุดซอมบี้ก็ถูกผู้ปกครองเก็บไว้ (โดยการโทรwait(2)) หากผู้ปกครองดั้งเดิมไม่ได้รับการเก็บเกี่ยวอีกครั้งก่อนที่จะออกจากinitกระบวนการของมันเอง( pid == 1) จะดำเนินการในภายหลัง กระบวนการซอมบี้เป็นเพียง:

กระบวนการที่ถูกยกเลิกและถูกลบเมื่อสถานะการออกของมันถูกรายงานไปยังกระบวนการอื่นซึ่งกำลังรอให้กระบวนการนั้นสิ้นสุดลง


1

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

# egrep -v '^1$ = Make sure the process is not the init process.
# awk '{print $3}' = Print the parent process.

first_parent_of_first_dead_kid=$(ps -ef | grep [d]efunct | awk '{print $3}' | head -n1 | egrep -v '^1$')
echo "$first_parent_of_first_dead_kid"

# If the first parent of the first dead kid is in.telnetd, then kill it.
if ps -ef | grep $first_parent_of_first_dead_kid | grep in.telnetd;then
        echo "We have a defunct process whose parent process is in.telnetd" | logger -t KILL-DEFUNCT-TELNET
        echo "killing $first_parent_of_first_dead_kid" | logger -t KILL-DEFUNCT-TELNET
        kill $first_parent_of_first_dead_kid 2>&1 | logger -t KILL-DEFUNCT-TELNET
fi

1

การขยายคำตอบของแพดดิงตั้น ..

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

kill -9 PID จะไม่ทำงาน (ตายไปแล้ว)

หากต้องการกำหนดพาเรนต์ของกระบวนการลูกนี้ให้รันคำสั่งนี้:

ps -ef | grep defunct

 UID  PID **PPID** C STIME TTY TIME     CMD
 1000 637  27872   0 Oct12 ?   00:00:04 [chrome] <defunct>

ดูว่าผู้ปกครองคือใคร: ps ax | grep 27872

หากคุณต้องการคุณสามารถฆ่าผู้ปกครองและผู้ตายจะหายไป kill -9 27872

ดูคำตอบของ JF Sebastian เพื่อเหตุผลด้านเทคนิคเพิ่มเติม


1

เมื่อเพิ่มคำตอบของ @ Paddington ฉันได้เพิ่มฟังก์ชั่นนี้ลงใน bashrc ของฉันเพื่อตรวจสอบอย่างรวดเร็ว:

defunct(){
    echo "Children:"
    ps -ef | head -n1
    ps -ef | grep defunct
    echo "------------------------------"
    echo "Parents:"
    ppids="$(ps -ef | grep defunct | awk '{ print $3 }')"
    echo "$ppids" | while read ppid; do
        ps -A | grep "$ppid"
    done
}

มันแสดงผลเหมือน:

เด็ก:
UID PID PPID C เวลา TTY TIME CMD
ผู้ใช้ 25707 25697 0 Feb26 แต้ม / 0 00:00:00 [sh] 
ผู้ใช้ 30381 29915 0 11:46 แต้ม / 7 00:00:00 grep defunct
------------------------------
พ่อแม่:
25697 แต้ม / 0 00:00:00 น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.