Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)...

代码示例支持
平台: Centos 6.3
Python: 2.7.14
Github: https://github.com/baidu/CUP

1.1 踩坑案例

pid, ppid是大家比较常见的术语, 代表进程号,父进程号. 但pgid是个什么鬼?

了解pgid之前, 我们先复习下:

  • 进程篇其一
    • 里面场景是: 一个进程通过os.system或者Popen家族启动子进程
    • 后通过杀死父进程的方式无法杀死它的连带子进程
    • 我们通过其他方式进行了解决

这个场景还有个后续就是:

  • 如果这个子进程还有孙子怎么办?
  • 它还有孙子的孙子怎么办?

这个就是今天我们遇到的坑, 怎么处理孙子进程. 大家注意, 不仅是Python会遇到这个问题, 其他语言包括 Shell 都一样会遇到这种"孙子"进程怎么进程异常处理的问题.

1.2 填坑解法

本期的坑位解法其实有两种, 第一种比较暴力, 简称穷尽搜索孙子法.

a. 穷尽搜索孙子法, 代码示例

关键点:

  • 使用cup.res.linux中的Process类, 获得该进程所有的子孙进程
  • 使用kill方法全部杀死
from cup.res import linux
pstatus = linux.Process(pid)
for child in pstatus.children(recursive=True):
    os.kill(child, signal.SIGKILL)

b. 获得该进程的 PGID, 进行 kill 操作

b1. 先讲个 shell 操作的做法, 使用ps 获取进程的pgid, 注意不是pid

# 以mysqld为例, 注意 pgid 项
ps -e -o uid,pid,gid,pgid,cmd|grep mysql

结果:

  • 注意其中第三列, 该进程和子进程都使用了同样的pgid 9779

    9790 0 9779 /bin/sh /usr/bin/mysqld_safe --datadir=/home/maguannan/mysql/mysql/....

    10171 501 9779 /home/maguannan/bin/mysqld --basedir=/home/maguannan/mysql/....

  • 通过kill -9 -9779的方式可以杀死该pgid底下的所有子孙进程

b2. 在讲 Python 里的处理方式

import os
import signal
from cup.res import linux
pstatus = linux.Process(pid)
os.killpg(pstatus.getpgid(), signal.SIGKILL)

1.3 坑位分析

进程组特性

a. 在*unix 编程中, 进程组(man getpgid)概念是个很重要但容易被忽略的内容

  • 进程组ID (pgid) 标记了一系列相关的进程
  • 进程组有一个组长进程, 一般组长进程 ID 等于进程组 ID
  • 进程组只要任一进程存在, 进程组就存在. 进程组存在与否与组长死活无关
  • 可以通过setpgid方式设置一个进程 pgid
    • 一个进程只能为自己或者子进程设置进程组 id
    • 子进程一旦执行了exec函数, 它就不能改变子进程的进程组 id

b. 进程组内的所有成员会收到来自相同的信号

引用 wikipedia 原文:

  a process group is used to control the distribution of a signal; when a signal is directed to a process group, the signal is delivered to each process that is a member of the group.

坑位解决

  • 由于进程组拥有以上的特性, 进程组内的进程可以被当做相同的处理单元
    • 默认子进程与父进程拥有同样的进程组
    • 组内每个进程收到相同的信号)
  • 使用kill发送信号 SIGKILL 即可满足杀死所有子进程的目的

1.4.1 技术关键字

  • pgid 进程组
  • pid, ppid 进程ID, 父进程ID

下期坑位预告

  • 踩坑之旅进程篇其四: 一次性踩透uid, euid, gid, egid的坑坑洼洼

转载于:https://www.cnblogs.com/mythmgn/p/10945941.html

<think>题目要求终止正在运行的进程,一般使用什么命令。选项为A.stop, B.break, C.kill, D.stay。 在Linux/Unix系统中,终止进程通常使用`kill`命令。`kill`命令可以向进程发送信号,默认情况下发送SIGTERM(15)信号,请求进程终止。如果进程不响应,可以使用SIGKILL(9)信号强制终止。 因此,正确答案是C.kill。 其他选项解释: - A.stop:在Linux中,stop命令通常用于停止服务(如通过init系统或systemd),但并非用于终止任意进程。 - B.break:break是编程语言中用于跳出循环的关键字,不是系统命令。 - D.stay:这不是一个用于进程管理的标准命令。 下面给出一个使用kill命令终止进程的示例: ```bash # 查找进程ID(PID)的常用方法 # 例如,终止名为"my_process"的进程 # 方法1:使用ps和grep ps aux | grep my_process # 假设输出中包含: # user 1234 0.0 0.1 12345 6789 pts/0 S+ 12:34 0:00 my_process # 使用kill命令终止PID为1234的进程 kill 1234 # 如果进程不响应,可以使用SIGKILL强制终止 kill -9 1234 # 方法2:使用pkill(通过进程名终止) pkill my_process # 方法3:使用killall(通过进程名终止) killall my_process ``` 注意:在使用kill命令时,需要确保你有权限终止该进程。通常,普通用户只能终止自己的进程,而root用户可以终止任何进程。 §§相关问题§§: 1. Linux中有哪些常用的进程管理命令? 2. 如何查看进程的状态信息? 3. kill命令发送的信号有哪些?各自的作用是什么? 4. 如何在Windows系统中终止进程?</think>### 终止进程的正确命令 正确答案是 **C. kill** #### 详细解释 在 Linux/Unix 系统中,`kill` 命令用于向进程发送信号以终止其运行。这是最标准、最常用的进程终止方式,具有以下特点: 1. **核心功能**: - 向指定进程发送信号(默认发送 SIGTERM 信号) - 允许强制终止无响应的进程(SIGKILL 信号) - 支持精确控制进程树 2. **选项分析**: | 命令 | 作用 | 适用场景 | |------|------|----------| | **kill** | **终止进程** | **标准终止方式** | | stop | 系统服务控制 | 停止系统服务(如 `systemctl stop`) | | break | 编程关键字 | 跳出循环(非系统命令) | | stay | 无效命令 | 无实际用途 | #### 使用示例代码 ```bash #!/bin/bash # 创建测试进程 sleep 300 & TEST_PID=$! echo "测试进程已启动 (PID: $TEST_PID)" # 1. 正常终止进程 (SIGTERM=15) echo "=== 正常终止进程 ===" kill $TEST_PID sleep 0.5 ps -p $TEST_PID > /dev/null && echo "进程仍在运行" || echo "进程已终止" # 2. 启动新进程 sleep 300 & TEST_PID=$! # 强制终止进程 (SIGKILL=9) echo "=== 强制终止进程 ===" kill -9 $TEST_PID ps -p $TEST_PID > /dev/null && echo "终止失败" || echo "强制终止成功" # 3. 终止整个进程组 echo "=== 终止进程组 ===" sleep 300 | sleep 300 & PGID=$(ps -o pgid= -p $!) kill -- -$PGID # 注意负号表示进程组ID ``` #### 关键用法说明: 1. **查找进程ID**: ```bash # 通过进程名查找 pgrep -f "process_name" # 通过端口查找 lsof -i :8080 | awk 'NR==2 {print $2}' ``` 2. **常用终止方式**: ```bash # 优雅终止 (允许清理) kill PID # 强制终止 (立即结束) kill -9 PID # 终止所有同名进程 pkill process_name # 终止整个进程killall -g process_name ``` 3. **信号类型参考**: | 信号编号 | 信号名 | 作用 | |---------|--------|------| | 1 | SIGHUP | 挂起进程(重新加载配置) | | 2 | SIGINT | 键盘中断 (Ctrl+C) | | **9** | **SIGKILL** | **强制终止** | | **15** | **SIGTERM** | **默认终止信号** | | 18 | SIGCONT | 继续运行暂停的进程 | | 19 | SIGSTOP | 暂停进程 (Ctrl+Z) | #### 安全终止最佳实践: ```bash # 1. 尝试正常终止 kill -15 PID # 等待5秒 sleep 5 # 2. 检查是否终止 if ps -p $PID > /dev/null; then echo "进程未响应,强制终止" kill -9 $PID fi # 3. 确认终止结果 [ $? -eq 0 ] && echo "终止成功" || echo "终止失败" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值