从父进程分离的过程很简单:在子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
不会被杀死。