Node.js使用spawn创建独立终端子进程通信时报ERR_INVALID_FD_TYPE如何解决
解决方案
错误原因
- 你使用的
start是Windows cmd内置命令,执行时会新开一个独立的Shell进程启动Node.js,父进程创建的fd 3管道不会被继承到最终的Node子进程中,导致child.js读取fd 3时因类型未知抛出ERR_INVALID_FD_TYPE错误 - 原代码的stdio管道配置逻辑本身没有问题,问题出在进程继承链断裂,管道没有传递到目标子进程
修复方案(无第三方依赖)
我们改用内置net模块的本地TCP套接字实现跨进程通信,既保留子进程独立终端的特性,又能稳定实现双向通信:
修复后parent.js代码
const spawn = require('child_process').spawn; const net = require('net'); console.log('started parent process...'); // 父进程启动本地TCP服务监听通信 const server = net.createServer((socket) => { const Name = 'general kenobi'; // 向子进程发送数据 socket.write(Name); // 监听子进程返回的数据 socket.on('data', (data) => { console.log('data=>', data.toString()); // 通信完成后清理资源 socket.destroy(); server.close(); child.kill(); }); socket.on('error', () => server.close()); }); // 监听本地随机端口 server.listen(0, '127.0.0.1', () => { const port = server.address().port; // 启动带独立终端的子进程,将端口作为参数传递 const child = spawn('start', ['node', 'child.js', port], { cwd: __dirname, shell: true, detached: true }); child.unref(); });
修复后child.js代码
const net = require('net'); console.log('started child process...'); (async()=>{ await new Promise(r=>setTimeout(r,3000)); try{ // 从启动参数获取父进程监听端口 const port = process.argv[2]; const pipe = net.connect(port, '127.0.0.1'); pipe.on('data',(data)=>{ pipe.write(`hello there ${data}`); pipe.destroy(); }); pipe.on('error',(err)=>console.log(err)); }catch(err){console.log(err)} await new Promise(r => setTimeout(r, 3000)); })();
效果验证
运行node parent.js后会自动弹出子进程的独立终端,3秒后父进程终端会输出预期的data=> hello there general kenobi,之后两个进程自动退出。
内容的提问来源于stack exchange,提问作者user15573857
相关产品推荐
相关产品推荐

