2

在 Linux/C++ 库中,我通过 system() 调用启动了一个进程,

system("nohup processName > /dev/null&");

这似乎适用于一个自行退出的简单测试应用程序,但如果我从获取终止信号的 Nodejs/V8 扩展内部使用它,则子进程将被终止。我确实发现正在运行,

system("sudo nohup processName > /dev/null&");

将 sudoers 文件设置为不需要密码,即使在父进程(节点)退出时也可以运行。有没有办法完全分离子进程,以便发送给父进程和父进程退出的信号不再对子进程产生影响?最好在 system() 调用中,而不是需要获取进程 ID 并对其进行处理。

4

2 回答 2

4

从父进程分离的过程很简单:在子shell的后台运行命令setsid(因此它在新会话中启动),将标准输入、输出和错误重定向到/dev/null(或其他地方,视情况而定)。因为system()启动了一个新的shell,就相当于这样一个子shell,所以

system("setsid COMMAND </dev/null >/dev/null 2>/dev/null &");

正是需要的。在 shell 脚本中,等价于

( setsid COMMAND </dev/null >/dev/null 2>/dev/null & )

(Shell 脚本需要一个子shell,否则COMMAND将在当前shell 的作业控制下。使用时这并不重要system(),因为无论如何它都会为命令启动一个新的shell;当命令退出时,shell 将退出。)

重定向是必要的,以确保COMMAND当前终端没有打开的描述符。(当终端关闭时,会向所有此类进程发送一个 TERM 信号。)这意味着标准输入、标准输出和标准错误都必须重定向。上述重定向适用于 Bash 和 POSIX shell,但可能不适用于旧版本的/bin/sh. 特别是,它应该适用于所有 Linux 发行版。

setsid开始一个新的会话;成为COMMAND自己的流程组的流程组负责人。信号可以指向单个进程,也可以指向进程组中的所有进程。终止信号通常被发送到整个进程组(因为一个应用程序在技术上可能由多个相关进程组成)。如果父进程所属的进程组被进程组范围的信号杀死,则启动新会话确保COMMAND不会被杀死。

于 2012-10-18T10:12:13.627 回答
2

我的猜测是整个进程组都被杀死了。您可以尝试setpgid在孩子中启动一个新的进程组。第一步应该是摆脱system和使用forkand execveor posix_spawn

于 2012-10-18T02:35:42.307 回答