เหตุใดฉันจึงไม่สามารถฆ่ากระบวนการนี้บน Linux ได้


8

ปัญหา

ฉันต้องการฆ่ากระบวนการที่เรียกว่า raspivid (โปรแกรมที่บันทึกวิดีโอโดยใช้กล้อง Raspberry Pi) แต่ฉันไม่สามารถ ...

นี่คือวิธีที่ฉันเรียกว่า:

#!/bin/bash

#Start recording...
raspivid -w 800 -h 600 -t 15000 -o $1 -v -n -rot 270 >> /home/pi/log/camera_output.txt 2>&1 &

#Waiting the video to be complete
sleep 16

#Killing child process
sudo kill -9 $!

#Killing parent process
sudo kill -9 $$

หากฉันค้นหากระบวนการนี้จะยังคงอยู่:

pi@raspberrypi ~ $ ps -ef | grep raspivid
root      7238     7234  0 21:53 ?        00:00:00 [raspivid]
pi       17096 14925  0 22:05 pts/0    00:00:00 grep --color=auto raspivid

ถ้าฉันพยายามจะฆ่ามันมันจะไม่ตาย แต่จะเปลี่ยนพาเรนต์ PID เป็น 1:

pi@raspberrypi ~ $ sudo killall raspivid
pi@raspberrypi ~ $ ps -ef | grep raspivid
root      7238     1  0 21:53 ?        00:00:00 [raspivid]
pi       17196 14925  0 22:05 pts/0    00:00:00 grep --color=auto raspivid
pi@raspberrypi ~ $ sudo killall raspivid

ข้อสังเกต:

  1. การโทรทำงานได้ดีชั่วขณะหนึ่ง (2 ชั่วโมงหรืออย่างน้อย) จากนั้นจะเริ่มแขวน
  2. เฉพาะการปิดเครื่องเท่านั้นที่สามารถแก้ไขปัญหาได้ ฉันไม่สามารถรีบูตผ่านเทอร์มินัลได้ (แฮงค์ด้วย)

คำถามของฉัน:

  1. เหตุใด Linux จึงกำหนด PID หลักให้กับ 1
  2. ทำไมกระบวนการไม่สามารถฆ่าได้? (ฉันก็ลองsudo kill -9 7238)

คำตอบ:


2

ปัญหา

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

จากที่man bashเราสามารถอ่านได้:

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

คำตอบ # 1:กระบวนการinitมีPID 1และสำหรับ Linux นี้จะกำหนดพาเรนต์ด้วย PID 1 (เพราะจะกำหนดให้กับinit )

คำตอบ # 2:พวกเขาไม่สามารถฆ่าได้เพียงเพราะตายไปแล้ว ... ถ้าพ่อแม่ของพวกเขาinitอาจจะพอที่จะรอสักครู่

ในการลบซอมบี้ออกจากระบบสัญญาณ SIGCHLD สามารถส่งไปยังผู้ปกครองด้วยตนเองโดยใช้คำสั่ง kill หากกระบวนการหลักยังคงปฏิเสธที่จะเก็บเกี่ยวซอมบี้ขั้นตอนต่อไปคือการลบกระบวนการหลัก เมื่อกระบวนการสูญเสียพาเรนต์ init จะกลายเป็นพาเรนต์ใหม่ ในขั้นต้นจะเรียกใช้งานระบบการรอเป็นระยะเพื่อเก็บเกี่ยวซอมบี้ใด ๆ ที่มี init เป็นผู้ปกครอง [1]

ในกรณีที่ความคิดนี้เกิดขึ้นหนึ่งวันหรืออีกวัน: การ#kill -9 initประมวลผลด้วยสิทธิ์พิเศษของรูทคือซอฟต์แวร์ที่เทียบเท่ากับการถอดปลั๊กคอมพิวเตอร์ออกจากระบบไฟฟ้า [:-)]

อย่างไรก็ตามกระบวนการซอมบี้สามารถระบุได้ในผลลัพธ์ของpsคำสั่งโดยการมี "Z" ในคอลัมน์STAT คุณสามารถใช้บรรทัดต่อไปนี้เพื่อระบุตัวตนได้อย่างง่ายดาย

ps -aux | grep Z

การอ้างอิงบางอย่างเกี่ยวกับโลกของซอมบี้ซอมบี้ :


กระบวนการที่มี parent PID 1 ไม่ใช่ซอมบี้ กระบวนการรับผู้ปกครองนี้เมื่อมันพ่อแม่ถูกฆ่าตายก่อนที่มันจะเป็น killallเห็นได้ชัดว่าเขาฆ่าพ่อแม่ไม่ใช่กระบวนการที่เขาต้องการ
Barmar

คุณเห็น<defunct>ในpsผลลัพธ์ของเขาที่ไหน คำถามนี้เกี่ยวข้องกับอะไร?
Barmar

@Barmar ฉันไม่เห็น แต่น่าเสียดายที่ไม่เคยเป็นปัญหาตรงที่คุณกำลังค้นหา BTW จาก$!เขาkill -9โดยไม่ต้องรอกระบวนการพื้นหลังด้วยกล้อง ... หลังจากที่sleep 16เขาผู้ปกครองทันทีอีกครั้ง มันได้กลิ่นของ. ซอมบี้ ... ตามกลิ่น (:-)) คุณจะเห็นว่าเมื่อเขาทำตามนี้เด็กยังมีชีวิตอยู่ แต่พ่อแม่ถูกฆ่าตาย (-9) kill -9ps -ef
Hastur

1
ฉันคิดว่าคุณทำให้กระบวนการเด็กกำพร้าสับสนด้วยกระบวนการซอมบี้ แต่ก็ไม่เกี่ยวข้องกัน
Barmar

ดูสคริปต์อีกครั้ง: เขาkill -9ดำเนินการเอง มันเหมาะสมที่จะถือว่ามันฆ่าตายและ <ตาย> ... sudo killall raspividมากยิ่งขึ้นหลังจากที่โทรไม่ใช่มีประสิทธิภาพ เป็นไปได้ที่raspividจะวางไข่กระบวนการเด็กของตัวเองที่ยังคงอยู่กับเด็กกำพร้า BTW มันเพียงพอที่จะทำ "ps -aux | grep Z" เพื่อดูว่ามันเป็นซอมบี้หรือไม่และควรจะ (เพียงพอ) เพื่อหลีกเลี่ยงkill -9กระบวนการในสคริปต์หลัก
Hastur

4

ในการตอบคำถามหมายเลข 1:

เมื่อกระบวนการสร้างกระบวนการเด็กกระบวนการลูกแต่ละคนมี PID ของตัวเอง PPID ของเด็กแต่ละคน (id กระบวนการของผู้ปกครอง) เป็น PID ของกระบวนการหลักของพวกเขา หากผู้ปกครองเสียชีวิตกระบวนการลูกจะถูกกำพร้า กระบวนการที่เป็นเด็กกำพร้าจะรับโดยอัตโนมัติโดยกระบวนการเริ่มต้นของระบบซึ่งมี PID เป็น 1


0

โปรแกรมอาจเปิดอุปกรณ์กล้องและโดยการบังคับให้ฆ่าคุณไม่ได้อนุญาตให้ล้างข้อมูลอย่างถูกต้องดังนั้นตอนนี้ก็ติดอยู่

ข้อสังเกตบางประการ:

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