我编写的C程序使用fork(2)和execl(3)来运行ssh以进行端口转发。 ssh在后台运行-f选项。
当C程序退出时,我希望它将SIGTERM发送到它产生的ssh实例。
我试过了
// creating the ssh process
ssh_pid = fork();
if (ssh_pid == 0)
execl("/usr/bin/ssh", "/usr/bin/ssh", "-f", other options, NULL)
// ...
printf("Killing %d\n", ssh_pid); // <--- output the PID
kill(ssh_pid, 15);
sleep(1); // give it a chance to exit properly
if (kill(ssh_pid, 0) == 0)
kill(ssh_pid, 9); // the "shotgun" approach
然而,这并不起作用(即使使用SIGKILL)。
如果我在程序退出之前运行ps
ps aux | grep ssh | grep -v sshd | grep -v grep
我看到这样的事情:
user 27825 0.2 0.0 0 0 pts/0 Z+ 18:23 0:00 [ssh] <defunct>
user 27834 0.0 0.0 41452 1176 ? Ss 18:23 0:00 /usr/bin/ssh -f [other options]
当程序打印PID时它会被杀死,我看到了:
Killing 27825
随后重复ps给了我:
user 27834 0.0 0.0 41452 1176 ? Ss 18:23 0:00 /usr/bin/ssh -f [other options]
似乎原始的ssh已经分叉,以便成为后台进程。
所以我改变了我的调用kill(2)来尝试杀死原始ssh产生的所有进程:
kill(-ssh_pid, 15);
但这似乎没有效果。我怀疑是因为原来的ssh不再是背景ssh的父级。
那么,我如何安全地杀死背景ssh?它甚至可能吗?
答案 0 :(得分:0)
我刚刚发现的解决方案是根本不使用-f选项,而是自己为ssh提供背景。
ssh_pid = fork();
if (ssh_pid == 0)
{
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
execl("/usr/bin/ssh", "/usr/bin/ssh", other options, NULL);
}
因为当ssh获得-f选项时会创建一个子节点,并且发送给父节点的信号不会传递给子节点。