Tại sao tôi không thể giết quá trình này trên Linux?


8

Vấn đề

Tôi muốn giết một quá trình gọi là raspivid (chương trình ghi video bằng Raspberry Pi Camera) nhưng tôi không thể ...

Đây là cách tôi gọi nó:

#!/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 $$

Nếu tôi tìm kiếm quá trình này, nó vẫn ở đó:

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

Nếu tôi cố giết nó, nó sẽ không chết. Thay vào đó, nó thay đổi PID gốc thành 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

Quan sát:

  1. Cuộc gọi hoạt động tốt trong một thời gian (2 giờ hoặc một cái gì đó) sau đó nó bắt đầu treo.
  2. Chỉ có một sức mạnh vật lý tắt giải quyết vấn đề. Tôi không thể khởi động lại qua thiết bị đầu cuối (nó cũng bị treo)

Những câu hỏi của tôi:

  1. Tại sao Linux lại gán cho cha mẹ là 1?
  2. Tại sao quá trình không thể bị giết? (Tôi cũng đã thử sudo kill -9 7238)

Câu trả lời:


2

Vấn đề

Kịch bản của bạn có thể đang tạo ra zombie vì các kill -9lệnh của bạn ; như đề xuất từ câu trả lời của jjlin cũng không bao giờ là một thực hành tốt để giết đột ngột một số quá trình mà không bị ép buộc.

Từ man bashchúng ta có thể đọc:

Các quy trình được đánh dấu <defposed> là các quy trình chết (được gọi là " zombie ") vẫn còn bởi vì cha mẹ của chúng đã không tiêu diệt chúng đúng cách . Các tiến trình này sẽ bị hủy bởi init (8) nếu tiến trình cha thoát ra.

Câu trả lời # 1: Quá trình initPID 1 và Linux này gán cho chúng là cha mẹ với PID 1 (vì nó gán chúng cho init ).

Câu trả lời số 2: Họ không thể bị giết đơn giản vì họ vừa mới chết ... nếu cha mẹ của họ initcó lẽ đủ để chờ đợi một thời gian.

Để loại bỏ zombie khỏi hệ thống, tín hiệu SIGCHLD có thể được gửi đến cha mẹ bằng tay, sử dụng lệnh kill. Nếu tiến trình cha mẹ vẫn từ chối gặt hái zombie, bước tiếp theo sẽ là loại bỏ tiến trình cha. Khi một tiến trình mất cha mẹ của nó, init trở thành cha mẹ mới của nó. Ban đầu định kỳ thực hiện lệnh gọi hệ thống chờ để gặt hái bất kỳ zombie nào với init là cha. [1]

Chỉ trong trường hợp ý tưởng này phát sinh ngày này hay ngày khác: để #kill -9 initxử lý với đặc quyền gốc là phần mềm tương đương với việc rút phích cắm máy tính khỏi lưới điện. [:-)]

Tuy nhiên, quá trình zombie có thể được xác định trong đầu ra của pslệnh bằng sự hiện diện của chữ "Z" trong cột STAT . Bạn có thể sử dụng dòng sau để dễ dàng xác định chúng

ps -aux | grep Z

Một số tài liệu tham khảo về thế giới zombie Linux :


Một quá trình với cha mẹ PID 1 không phải là một zombie. Một quá trình có được cha mẹ này khi cha mẹ của nó bị giết trước đó. Vì vậy, anh ta killallrõ ràng là giết cha mẹ, không phải là quá trình anh ta muốn.
Barmar 6/2/2015

Bạn thấy nơi nào <defunct>trong psđầu ra của anh ấy ? Điều đó có liên quan gì đến câu hỏi này?
Barmar 6/2/2015

@Barmar tôi không thấy. Thật không may, không phải lúc nào vấn đề là chính xác nơi bạn đang tìm kiếm . BTW từ $!anh ấy kill -9mà không chờ quá trình nền với máy ảnh ... sau khi sleep 16anh ấy kill -9cha mẹ , đột ngột một lần nữa. Nó có mùi .zombie ... Theo mùi (:-)) bạn có thể thấy rằng, với những điều sau đây ps -ef, đứa trẻ vẫn còn sống, nhưng cha mẹ đã bị giết (-9).
Hastur 7/2/2015

1
Tôi nghĩ rằng bạn đang nhầm lẫn các quy trình mồ côi với các quy trình zombie, nhưng chúng không liên quan.
Barmar 7/2/2015

Nhìn lại kịch bản: anh ấy kill -9tự xử lý. Thật hợp lý khi cho rằng nó đã bị giết và <không còn tồn tại> ... thậm chí nhiều hơn sau cuộc gọi không hiệu quả sudo killall raspivid. Thậm chí có khả năng raspividsinh ra các quá trình con của chính nó mà vẫn mồ côi. BTW đủ để thực hiện "ps -aux | grep Z" để xem nó có phải là zombie hay không, và nó nên (đủ) để tránh kill -9quá trình trong kịch bản chính.
Hastur 7/2/2015

4

Để trả lời câu hỏi số 1:

Khi một quá trình sinh ra các quá trình con, mỗi đứa trẻ đều có PID riêng. PPID của mỗi đứa trẻ (id quy trình của cha mẹ) là PID của quy trình cha mẹ của chúng. Nếu cha mẹ chết, thì quá trình con bị mồ côi. Các quy trình mồ côi được tự động chọn bởi quy trình khởi tạo hệ thống có chỉ số PID là 1.


0

Chương trình có thể mở thiết bị camera và bằng cách giết chết nó, bạn đã không cho phép nó dọn dẹp đúng cách, vì vậy bây giờ nó bị kẹt.

Một vài quan sát:

  • Nói chung, không nên giết chương trình bằng cách bắt đầu bằng -9 trừ khi bạn biết bạn đang làm gì. Chỉ cần giết bình thường (không có tùy chọn) là ổn.
  • Không cần phải thực hiện bất kỳ hành vi giết người nào trong kịch bản của bạn cả. Bạn đã chuyển qua -t 15000chương trình để chỉ định thời lượng của video, do đó, lần giết đầu tiên là không cần thiết. Việc giết thứ hai cũng không cần thiết vì shell sẽ tự thoát khi đến cuối đoạn script. Nếu chương trình không tự thoát (như vậy), thì bạn đã gặp vấn đề khác.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.