在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行
Posted
技术标签:
【中文标题】在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行【英文标题】:Make child process spawned with system() keep running after parent gets kill signals and exits 【发布时间】:2012-10-17 23:52:58 【问题描述】:在 Linux/C++ 库中,我通过 system() 调用启动一个进程,
system("nohup processName > /dev/null&");
这似乎适用于一个自行退出的简单测试应用程序,但如果我从一个收到终止信号的 Nodejs/V8 扩展内部使用它,子进程就会被终止。我确实发现它正在运行,
system("sudo nohup processName > /dev/null&");
将 sudoers 文件设置为不需要密码,即使在父进程(节点)退出时也可以运行。有没有办法完全分离子进程,以便发送给父进程和父进程退出的信号不再对子进程产生影响?最好在 system() 调用中,而不是需要获取进程 ID 并对其执行某些操作。
【问题讨论】:
也许是值得信赖的双分叉执行器? 为此使用sudo
似乎是一个非常糟糕的主意
是的,这并不是一个解决方案,我只是将其记录为观察。虽然我想到了使用 sudo 将用户切换到已经运行该进程的同一用户。
避免使用system(3)
启动这样的进程。你应该使用fork(2)
& execve(2)
或者daemon(3)
。阅读advancedlinuxprogramming.com
【参考方案1】:
与父进程分离的过程很简单:在setsid
下运行命令(因此它在新会话中启动),将标准输入、输出和错误重定向到/dev/null
(或其他地方,视情况而定) ,在子shell的背景中。因为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
不会被杀死。
【讨论】:
【参考方案2】:我的猜测是整个进程组都被杀死了。你可以在子进程中尝试setpgid
来启动一个新的进程组。第一步应该是摆脱system
并使用fork
和execve
或posix_spawn
。
【讨论】:
以上是关于在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行的主要内容,如果未能解决你的问题,请参考以下文章