我正在尝试实现类似于httpd
开始使用 NodeJS 时的行为。当我们说:
service httpd start
在ps
,我们将看到:
[root@dev ~]# service httpd start
Starting httpd: [ OK ]
[root@dev ~]# ps auxf | grep httpd
root 3395 0.0 0.1 6336 304 pts/0 R+ 12:03 0:00 | _ grep httpd
root 3391 0.0 1.3 175216 3656 ? Ss 12:02 0:00 /usr/sbin/httpd
apache 3393 0.0 0.9 175216 2432 ? S 12:02 0:00 _ /usr/sbin/httpd
请注意httpd
主节点和子节点没有终端(显示的是?
而不是grep
的pts/0
)。
现在。。。我需要一个 IPC 通道,因此我使用 child_process.fork,但无论我做什么,每次我看到终端仍然连接到我的守护程序时。以下是欢迎您进行试验的代码:
c.js
- 控制器
var cp = require('child_process');
var d = cp.fork('d.js', {});
d.on('message', function() {
d.disconnect();
d.unref();
});
d.js
- 守护进程
process.send('ready');
setTimeout(function() {
console.log('test');
}, 10000);
这就是我在终端中看到的:
[root@dev ~]# node c.js # running the control script
[root@dev ~]# ps auxf | grep node # my terminal is interactive again so I check
root 3472 0.0 0.3 103308 864 pts/0 S+ 12:13 0:00 | _ grep node
root 3466 1.1 5.6 648548 14904 pts/0 Sl 12:13 0:00 /usr/bin/node d.js
[root@dev ~]# test # appears outta nowhere because d.js still has this stdout
d.js
仍然有我pts/0
,即使它已经与bash
交互,也写test
。
如何解决这个问题并使守护程序删除终端?我不在乎哪一边(c.js
或d.js
)对代码进行调整,我控制两者,但我需要那个 IPC 通道,因此这必须通过 fork
来完成。
可以通过放弃fork
而支持spawn
来解决。然后可以将相同的代码重写为:
var cp = require('child_process');
var d = cp.spawn(process.execPath, ['./d.js'], {
detached: true,
stdio: ['ignore', 'ignore', 'ignore', 'ipc']
});
d.unref();
d.disconnect();
stdio
部分是fork
内部的工作方式。我不知道为什么他们决定不公开完整的阵列,而是只给出silent
.
然后d.js
在开始时将没有终端(它将/dev/null
- 与httpd
相同)。未在 Windows 上测试。