问题
我想终止一个名为 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
观察结果:
- 通话正常进行一段时间(2 小时左右),然后就开始挂断。
- 只有物理关闭电源才能解决问题。我无法通过终端重新启动(它也挂了)
我的问题:
- 为什么Linux将父PID指定为1?
- 为什么进程不能被杀死?(我也试过
sudo kill -9 7238
)
答案1
问题
你的脚本可能正在创建僵尸因为你的kill -9
命令;正如建议的那样jjlin 回答在没有强制的情况下突然终止某些进程永远不是一个好的做法。
我们可以从中man bash
读到:
标记为 <defunct> 的进程是死进程(所谓的“僵尸“)剩下的因为他们的父母没有妥善销毁它们. 这些过程将被 init(8) 销毁如果父进程退出。
答案#1:流程在里面有PID 1为此,Linux 为它们分配了 PID 为 1 的父进程(因为它将它们分配给在里面)。
答案#2:它们无法被杀死简单地因为他们只是死的... 如果他们的父母init
可能就足以等待一段时间了。
要从系统中移除僵尸进程,可以使用 kill 命令手动向父进程发送 SIGCHLD 信号。如果父进程仍然拒绝收割僵尸进程,下一步就是移除父进程。当进程失去父进程时,init 将成为其新的父进程。Init 会定期执行 wait 系统调用来收割以 init 为父进程的任何僵尸进程。[1]
万一有一天这个想法出现:以 root 权限进行#kill -9 init
处理的软件相当于物理上将计算机从电网中拔出。[:-)]
然而僵尸进程ps
可以通过命令输出中的“Z”来识别统计列。您可以使用以下行轻松识别它们
ps -aux | grep Z
一些参考资料Linux 僵尸世界:
答案2
回答问题1:
当一个进程产生子进程时,每个子进程都有自己的 PID。每个子进程的 PPID(父进程的 id)是其父进程的 PID。如果父进程死亡,则子进程将变为孤儿进程。孤儿进程将由 PID 为 1 的系统 init 进程自动接收。
答案3
该程序可能打开了摄像头设备,通过强行关闭它,您没有让它正确清理,所以现在它卡住了。
一些观察:
- 除非您知道自己在做什么,否则通常不要以 -9 开头来终止程序。只需正常终止(不带任何选项)即可。
- 您的脚本中根本不需要执行任何终止操作。您已经将
-t 15000
视频的长度传递给程序,因此第一次终止操作应该是不必要的。第二次终止操作也是不必要的,因为当 shell 到达脚本末尾时,它将自行退出。如果程序没有自行退出(应该如此),那么您就遇到了其他问题。
答案4
这是我清理僵尸进程的一些技巧。我需要它,因为一个包的升级脚本一直在等待 killall -pw,但该进程是僵尸进程,因为 gnome-session 没有对其执行“waitpid”。所以我手动做了:
gdb
(gdb) attach <zombie parent PID>
(gdb) call waitpid( <zombie PID>, 0, 0)
(gdb) detach
就这样!僵尸进程被清理了!