使用 sudo 生成的节点无法使用 ipc

node spawn with sudo cannot use ipc

在我的项目中,我需要创建一个子进程并通过IPC与它通信,同时这个子进程必须运行 root。所以我使用 cp.spawn('sudo', ...) 和 IPC 通道,但我发现 process.send 方法是 undefined.

代码如下:

文件:parent.js

'use strict'

const cp = require('child_process')
const path = require('path')

const script = path.join(__dirname, 'child.js')

let child = cp.spawn('sudo', [process.execPath, script], {
  stdio: ['inherit', 'inherit', 'inherit', 'ipc']
})

child.on('message', msg => {
  console.log('message> ', msg)
})

console.log('parent> parent run!')

文件:child.js

'use strict'

console.log('child> child run!')

process.send('hahaha')

运行 node parent.js

parent> parent run!
Password:
child> child run!
/Users/zoujie.wzj/workbench/child.js:5
process.send('hahaha')
        ^

TypeError: process.send is not a function
    at Object.<anonymous> (/Users/zoujie.wzj/workbench/child.js:5:9)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

更新:将cp.spawn('sudo', ...)替换为cp.spawn(process.execPath, ...)后,程序将运行:

parent> parent run!
child> child run!
message>  hahaha

有人知道为什么 IPC 不能与 sudo 一起使用吗?

尝试删除 所有 inherit,IPC 应该可以工作。

请注意,您的代码不会打印 child 发送的 'hahaha' 消息,因为您没有等待或阻止;所以当你 运行 parent.js 时,它会执行每一行并安静地(干净地)退出。

如文档中所述:

If the child is a Node.js process, the presence of an IPC channel will enable process.send(), process.disconnect(), process.on('disconnect'), and process.on('message') within the child.

https://nodejs.org/api/child_process.html#child_process_options_stdio

只有在生成节点进程的情况下,才会启用 process.send() 方法。

在你的情况下,你正在生成一个 sudo 进程,节点 运行 child.js 是 sudo 的参数而不是从 parent.js 生成.所以 process.send() 不会启用,这就是 child.js 抛出错误的原因。

因此 child.send() 实际上被发送到 sudo 进程,而不是预期的 node child.js

当你问为什么 IPC 对 sudo 不起作用时:我认为 IPC 起作用。但是,如上所述,您正在尝试使用 sudo 进程进行 IPC,但实际上不理解或不会对您的 child.send() 操作做出响应。