LabHub
学习 学习路径 课程

Linux 基础

操作进程与信号

在 LabHub 中继续学习

目标

向进程发送信号,确认暂停、终止、强制终止之间有何不同,并亲手制造僵尸进程,观察它如何产生。

为什么重要

‘进程杀不掉’这种报告,至少把四种不同情况混为一谈:应用程序可能捕获并忽略了 SIGTERM;进程可能处于 D 状态,导致信号处理本身被延后;也可能早已结束,只是作为僵尸进程残留下来。每种情况的处理方式完全不同,因此首先要问清楚停在哪一层。此外,只有 SIGKILL 和 SIGSTOP 无法被捕获,这是内核留给管理员的最后手段——因此 SIGKILL 不会给程序清理的机会,对于数据库或队列消费者而言,等同于直接拔掉电源。

步骤

  1. 在后台启动 sleep 3600,并将其 PID 写入 /root/proc/pid.txt
  2. 将该进程的父 PID 写入 /root/proc/ppid.txt
  3. 启动另一个 sleep 并将其暂停(SIGSTOP),把 PID 写入 /root/proc/stopped_pid.txt,再把暂停后的单个状态字符写入 /root/proc/state_stopped.txt
  4. 启动另一个 sleep,先把 PID 写入 /root/proc/killed_pid.txt,然后用 SIGTERM 将其终止。
  5. 创建 /root/proc/trapper.sh。收到 SIGTERM 时,必须在 /root/proc/term.log 中追加一行 caught SIGTERM。为脚本添加执行权限并放到后台运行,再发送 SIGTERM,确认日志是否增加。
  6. 再次启动 trapper.sh,这次发送 SIGKILL。发送前将 term.log 的行数写入 /root/proc/before_kill.txt,发送后将行数写入 /root/proc/after_kill.txt。实验结束时不能有任何 trapper.sh 仍在运行。
  7. 创建一个子进程,让子进程先结束,而父进程不执行 wait 并继续存活。将该父进程的 PID 写入 /root/proc/zombie_parent.txt
  8. 创建 /root/proc/cleanup.sh <패턴>。它必须终止命令行与该模式匹配的所有进程,并以 terminated=<n> 格式输出一行终止数量。不能统计或终止脚本自身。

提示

启动后台进程

在后台启动 sleep 3600,并将其 PID 写入 /root/proc/pid.txt

在命令末尾加上 & 就会在后台运行。紧接着,$! 中就保存着该进程的 PID。

查看父 PID

将该进程的父 PID 写入 /root/proc/ppid.txt

查看 /proc//status 中的 PPid 行,或使用 ps -o ppid= -p 。

暂停进程

启动另一个 sleep 并将其暂停(SIGSTOP),把 PID 写入 /root/proc/stopped_pid.txt,再把暂停后的单个状态字符写入 /root/proc/state_stopped.txt

暂停与终止不同。暂停的进程仍留在进程列表中,只是状态字符会改变。

礼貌地请求终止

启动另一个 sleep,先把 PID 写入 /root/proc/killed_pid.txt,然后用 SIGTERM 将其终止。

kill 默认发送 SIGTERM。发送前请先把 PID 写入文件。

捕获 SIGTERM 的脚本

创建 /root/proc/trapper.sh。收到 SIGTERM 时,必须在 /root/proc/term.log 中追加一行 caught SIGTERM。为脚本添加执行权限并放到后台运行,再发送 SIGTERM,确认日志是否增加。

以 trap '命令' TERM 的形式设置处理程序。脚本必须不退出并保持运行,才能接收信号。

SIGKILL 无法被捕获

再次启动 trapper.sh,这次发送 SIGKILL。发送前将 term.log 的行数写入 /root/proc/before_kill.txt,发送后将行数写入 /root/proc/after_kill.txt。实验结束时不能有任何 trapper.sh 仍在运行。

向设置了 trap 的脚本发送 9 号信号,并记录前后日志行数,比较是否增加。

制造僵尸进程

创建一个子进程,让子进程先结束,而父进程不执行 wait 并继续存活。将该父进程的 PID 写入 /root/proc/zombie_parent.txt

子进程先结束,而父进程不 wait 并继续存活时,子进程就会成为僵尸。父进程必须保持运行。

基于模式的清理脚本

创建 /root/proc/cleanup.sh <패턴>。它必须终止命令行与该模式匹配的所有进程,并以 terminated=<n> 格式输出一行终止数量。不能统计或终止脚本自身。

先用 pgrep -f 统计,并排除脚本自身。终止后以 terminated= 格式输出数量。