จะหากระบวนการซอมบี้ได้อย่างไร?


100
System information as of Fri Mar  9 19:40:01 KST 2012

  System load:    0.59               Processes:           167
  Usage of /home: 23.0% of 11.00GB   Users logged in:     1
  Swap usage:     0%                 IP address for eth1: 192.168.0.1

  => There is 1 zombie process.

  Graph this data and manage this system at https://landscape.canonical.com/

10 packages can be updated.
4 updates are security updates.

Last login: Fri Mar  9 10:23:48 2012
a@SERVER:~$ ps auxwww | grep 'Z'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
usera     13572  0.0  0.0   7628   992 pts/2    S+   19:40   0:00 grep --color=auto Z
a@SERVER:~$ 

จะหากระบวนการซอมบี้นั้นได้อย่างไร?


ทำไมคุณไม่เปิดการตรวจสอบระบบและค้นหากระบวนการซอมบี้?
dlin

8
วิธีการทำเช่นนั้นบนเซิร์ฟเวอร์ no-X ที่ไม่มีส่วนหัว?
SabreWolfy

2
น่าแปลกใจที่ไม่มีคำตอบด้านล่างบอกว่าไม่มีกระบวนการซอมบี้ในระบบตามเอาท์พุทข้างต้น หากมีอยู่จริงps auxwww | grep 'Z'คำสั่งควรแสดงกระบวนการในZสถานะ คำว่า "ข้อมูลระบบ" => There is 1 zombie process.ดูเหมือนว่าจะเป็นจุดบกพร่อง อาจเป็นได้ว่ามีข้อมูลขาดหายไปหรือไม่
arielf

คำตอบ:


126

เพื่อฆ่าซอมบี้ (โปรเซส) คุณจะต้องฆ่าโพรเซสแม่ (เหมือนกับซอมบี้จริง ๆ !) แต่คำถามก็คือจะต้องค้นหามันอย่างไร

ค้นหาซอมบี้ (คำถามตอบส่วนนี้):

a@SERVER:~$ ps aux | grep 'Z'

สิ่งที่คุณได้รับคือซอมบี้และสิ่งอื่นใดที่มี Z อยู่ด้วยดังนั้นคุณจะได้รับ grep:

USER       PID     %CPU %MEM  VSZ    RSS TTY      STAT START   TIME COMMAND
usera      13572   0.0  0.0   7628   992 pts/2    S+   19:40   0:00 grep --color=auto Z
usera      93572   0.0  0.0   0      0   ??       Z    19:40   0:00 something

ค้นหาผู้ปกครองของซอมบี้:

a@SERVER:~$ pstree -p -s 93572

จะให้คุณ:

init(1)---cnid_metad(1311)---cnid_dbd(5145)

ในกรณีนี้คุณไม่ต้องการที่จะฆ่ากระบวนการผู้ปกครองและคุณควรจะมีความสุขมากกับซอมบี้หนึ่งตัว แต่การฆ่ากระบวนการผู้ปกครองทันที 5145 ควรกำจัดมัน

แหล่งข้อมูลเพิ่มเติมเกี่ยวกับ Askubuntu:


1
ผลลัพธ์ที่คุณแสดงในคำตอบของคุณคือคำสั่ง grep ไม่ใช่กระบวนการซอมบี้ มันเป็นความผิดพลาดแบบเดียวกับที่ Pablo ทำไว้ในคำตอบของเขา คำตอบโดย Rinzwind ด้านล่างจะค้นหากระบวนการซอมบี้และทำรายการ ตัวเลือกอื่นสามารถ grep สำหรับ "ตาย"
FvD

pstree -H your_desired_pid -p
Greg M. Krsak

ขอบคุณ Greg สำหรับการเพิ่มการสนทนา แต่โปรดจำไว้ว่านี่เป็นเว็บไซต์ความช่วยเหลือเพียงแค่วางคำสั่งโดยไม่อธิบายสิ่งใด ๆ จะไม่เป็นประโยชน์กับคนส่วนใหญ่ที่มาที่นี่เพื่อขอความช่วยเหลือ
Duncanmoo

1
นี่เป็นคำตอบที่ยอดเยี่ยม! มันยังคงใช้ได้วันนี้! ฉันสามารถค้นหากระบวนการซอมบี้ของฉันและฆ่ากระบวนการหลักได้โดยไม่มีปัญหา ขอขอบคุณ!
Terrance

1
หากคุณไม่ได้ติดตั้ง pstree ให้ps wauxfทำสิ่งเดียวกัน
JDS

35

แม้ว่าคำถามนี้จะเก่า แต่ฉันคิดว่าทุกคนสมควรได้รับคำตอบที่น่าเชื่อถือมากขึ้น:

ps axo pid=,stat=

สิ่งนี้จะปล่อยคอลัมน์สองคอลัมน์ที่คั่นด้วยช่องว่างซึ่งคอลัมน์แรกเป็น PID และคอลัมน์ที่สองเป็นสถานะ

ฉันไม่คิดว่าแม้แต่ GNU psจะมีวิธีการกรองตามสถานะโดยตรง แต่คุณสามารถทำได้ด้วยความน่าเชื่อถือawk

ps axo pid=,stat= | awk '$2~/^Z/ { print }'

ตอนนี้คุณมีรายการ PID ซึ่งเป็นซอมบี้ เนื่องจากคุณทราบสถานะแล้วไม่จำเป็นต้องแสดงอีกต่อไปดังนั้นจึงสามารถกรองออกได้

ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'

ให้รายการ PID ซอมบี้ที่มีการคั่นบรรทัด

ตอนนี้คุณสามารถใช้งานรายการนี้ได้โดยใช้ shell shell แบบง่าย ๆ

for pid in $(ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }') ; do
    echo "$pid" # do something interesting here
done

ps เป็นเครื่องมือที่ทรงพลังและคุณไม่จำเป็นต้องทำอะไรซับซ้อนเพื่อดึงข้อมูลกระบวนการออกมา

(ความหมายของสถานะกระบวนการที่แตกต่างกันที่นี่ - https://unix.stackexchange.com/a/18477/121634 )


2
awkยังเป็นเครื่องมือที่มีประสิทธิภาพซึ่งไม่เพียง แต่แบ่งข้อความ แต่ยังสามารถจับคู่ได้ +1 ... คนอื่น ๆ ใช้สิ่งgrepที่ไม่จำเป็นและไม่แม่นยำ
0xC0000022L

ดังนั้นตอนนี้ที่ฉันมีรายการกระบวนการซอมบี้ ฉันจะฆ่าพวกเขาได้อย่างไร
chovy

@ chovy: มันขึ้นอยู่กับ แต่โดยทั่วไปแล้วเกี่ยวข้องกับการฆ่าหรือการส่งสัญญาณผู้ปกครอง คำตอบอื่น ๆ ที่นี่จะไปในที่ จากภายในลูปที่แสดงด้านบนคุณจะพบ pid พาเรนต์ดังนี้:ps -p "$pid" -opid=,ppid=
Sorpigal

ถ้าฉันจะพ่อแม่จะไม่ฆ่ากระบวนการลูกทั้งหมด? ฉันแค่อยากจะฆ่าหนึ่งกระบวนการซอมบี้ ฉันรู้ PPID
chovy

1
ฉันขอแนะนำให้เพิ่มลงppid=ในรายการตัวเลือกดังนั้นไม่จำเป็นต้องใช้คำสั่งแยกเพื่อรับ ppid
Ding-Yi Chen

3

ps aux | awk '{ print $8 " " $2 }' | grep -w Z

จาก: http://www.cyberciti.biz/tips/killing-zombie-process.html

จากความคิดเห็นหนึ่งที่ได้รับการปรับปรุง:

for p in $(ps jauxww | grep Z | grep -v PID | awk '{print $3}'); do
    for every in $(ps auxw | grep $p | grep cron | awk '{print $2}'); do
        kill -9 $every;
    done;
done;

ระวังหน่อย: อันนี้ก็ฆ่ากระบวนการเช่นกัน


ยังคงส่งคืนอะไร ฉันคิดว่าวิธีการของฉันก็ไม่ผิด
Pablo

ตัวอย่างที่ 2 นั้นไม่น่าเชื่อถืออย่างชั่วร้ายและอดีตนั้นไม่จำเป็นต้องใช้คำอธิบายอย่างละเอียด (ลองps axo pid=,stat= | awk '$2~/Z/ {print $1}'แทน)
Sorpigal

3

น้อยกว่ามากแม้ว่า:

ps afuwwx | less +u -p'^(\S+\s+){7}Z.*'

นั่นเป็นเหมือนให้ป่า (ต้นไม้) ของกระบวนการผู้ใช้ทั้งหมดในรูปแบบผู้ใช้ที่มีความกว้างไม่ จำกัด บน tty ใด ๆ และแสดงให้ฉันที่ครึ่งหน้าจอด้านบนซึ่งตรงกับกรณีที่คอลัมน์ที่ 8 ประกอบด้วย Z และ ทำไมไม่เน้นทั้งบรรทัด

รูปแบบที่มุ่งเน้นผู้ใช้ดูเหมือนจะหมายถึง: USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMANDดังนั้นสถานะ Zombie จะปรากฏในคอลัมน์ที่ 8

คุณสามารถโยนNก่อนpถ้าคุณต้องการหมายเลขบรรทัดและ a Jถ้าคุณต้องการเครื่องหมายดอกจันในการแข่งขัน น่าเศร้าถ้าคุณใช้Gเพื่อไม่เน้นบรรทัดที่เครื่องหมายดอกจันจะไม่แสดงแม้ว่าJจะสร้างที่ว่างสำหรับมัน

คุณจะได้สิ่งที่ดูเหมือน:

…
  root      2919  0.0  0.0  61432  5852 ?      Ss Jan24 0:00 /usr/sbin/sshd -D
  root     12984  0.0  0.1 154796 15708 ?      Ss 20:20 0:00  \_ sshd: lamblin [priv]
  lamblin  13084  0.0  0.0 154796  9764 ?      S  20:20 0:00      \_ sshd: lamblin@pts/0
* lamblin  13086  0.0  0.0  13080  5056 pts/0  Z  20:20 0:00          \_ -bash <defunct>
  lamblin  13085  0.0  0.0  13080  5056 pts/0  Ss 20:20 0:00          \_ -bash
  root     13159  0.0  0.0 111740  6276 pts/0  S  20:20 0:00              \_ su - nilbmal
  nilbmal  13161  0.2  0.0  13156  5004 pts/0  S  20:20 0:00                  \_ -su
  nilbmal  13271  0.0  0.0  28152  3332 pts/0  R+ 20:20 0:00                      \_ ps afuwwx
  nilbmal  13275  0.0  0.0   8404   848 pts/0  S+ 20:20 0:00                      \_ less +u -Jp^(\S+\s+){7}Z.*
…

คุณสามารถติดตามสิ่งนี้ได้ด้วย (และจะตรวจพบว่าเทอร์มินัลของคุณชอบ -U Unicode หรือ -A Ascii):

pstree -psS <PID LIST>

หรือเพียงแค่คุณใช้ลูกศรขึ้นlessเพื่อติดตามต้นไม้ / ฟอเรสต์ผ่านลำดับชั้น ซึ่งเป็นสิ่งที่ฉันแนะนำด้วยวิธี "Less is more"


0

ฉันขอแนะนำให้คุณคำสั่งนี้:

ps aux | awk '"[Zz]" ~ $8 { printf("%s, PID = %d\n", $8, $2); }'

การใช้auxและ munging สตริงนั้นไม่น่าเชื่อถือโดยไม่จำเป็นเมื่อคุณสามารถใช้-oและขอสิ่งที่คุณต้องการ ใช้ps ax -o pid=,stat= | awk '$2 ~ "[Zz]" { printf("%s, PID = %d\n", $2, $1); }'แทน
Sorpigal

-1

ในการแสดงรายการซอมบี้กระบวนการลองคำสั่งนี้:

ps j | awk '$7 ~ "Z"'

คุณอาจต้องเปลี่ยน$7ขึ้นอยู่กับระบบปฏิบัติการของคุณ

สิ่งนี้จะส่งคืนรายการของรหัสกระบวนการหลัก ( PPID)

ในการพยายามฆ่าซอมบี้ (หลังจากทดสอบคำสั่งด้านบน) ให้ลอง:

kill -9 $(ps j | awk 'NR>1 && $7 ~ "Z" {print $2}')

หากต้องการระบุผู้ปกครองให้ลองทำpstreeเช่น:

$ ps j | awk 'NR>1 && $7 ~ "T" {print $2}' | xargs -L1 pstree -sg
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2430)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2431)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2432)

การหันหนึ่งคอลัมน์จากjรูปแบบมาใช้นั้นมีความซับซ้อนโดยไม่จำเป็น ใช้-oเพื่อเลือกสิ่งที่คุณต้องการแทน
Sorpigal

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