在Linux中,我如何使用系统调用杀掉同一会话(具有相同SID)中的所有进程?

3
我正在尝试使用C语言的系统调用来杀掉一个会话(具有相同SID)中的所有进程。我不仅仅想要杀掉指定PGID下的进程,因为我感兴趣的并不是所有进程都拥有相同的PGID,但它们都有相同的SID。
我的研究只找到了这个链接,Graeme已经为脚本做出了很好的回答:https://unix.stackexchange.com/questions/124127/kill-all-descendant-processes 我希望能得到一个回答,如何杀死所有直接子级以及更高兴的是如何杀死会话中的所有子级。
或者我所问的是否有可能?我不感兴趣的解决方案只是列出父进程后代的PID。

4
在Linux上,没有直接结束具有相同SID的进程的内置选项,你唯一的选择就是按照你最后一句话所述进行操作。 - nos
@nos:我想这就是为什么我的研究没有找到任何东西的原因... - Tobias Johansson
好的,但有没有可能以某种方式杀死所有直接子进程(所有具有相同 PPID 的进程)? - Tobias Johansson
只有当它们属于同一进程组时,您才能执行以下操作:1. 终止特定pid。2. 终止进程组中的所有进程。3. 终止您拥有权限的所有进程(您自己用户的所有进程,除非您是root)。4. 当父进程终止时,让子进程自行终止(仅在您可以更改所有相关进程的源代码时才相关)。 - nos
4个回答

1

你始终可以使用 /proc/ 文件系统来查询进程(详见proc(5))。特别地,你可以扫描 /proc/PID/ 目录(其中PID是一些数字名称,如1234,它是相关的pid,因此pid 1234的进程在/proc/1234/伪目录中描述;因此,你可以readdir读取/proc/目录并查找其中的每个数字名称),并检查哪些进程有定义的父pid。你会按顺序阅读伪文件如/proc/1234/status(及其PPid: 行)。也可参见 这个答案那个答案


1
请尝试这样做: pkill -9 -s [会话 ID]

在运行“kill -9”之前,请务必非常小心。最好先运行“pgrep -s [session id]”,然后使用不带“-9”的pkill来优雅地结束进程,并仅在最需要时添加“-9”。 - andrew lorien

0
据我所知,你无法安全地这样做。你只能安全地杀死直接子进程,因为只有对于它们,你才能确定它们的 pid 是准确的。对于任何其他进程,它们的非子进程的 pid 是一个移动目标(尽管非常缓慢移动,除非你在一个极忙碌的系统上,在那里像疯狂生成进程,使 pid 回收非常快)。因此,理论上你可以遍历进程树,例如:
#This will create a nice process tree
(sleep 1000 & ( sleep 1000&  sleep 1000& sleep 1000)&  sleep 1000 )&
#View it with 
ps T --forest
#Or recursively get all the nodes (this should match the corresponding part of the above ps command)
walk_processes() { echo $1; cat /proc/$1/task/$1/children | while read -d ' ' pid; do walk_processes $pid; done;  }
walk_processes $!

但是你不能使用上述方式获取的进程ID来实现安全的“杀死整个进程树”(其中会话是特定类型的进程树)。

你只能杀死会话领导者的直接子进程或它们的整个进程组,但以这种方式被杀死的进程可能无法将杀死信号传递给它们的子组 - 这是你无法安全/可靠地为它们做的事情。以这种方式关闭会话后剩下的进程将被重新分配到init。如果它们是停止的进程组,则没有人可以唤醒它们(这些被称为孤立组),因此init将向它们发送SIGCONT和SIGHUP(这两个信号中,SIGHUP首先被发送)。SIGHUP通常会杀死它们。如果它们有SIGHUP的处理程序,则可能作为守护进程继续运行。

换句话说,如果您想安全地杀死会话领导者的子进程,请防止这些子进程创建子组(使您的会话ID始终与单个进程组ID匹配)。


*这是因为在你成功kill掉自己的子进程后,它会变成僵尸进程,直到你对其进行wait操作,而该僵尸进程会保留pid位置,因此在等待子进程之前,子进程的pid不是一个动态目标(所有其他pid都是)。


0
受到Basile Starynkevitch的启发,我使用了这个简单的循环,然后等待子进程。
/* Searches through all directories in /proc */
while((dent = readdir(srcdir)) != NULL) {
    /* If numerical */
    if (dent->d_name[0] >= '0' && dent->d_name[0] <= '9') {
        /* Take data from /proc/[pid]/stat, see URL below for more info */
        /* http://man7.org/linux/man-pages/man5/proc.5.html */
        sprintf(path, "/proc/%s/stat", dent->d_name);
        stat_f = fopen(path,"r");
        fscanf(stat_f, "%d %*s %*c %d", &pid, &ppid);
        fclose(stat_f);
        /* Kill if shell is parent to process */
        if (shell_pid == ppid) kill(pid, SIGKILL);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接