1
black11black 2020-12-29 18:41:48 +08:00
提一个思路,开一个子线程运行 terminal,通过 ps 命令获取完整进程树,Linux 中应该不算繁重操作,效率可以。
|
2
emSaVya 2020-12-29 18:45:54 +08:00
进程组
|
3
codehz 2020-12-29 18:54:11 +08:00 1
得区分系统,windows 10 下大概可以使用 job 对象配合 silo 隔离
linux 可以用 pid namespace 隔离 |
4
zictos OP @black11black #1
@emSaVya #2 能识别是哪个子进程下面的子进程吗?因为可能有多个进程,并且不同进程下面都有子进程,而我只需要结束某个子进程以及该子进程下面的子进程。 python 我只知道能直接获取当前进程下面的所有子进程的 pid (子进程下面的子进程好像不行),对于我题的例子来说,能不能直接在主进程 m 处获取子进程 p 下面的所有子进程的 pid 列表呢?然后再分别终止对应 pid 。 或者如果事先对每个子进程进行有规则的命名,有没有办法通过名称来达到直接终止进程的目的呢? |
5
zictos OP 笨办法不是没有,比如每创建一个子进程就把子进程的 pid 以及归属哪个父进程的信息写入全局变量中或写入数据库或者写入文本中,然后结束时一个个判断 pid 属于哪个分组并且判断是否存在就行了。只是不知道有没有更简单的,可能有,但是没发现。另外如果是第三方模块创建的子进程这么做就不行了
|
6
tonic 2020-12-29 19:30:27 +08:00
|
7
fish267 2020-12-29 19:33:41 +08:00
1. 子线程,带个是否退出标志,自己轮询
2. thread.join() |
8
Jirajine 2020-12-29 19:34:04 +08:00
psutil
|
9
tonic 2020-12-29 19:36:58 +08:00
似乎跟你场景有点差别, 不过可以参考下自己封装个 =.=
|
10
codehz 2020-12-29 19:56:57 +08:00 1
跟踪进程的方法有竞争条件,而且还有可能故意逃逸(比如 fork 两次 setsid 就出去了(
思考下 android 的停止运行功能是怎么被绕过的( |
11
lsc 2020-12-29 20:06:36 +08:00
试试执行 shell,kill -9 pstree ?
|
12
black11black 2020-12-29 20:15:06 +08:00
@zictos 参考命令`ps ax -o pid,ppid,cmd`,可以直接构建出树,唯一瑕疵是这是请求全系统的树,浪费了资源。
|
13
yucongo 2020-12-29 23:42:42 +08:00 via Android 1
import psutil
parent_pid = 30437 parent = psutil.Process(parent_pid) for child in parent.children(recursive=True): # or parent.children() for recursive=False .... child.kill() parent.kill() SO 答案 |
14
zictos OP @tonic #6
其实把子进程设为守护进程就可以让子进程在父进程被杀死时自动退出,但守护进程下面不能再创建子进程了。 p = Process(target=test) #创建子进程 p p.daemon = True #把子进程 p 设为守护进程 p.start() |
15
zictos OP @yucongo #13
可用,不过你的代码好像根本描述的效果不一样,我刚自己写着尝试了一下。把下面代码中的“[四空格]”替换成真正的 4 个空格就可以直接运行了 ■■■■■■■■分割■■■■■■■■■■ from multiprocessing import Process import psutil, os, time def test1(): [四空格]print('我是主线程创建的第一个子线程,我的 pid 是%s' % os.getpid()) [四空格]#在第一个子线程下面继续创建子线程 [四空格]p2 = Process(target=test2) [四空格]p2.start() [四空格]time.sleep(1000) def test2(): [四空格]print('我是子线程创建的子线程,是主线程的孙线程,我的 pid 是%s' % os.getpid()) [四空格]#在第二个子线程下面继续创建子线程 [四空格]p3 = Process(target=test3) [四空格]p3.start() [四空格]time.sleep(1000) def test3(): [四空格]print('我是主线程的孙线程创建的子线程,我的 pid 是%s' % os.getpid()) [四空格]time.sleep(1000) if __name__ == '__main__': [四空格]#创建子线程 p1 [四空格]p1 = Process(target=test1) [四空格]p1.start() [四空格]#获取子线程 p1 的 pid [四空格]pid = p1.pid [四空格]#等待 4 秒后获取子线程 p1 下面所有子线程的 pid [四空格]time.sleep(4) [四空格]pidlist = psutil.Process(pid).children(recursive=True) [四空格]print('pid 为%s 下面的所有子线程为%s' % (pid, pidlist)) |
16
zictos OP 15 楼写错了,“进程”二字全部写成了“线程”
|
17
abersheeran 2020-12-30 09:39:17 +08:00
这个事可以是各个进程主动检测自己的父进程是否存活,也可以是各个拥有子进程的父进程在退出前杀死自己所有的子进程。
|
18
JCZ2MkKb5S8ZX9pq 2020-12-30 09:46:24 +08:00
有类似需求,现在用的就是记 pid 的笨办法,蹲一个。
|
19
fuse 2020-12-30 11:59:14 +08:00 via iPhone
cgroup
鼎鼎大名 systemd 实现方式不知道 |
20
zictos OP @abersheeran #17
@JCZ2MkKb5S8ZX9pq #18 15 楼已经解决了,已经可以获取到子进程对象了,杀进程可以再加一个循环 for i in pidlist: ####i.kill() |
21
zictos OP 写成函数,只要传入某个进程的 pid 就可以杀死该进程以及该进程下面的子进程。把 killprocess(pid)中的 pid 替换为要杀的进程的 pid 即可
def killprocess(pid): ****import psutil ****childlist = psutil.Process(pid).children(recursive=True) ****for i in childlist: ********i.kill() ****psutil.Process(pid).kill() |
22
abersheeran 2020-12-30 20:01:45 +08:00
@zictos 学到了。 原来还可以这么获取全部下属进程。
|
24
zictos OP @julyclyde #23
针对 21 楼的代码,childlist 就已经包含了所有子进程对象了,直接用 for 遍历再逐个 kill 自然就是把所有子进程都杀死了。 最后一行 psutil.Process(pid).kill()是杀死 pid 为传入的 pid 的进程,前面的 for 是杀死 pid 下面的子进程、孙进程…… |