ฉันมีกระบวนการที่ฉันไม่สามารถฆ่าkill -9 <pid>
ได้ มีปัญหาอะไรในกรณีเช่นนี้โดยเฉพาะอย่างยิ่งเมื่อฉันเป็นเจ้าของกระบวนการนั้น ฉันคิดว่าไม่มีสิ่งใดสามารถเลี่ยงkill
ทางเลือกนั้นได้
ฉันมีกระบวนการที่ฉันไม่สามารถฆ่าkill -9 <pid>
ได้ มีปัญหาอะไรในกรณีเช่นนี้โดยเฉพาะอย่างยิ่งเมื่อฉันเป็นเจ้าของกระบวนการนั้น ฉันคิดว่าไม่มีสิ่งใดสามารถเลี่ยงkill
ทางเลือกนั้นได้
คำตอบ:
kill -9
( SIGKILL ) ใช้งานได้เสมอหากคุณได้รับอนุญาตให้ฆ่ากระบวนการ โดยพื้นฐานแล้วทั้งกระบวนการจะต้องเริ่มจากคุณและไม่ต้อง setuid หรือ setgid หรือคุณต้องรูท มีข้อยกเว้นหนึ่งข้อ: แม้แต่ root ไม่สามารถส่งสัญญาณที่ร้ายแรงถึง PID 1 ( init
กระบวนการ)
แต่kill -9
ไม่รับประกันว่าจะทำงานทันที สัญญาณทั้งหมดรวมถึง SIGKILL นั้นจะส่งมอบแบบอะซิงโครนัส: เคอร์เนลอาจใช้เวลาในการส่งสัญญาณ โดยปกติแล้วการส่งสัญญาณจะใช้เวลาไม่เกินสองสามไมโครวินาทีเพียงเวลาที่เป้าหมายใช้เพื่อให้ได้ชิ้นเวลา อย่างไรก็ตามหากเป้าหมายปิดกั้นสัญญาณสัญญาณจะถูกเข้าคิวจนกว่าเป้าหมายจะปลดล็อค
โดยปกติกระบวนการไม่สามารถปิดกั้น SIGKILL แต่รหัสเคอร์เนลสามารถและกระบวนการรันโค้ดเคอร์เนลเมื่อพวกเขาโทรสายระบบ รหัสเคอร์เนลบล็อกสัญญาณทั้งหมดเมื่อขัดจังหวะการเรียกระบบจะส่งผลให้เกิดโครงสร้างข้อมูลที่ไม่ดีที่ใดที่หนึ่งในเคอร์เนลหรือโดยทั่วไปในเคอร์เนลบางค่าคงที่ถูกละเมิด ดังนั้นหาก (เนื่องจากข้อผิดพลาดหรือการออกแบบผิดพลาด) การเรียกระบบบล็อกอย่างไม่มีกำหนดอาจไม่มีทางที่จะฆ่ากระบวนการได้อย่างมีประสิทธิภาพ (แต่กระบวนการจะถูกฆ่าหากการเรียกระบบเสร็จสิ้น)
กระบวนการที่ถูกบล็อกในการเรียกระบบอยู่ในโหมดสลีป ps
หรือtop
คำสั่งจะ (บน Unices มากที่สุด) แสดงในรัฐD
( แต่เดิมสำหรับ“ d ISK” ผมคิดว่า)
กรณีคลาสสิกของ uninterruptible sleep ที่ยาวนานคือกระบวนการเข้าถึงไฟล์ผ่านNFSเมื่อเซิร์ฟเวอร์ไม่ตอบสนอง การใช้งานที่ทันสมัยมีแนวโน้มที่จะไม่ทำให้การนอนหลับที่ไม่หยุดชะงัก (เช่นภายใต้ Linux intr
ตัวเลือกการเมาท์ช่วยให้สัญญาณเข้าถึงการขัดจังหวะการเข้าถึงไฟล์ NFS)
บางครั้งคุณอาจเห็นรายการที่ทำเครื่องหมายZ
(หรือH
ภายใต้ Linux ฉันไม่ทราบความแตกต่าง) ในps
หรือtop
ผลลัพธ์ เทคนิคเหล่านี้ไม่ใช่กระบวนการ แต่เป็นกระบวนการซอมบี้ซึ่งไม่มีอะไรมากไปกว่ารายการในตารางกระบวนการเก็บไว้รอบ ๆ เพื่อให้กระบวนการหลักสามารถได้รับแจ้งถึงการเสียชีวิตของบุตรหลาน พวกเขาจะหายไปเมื่อกระบวนการหลักให้ความสนใจ (หรือตาย)
man 5 nfs
: " ตัวเลือกintr
/ nointr
mount ถูกคัดค้านหลังจากเคอร์เนล 2.6.25 SIGKILL เท่านั้นที่สามารถขัดจังหวะการดำเนินการ NFS ที่ค้างอยู่บนเมล็ดเหล่านี้และหากระบุไว้ตัวเลือกการเมาท์นี้จะถูกละเว้นเพื่อให้เข้ากันได้กับเมล็ดเก่า"
sshfs
กระบวนการ (และเช่นเดียวกันกับระบบไฟล์ FUSE อื่น ๆ : คุณสามารถบังคับให้ unmount ด้วยวิธีนี้ได้เสมอ)
กระบวนการบางครั้งมีอยู่และไม่สามารถฆ่าได้เนื่องจาก:
top
นั้นเป็นสัญญาณ Ztop
มันคือสัญญาณโดย Dดูเหมือนว่าคุณอาจมีกระบวนการผีดิบ สิ่งนี้ไม่เป็นอันตราย: ทรัพยากรเดียวที่กระบวนการซอมบี้ใช้คือรายการในตารางกระบวนการ มันจะหายไปเมื่อกระบวนการผู้ปกครองเสียชีวิตหรือตอบสนองต่อการตายของเด็ก
คุณสามารถดูว่ากระบวนการเป็นซอมบี้โดยใช้top
หรือคำสั่งต่อไปนี้:
ps aux | awk '$8=="Z" {print $2}'
ps
เสมอ ใครบ้างที่สามารถมั่นใจได้ว่าฟิลด์ที่จำเป็นจะต้องเป็นที่ 8 เสมอพร้อมกับการนำไปปฏิบัติps
ทั้งหมดใน Unices ทั้งหมด?
ตรวจสอบเบาะแสของคุณ/var/log/kern.log
และ/var/log/dmesg
(หรือเทียบเท่า) จากประสบการณ์ของฉันสิ่งนี้เกิดขึ้นกับฉันเฉพาะเมื่อการเชื่อมต่อเครือข่ายของ NFS mount ลดลงอย่างกระทันหันหรือไดรเวอร์อุปกรณ์ขัดข้อง อาจเกิดขึ้นได้หากฮาร์ดไดรฟ์ล่มเช่นกันฉันเชื่อ
คุณสามารถใช้lsof
เพื่อดูไฟล์อุปกรณ์ที่กระบวนการเปิด
kill -9
มักจะไม่ทำงานแม้หลังจากรอ 60 นาที ทางออกเดียวคือรีบูท
หากคำตอบของ@ Maciejและ @ Gillesไม่แก้ปัญหาของคุณและคุณไม่รู้จักกระบวนการ (และถามว่ามันคืออะไรกับ distro ของคุณจะไม่ตอบคำถาม) ตรวจสอบ Rootkit และสัญญาณอื่น ๆ ที่คุณได้รับเป็นเจ้าของ รูทคิทมีความสามารถในการป้องกันไม่ให้คุณฆ่ากระบวนการ ในความเป็นจริงหลายคนสามารถป้องกันไม่ให้คุณเห็นพวกเขา แต่ถ้าพวกเขาลืมที่จะแก้ไข 1 โปรแกรมเล็ก ๆ พวกเขาอาจจะเห็น (เช่นพวกเขาแก้ไขtop
แต่ไม่ใช่htop
) เป็นไปได้ว่านี่ไม่ใช่กรณี แต่ดีกว่าปลอดภัยกว่าขออภัย
ฆ่าจริงหมายถึงส่งสัญญาณ มีหลายสัญญาณที่คุณสามารถส่งได้ kill -9 เป็นสัญญาณพิเศษ
เมื่อส่งสัญญาณแอปพลิเคชั่นจะเกี่ยวข้องกับมัน ถ้าไม่ใช่เคอร์เนลที่เกี่ยวข้องกับมัน เพื่อให้คุณสามารถดักจับสัญญาณในแอปพลิเคชันของคุณ
แต่ฉันบอกว่า kill -9 นั้นพิเศษ เป็นสิ่งพิเศษที่แอปพลิเคชันไม่สามารถทำได้ มันจะไปที่เคอร์เนลซึ่งจะฆ่าแอปพลิเคชันอย่างแท้จริงในโอกาสแรกที่เป็นไปได้ กล่าวอีกนัยหนึ่งก็คือฆ่ามันตาย
kill -15 ส่งสัญญาณ SIGTERM ซึ่งย่อมาจาก SIGNAL TERMINATE ในคำอื่น ๆ บอกให้แอปพลิเคชันหยุดการทำงาน นี่เป็นวิธีที่เป็นมิตรในการบอกแอปพลิเคชันว่าถึงเวลาที่ต้องปิดเครื่อง แต่ถ้าแอปพลิเคชันไม่ตอบสนองการฆ่า -9 จะเป็นการฆ่ามัน
ถ้า kill -9 ใช้งานไม่ได้อาจหมายความว่าเคอร์เนลของคุณไม่ทำงาน รีบูตอยู่ในลำดับ ฉันจำไม่ได้ว่าเคยเกิดขึ้น
ก่อนอื่นให้ตรวจดูว่ามันเป็นกระบวนการของซอมบี้หรือไม่
ps -Al
คุณจะเห็นสิ่งที่ชอบ:
0 Z 1000 24589 1 0 80 0 - 0 exit ? 00:00:00 soffice.bin <defunct>
(หมายเหตุ "Z" ทางด้านซ้าย)
หากคอลัมน์ที่ 5 ไม่ใช่ 1 หมายความว่ามีกระบวนการหลัก ลองฆ่าว่าการปกครอง ID
ถ้า PPID ของมัน = 1 อย่าฆ่ามัน !! คิดว่าอุปกรณ์หรือกระบวนการอื่นใดที่เกี่ยวข้องกับมัน
ตัวอย่างเช่นหากคุณใช้อุปกรณ์ที่ติดตั้งหรือแซมบ้าให้ลองยกเลิกการต่อเชื่อม ที่อาจปล่อยกระบวนการซอมบี้
หมายเหตุ : หากps -Al
(หรือtop
) แสดง "D" แทน "Z" อาจเกี่ยวข้องกับการเมาท์ระยะไกล (เช่น NFS) จากประสบการณ์ของฉันการรีบูตเครื่องเป็นวิธีเดียวที่จะไปที่นั่น แต่คุณสามารถตรวจสอบคำตอบอื่น ๆ ซึ่งครอบคลุมรายละเอียดเพิ่มเติมได้
กระบวนการเริ่มต้นนั้นไม่ได้รับผลกระทบจาก SIGKILL
สิ่งนี้เป็นจริงเช่นกันสำหรับเคอร์เนลเธรดเช่น "กระบวนการ" ที่มี PPID เท่ากับ 0
ดังที่คนอื่น ๆ ได้กล่าวถึงกระบวนการในการนอนหลับที่ไม่สามารถขัดจังหวะได้นั้นไม่สามารถฆ่าได้ทันที (หรือในบางกรณี) เป็นที่น่าสังเกตว่ามีการเพิ่มสถานะของกระบวนการอื่น TASK_KILLABLE เพื่อแก้ไขปัญหานี้ในบางสถานการณ์โดยเฉพาะกรณีทั่วไปที่กระบวนการกำลังรอ NFS ดูhttp://lwn.net/Articles/288056/
น่าเสียดายที่ฉันไม่เชื่อว่าสิ่งนี้จะถูกใช้ในเคอร์เนล แต่เป็น NFS
ls
กระบวนการในการเข้าถึงการsshfs
ติดตั้งเมื่อเซิร์ฟเวอร์ระยะไกลไม่สามารถเข้าถึงได้ มีวิธีแก้ปัญหาสำหรับ FUSE หรือ sshfs ซึ่งฉันสามารถใช้ในอนาคตเพื่อหลีกเลี่ยงสถานการณ์เช่นนี้ได้หรือไม่? 2.6.30 เคอร์เนล
ทำสคริปต์เล็ก ๆ น้อย ๆ ที่ช่วยให้ฉันดูได้มาก!
คุณสามารถใช้มันเพื่อฆ่ากระบวนการใด ๆ ที่มีชื่อที่กำหนดในเส้นทางของมัน (ให้ความสนใจกับสิ่งนี้ !!) หรือคุณสามารถฆ่ากระบวนการใด ๆ ของผู้ใช้ที่กำหนดโดยใช้พารามิเตอร์ "-u ชื่อผู้ใช้"
#!/bin/bash
if [ "$1" == "-u" ] ; then\n
PID=`grep "$2" /etc/passwd | cut -d ":" -f3`
processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print $2}'`
echo "############# Killing all processes of user: $2 ############################"
else
echo "############# Killing processes by name: $1 ############################"
processes=`ps aux | grep "$1" | egrep -v "killbyname|grep" | awk '{ print $2}' `
fi
for process in $processes ; do
# "command" stores the entire commandline of the process that will be killed
#it may be useful to show it but in some cases it is counter-productive
#command=`ps aux | grep $process | egrep -v "grep" | awk '{ print $2 }'`
echo "Killing process: $process"
echo ""
kill -9 $process
done
มีหลายกรณีที่แม้ว่าคุณส่ง kill -9 ไปยังโปรเซส pid นั้นจะหยุดทำงาน แต่กระบวนการจะรีสตาร์ทโดยอัตโนมัติ (ตัวอย่างเช่นถ้าคุณลองด้วยgnome-panel
มันจะรีสตาร์ท): เป็นไปได้ไหม?
จากที่นี่เดิม :
ตรวจสอบว่า strace แสดงอะไรหรือไม่
strace -p <PID>
ลองแนบกับกระบวนการด้วย gdb
gdb <path to binary> <PID>
หากกระบวนการโต้ตอบกับอุปกรณ์ที่คุณสามารถยกเลิกการต่อเชื่อมให้นำโมดูลเคอร์เนลออกหรือยกเลิกการเชื่อมต่อ / ถอดปลั๊ก ... จากนั้นลองใช้
ฉันมีปัญหานี้ นี้เป็นโปรแกรมที่ผมได้เปิดตัวด้วยstrace
และขัดจังหวะด้วย+Ctrl
C
มันสิ้นสุดในสถานะT
(traced or หยุด) ผมไม่ทราบว่ามันเกิดขึ้นว่า แต่มันก็ไม่ได้ killable SIGKILL
กับ
เรื่องสั้นสั้นฉันประสบความสำเร็จในการฆ่ามันด้วยgdb
:
gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit
จากคำใบ้ของคำตอบของกิลส์ฉันมีกระบวนการที่ระบุว่า "Z" ที่ด้านบน ( <defunct>
ใน ps) ที่ใช้ทรัพยากรระบบมันยังมีพอร์ตเปิดที่กำลังรับฟังอยู่และคุณสามารถเชื่อมต่อกับพอร์ตนั้นได้ นี่คือหลังจากดำเนินการkill -9
เกี่ยวกับมัน ผู้ปกครองของมันคือ "1" (เช่นinit
) ดังนั้นในทางทฤษฎีมันควรจะยกเลิกและหายไป แต่มันก็ไม่ได้มันติดอยู่รอบ ๆ แม้ว่าจะไม่วิ่งและ "ไม่ตาย"
ดังนั้นในกรณีของฉันมันเป็นซอมบี้ แต่ยังคงใช้ทรัพยากร ... FWIW
และมันก็ไม่ใช่ killable จากจำนวนใด ๆkill -9
's
และพ่อแม่ของมันก็คือinit
แต่มันไม่ได้ถูกเก็บเกี่ยว (ทำความสะอาด) Ie init
มีลูกซอมบี้
และรีบูตเครื่องก็ไม่จำเป็นต้องแก้ไขปัญหา แม้ว่าการรีบูต "จะได้ผล" รอบ ๆ ปัญหา / ทำให้การปิดระบบเร็วขึ้น เพียงแค่ไม่ได้สง่างามซึ่งก็ยังเป็นไปได้
และมันก็เป็นพอร์ต LISTEN ที่เป็นเจ้าของโดยกระบวนการ zombie (และพอร์ตอื่น ๆ อีกสองสามตัวเช่นสถานะ CLOSE_WAIT ที่เชื่อมต่อ localhost กับ localhost) และมันก็ยังได้รับการยอมรับการเชื่อมต่อ แม้กระทั่งเป็นซอมบี้ ฉันเดาว่าไม่ได้รับการทำความสะอาดพอร์ต แต่การเชื่อมต่อขาเข้ายังคงถูกเพิ่มใน backlog ของพอร์ต tcp Listen แม้ว่าพวกเขาจะไม่มีโอกาสได้รับการยอมรับก็ตาม
หลายอย่างที่กล่าวมาข้างต้นระบุว่า "เป็นไปไม่ได้" ในสถานที่ต่าง ๆ ใน interwebs
ปรากฎว่าฉันมีเธรดภายในอยู่ภายในซึ่งเรียกใช้งาน "การเรียกของระบบ" (ioctl ในอินสแตนซ์นี้) ซึ่งใช้เวลาสองสามชั่วโมงในการส่งคืน (ซึ่งเป็นพฤติกรรมที่คาดไว้) เห็นได้ชัดว่าระบบไม่สามารถฆ่ากระบวนการ "ตลอดทาง" จนกว่ามันจะกลับมาจากการioctl
โทรเดาว่ามันเข้าสู่พื้นที่เคอร์เนล หลังจากผ่านไปสองสามชั่วโมงสิ่งต่างๆก็ถูกล้างและซ็อกเก็ตก็ถูกปิดโดยอัตโนมัติ ฯลฯ ตามที่คาดไว้ นั่นเป็นช่วงเวลาแห่งความตายบนแผงประลอง! เคอร์เนลกำลังรอการฆ่าอย่างอดทน
ดังนั้นเพื่อตอบ OP บางครั้งคุณต้องรอ เวลานาน. จากนั้นการสังหารจะเกิดขึ้นในที่สุด
ตรวจสอบ dmesg เพื่อดูว่ามี kernel panic หรือไม่ (เช่น kernel bug)