我正在使用 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);
现在你只有两个进程:sudo
和nmap
本身。您知道父进程 ( ) 的进程 ID sudo
,但不知道子进程 ( nmap
) 的进程 ID。但这并不重要,因为您可以使用以下功能sudo
:杀死父级(使用SIGTERM
),它会将信号转发给您的子级。
您最后剩下的问题与您提出的问题没有直接关系,但无论如何您可能无权终止这些进程中的任何一个!由于sudo
涉及到其目的是提升其特权,因此您可能一开始就没有发送它或其子信号的权限。
答案2
一种方法是从父进程到sudo kill
子进程,假设授予该权限。pid
sudoers
#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);
}