ทำไมกระบวนการ / โปรแกรมกลายเป็นซอมบี้?


13

หากสคริปต์ทำงานได้ดีจากบรรทัดคำสั่งทำไมสคริปต์เดียวกันกลายเป็นสถานะซอมบี้หลังจากทำงานผ่าน cron และคุณจะแก้ไขปัญหาเดียวกันได้อย่างไร

นี่คือตัวอย่างจริง:

[root@abc ~]# ps ax | grep Z
23880 ?        Zs     0:00 [checkloadadv.sh] <defunct>
23926 pts/0    S+     0:00 grep Z
[root@abc ~]# strace -p 23880
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted
[root@abc ~]# pstree | grep  checkload
init-+-crond---crond-+-checkloadadv.sh
[root@abc ~]# bash /usr/bin/checkloadadv.sh
System Load is OK : 0.05

การแก้ไขปัญหาเกิดขึ้นเมื่อมีปัญหา ซอมบี้ไม่ใช่ปัญหา
Gilles 'หยุดความชั่วร้าย'

@Gilles คุณพูดถูก แต่ฉันจำเป็นต้องดูแลและหาวิธีป้องกันพวกเขาหรือไม่? คุณคิดว่าไง ?
ราหุลปาติล

พวกเขาไม่ใช่ปัญหาดังนั้นไม่คุณไม่ต้องดูแล
Gilles 'หยุดความชั่วร้าย'

คำตอบ:


21

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

เช่นเดียวกับซอมบี้ที่เกิดขึ้นจริงกระบวนการซอมบี้ไม่สามารถฆ่าได้เพราะมันตายไปแล้ว

มันเกิดขึ้นได้อย่างไร

เมื่ออยู่ใน Linux / Unix กระบวนการจะหยุด / สิ้นสุดข้อมูลทั้งหมดจากกระบวนการจะถูกลบออกจากหน่วยความจำระบบเฉพาะตัวอธิบายกระบวนการเท่านั้น กระบวนการเข้าสู่สถานะ Z (ซอมบี้) กระบวนการหลักของเขาได้รับสัญญาณจากเคอร์เนล: SIGCHLDซึ่งหมายความว่าหนึ่งในกระบวนการลูกของเขาออกจากถูกขัดจังหวะหรือดำเนินการต่อหลังจากถูกขัดจังหวะ (ในกรณีของเรามันออกจากเพียง)

ตอนนี้กระบวนการพาเรนต์จะต้องเรียกใช้wait()syscall เพื่ออ่านสถานะการออกและข้อมูลอื่น ๆ จากกระบวนการลูกของเขา จากนั้น descriptor จะถูกลบออกจากหน่วยความจำและกระบวนการไม่ได้เป็นซอมบี้อีกต่อไป

หากกระบวนการหลักไม่เคยเรียกwait()syscall ตัวอธิบายกระบวนการซอมบี้จะยังคงอยู่ในหน่วยความจำและกินสมอง โดยปกติคุณจะไม่เห็นกระบวนการซอมบี้เนื่องจากขั้นตอนด้านบนใช้เวลาน้อยลง

รุ่งอรุณแห่งความตาย

ตัวอธิบายกระบวนการแต่ละอันต้องการหน่วยความจำเพียงเล็กน้อยดังนั้นซอมบี้บางตัวจึงไม่อันตรายมาก (เหมือนในชีวิตจริง) ปัญหาหนึ่งคือกระบวนการซอมบี้แต่ละอันจะเก็บ id กระบวนการของเขาไว้และระบบปฏิบัติการ Linux / Unix มีจำนวน pid ที่ จำกัด หากซอฟต์แวร์ที่ตั้งโปรแกรมไม่ถูกต้องสร้างกระบวนการซอมบี้จำนวนมากมันอาจเกิดขึ้นได้ว่ากระบวนการไม่สามารถเริ่มต้นได้อีกต่อไปเพราะไม่มีรหัสกระบวนการมากขึ้น

ดังนั้นหากพวกเขาอยู่ในกลุ่มใหญ่พวกเขาจะอันตรายมาก (เหมือนในภาพยนตร์หลายเรื่องที่แสดงให้เห็นเป็นอย่างดี)

เราจะป้องกันตัวเองจากฝูงซอมบี้ได้อย่างไร?

การยิงที่หัวจะใช้งานได้ แต่ฉันไม่รู้คำสั่งสำหรับสิ่งนั้น (SIGKILL จะไม่ทำงานเพราะกระบวนการตายไปแล้ว)

ทีนี้คุณสามารถส่ง SIGCHLD ผ่าน kill ไปยังโพรเซสแม่ แต่เมื่อมันละเว้นสัญญาณนี้แล้วจะเป็นอย่างไร? ตัวเลือกเดียวของคุณคือฆ่ากระบวนการผู้ปกครองและกระบวนการเริ่มต้น "adopts" ซอมบี้ ตอนแรกเรียกwait()syscall เป็นระยะเพื่อล้างลูกซอมบี้ของเขา

ในกรณีของคุณ

ในกรณีของคุณคุณต้องส่ง SIGCHLD ไปยังกระบวนการ crond:

root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit

จากนั้นอีกเทอร์มินัล:

root@host:~$ kill -17 $(pgrep cron)

ผลลัพธ์คือ:

restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff)        = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached

คุณเห็นwait4()syscall คืนค่า -1 ECHILD ซึ่งหมายความว่าไม่มีกระบวนการลูก ดังนั้นข้อสรุปคือ: cron ตอบสนองต่อ SIGCHLD syscall และไม่ควรบังคับให้เปิดเผย


1
อะไรไม่มีค้างคาวคริกเก็ตและ LP
Alexios

-3

หากเธรดหลักถูกฆ่าก่อนที่เธรดย่อยเธรดย่อยทั้งหมดจะกลายเป็นกระบวนการซอมบี้


7
ไม่เป็นความจริงพวกเขาเพิ่งจะได้รับการชดใช้ กระบวนการซอมบี้ไม่ได้เรียกว่า waitpid
Chris Down

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