Search code examples
node.jsipcsudospawn

node spawn with sudo cannot use ipc


In my project, I need to create a child process and communicate with it via IPC, at same time, this child process must run as root. So I use cp.spawn('sudo', ...) with IPC channel, but I found the process.send method is undefined.

Here is the code:

file: 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!')

file: child.js

'use strict'

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

process.send('hahaha')

run 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

Update: After I replace cp.spawn('sudo', ...) with cp.spawn(process.execPath, ...), the program will work:

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

Is anyone knowns why IPC doesn't work with sudo?


Solution

  • As mentioned in the documentation:

    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

    Only in the situation what you are spawning is a Node process, the process.send() method would be enabled.

    In your situation, you are spawning a sudo process, and the Node running child.js is argument to sudo rather than spawned from parent.js. So the process.send() won't be enabled, That's why child.js throwed error.

    So the child.send() is actually sended to the sudo process instead of node child.js as expected.

    As you are asking why IPC doesn't work for sudo: I think IPC is working. However, as mentioned above, you are trying to IPC with sudo process which actually doesn't understand or won't make a response to your child.send() action.