终止由 execl 启动的进程

终止由 execl 启动的进程

我正在使用 execl 从 C 程序运行 nmap:

execl("/bin/sh","sh","-c","sudo nmap -sS -A 192.168.0.1/24",NULL);

我在另一个 shell 窗口中运行 HTOP,并且看到我的execl启动 PID:

2339 for command "nmap -sS .."
2335 for command "sudo nmap -sS .."
2334 for command "sh .."

子进程 PID 是 2334。Nmap 需要很长时间才能完成,如果我想终止所有三个进程,我可以kill 2339从 shell 发出。所有2339、2335和2334随后从HTOP监控程序中消失。

我想做的是在我的 C 程序中发出kill(2339, ...) 并杀死所有内容,就像我可以从 shell 中执行的那样。我的问题是如何获得 PID 2339?在本例中,我的 childPID 为 2334。

答案1

首先,您可以通过删除其中一个中间流程来简化您的问题:您没有理由使用这里sh -c来启动您的流程。事实上,如果您的实际命令行是动态构建的,那么它可能不太安全。代替:

execl("/bin/sh","sh","-c","sudo nmap -sS -A 192.168.0.1/24",NULL);

你应该这样做:

execlp("sudo", "sudo", "nmap", "-sS", "-A", "192.168.0.1/24", NULL);

现在你只有两个进程:sudonmap本身。您知道父进程 ( ) 的进程 ID sudo,但不知道子进程 ( nmap) 的进程 ID。但这并不重要,因为您可以使用以下功能sudo:杀死父级(使用SIGTERM),它会将信号转发给您的子级。

您最后剩下的问题与您提出的问题没有直接关系,但无论如何您可能无权终止这些进程中的任何一个!由于sudo涉及到其目的是提升其特权,因此您可能一开始就没有发送它或其子信号的权限。

答案2

一种方法是从父进程到sudo kill子进程,假设授予该权限。pidsudoers

#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void sudokill(pid_t tokill);

int main(void)
{
    pid_t pid;

    pid = fork();
    switch (pid) {
    case -1:
        err(1, "fork() failed");
    case 0:
        execlp("sudo", "sudo", "sleep", "999", (char *) NULL);
        err(1, "execlp() failed");
    default:
        sleep(7);
        sudokill(pid);
    }
    exit(EXIT_SUCCESS);
}

void sudokill(pid_t tokill)
{
    char *killstr;
    int status;
    pid_t pid;

    if (asprintf(&killstr, "%d", tokill) < 0)
        err(1, "asprintf() failed");

    pid = fork();
    switch (pid) {
    case -1:
        err(1, "fork() failed");
    case 0:
        execlp("sudo", "sudo", "kill", killstr, (char *) NULL);
        err(1, "execlp() failed");
    default:
        wait(&status);
    }

    free(killstr);
}

相关内容