美文网首页
Nodejs spawn 之stdio

Nodejs spawn 之stdio

作者: 黑曼巴yk | 来源:发表于2019-10-15 11:56 被阅读0次

spawn,exec,execFile和fork关系

exec 
  │
execFile         fork
  │               │     
  └─────spawn─────┘          用户层面
           │
-----------│------------------------
           │
           │                  nodejs内部
           │                   
     spawn(位于lib/internal/child_process.js)

从上图可以看出,在用户层面其他的三个函数都调用了child_process.spwan

子进程的stdio(标准输入输出)

  1. options.stdio的值是字符串时,有以下几种取值
  • pipe:相当于['pipe', 'pipe', 'pipe'],子进程的stdio和父进程的stdio通过管道进行连接
  • ignore:相当于['ignore','ignore', 'ignore'],子进程的stdio绑定到/dev/null,丢弃数据的输入输出。
  • inherit:继承父进程相关的stdio,等同于[process.stdin,process.stdout,process.sterr]或者[0,1,2],此时子进程的stdio都是绑定在同一个地方。
  1. 当options.stdio值是数组的时候,前三个元素分别代表stdin,stdout,stderr。如果数组的元素大于3,则会在父子进程之间建立额外的通讯通道,他们可能是下面的值.
  • pipe 通过管道进行通讯,管道两端分别连接父子进程,父进程可以通过subprocess.stdin,subprocess.stdout,subprocess.stderr来引用管道的一端。子进程可以通过process.stdin, process.stdout, process.stderr来引用另外一端
  • ipc:额外的通讯通道,通过ipc channel通讯
  • stream:通过nodejs 的stream 对象通讯,对象底层文件描述符代表一个文件。如:socket,tty,本地文件
  • null, undefined,对于前三个元素,他们会设置为pipe,剩下的元素会设置为ignore

例子

  1. pipe
    绑定到父进程的process.stdio中
const child_process = require("child_process");
const script = (function(data) {
  console.log(data);
}).toString();
const node = child_process.spawn("node", ["-e", `( ${script}("pipe,只能通过父进程将它输出") )`], {
  stdio: 'pipe'
});
node.stdout.on('data', data => {
  console.log(data.toString())
})
  1. inherit
const child_process = require("child_process");
const script = (function(data) {
  console.log(data);
}).toString();
child_process.spawn("node", ["-e", `( ${script}("inherit,这一般个会写到控制台") )`], {
  stdio: [process.stdin, process.stdout, process.stderr]
  // 和 stdio: 'inherit'相似
});
  1. 绑定文件描述符(fd)
const child_process = require("child_process");
const fd = require("fs").openSync("./node.log", "w+");
const script = (function(data) {
  console.log(data);
}).toString();

const node = child_process.spawn("node", ["-e", `( ${script}("整数fd,这一般个会写到某个文件") )`], {
  //stdio绑定到文件描述符fd,它代表文件node.log,因此会输出到该文件
  stdio: [process.stdin, fd, fd]
});
  1. 绑定stream
const child_process = require("child_process");
const fd = require("fs").openSync("./node.log", "w+");
const script = (function(data) {
  console.log(data);
}).toString();


const writableStream = require("fs").createWriteStream(null, {
  flags: "a",
  fd,
});
child_process.spawn("node", ["-e", `( ${script}("stream,这一般个会写到某个文件") )`], {
  //输出到流所代表的目的地,注意这个流必须要有文件描述符,否则会失败
  //这个例子中它会输出到文件node.log
  stdio: [process.stdin, writableStream, fd]
});
  1. ipc通道
// parent.js
const child_process = require("child_process");

const node = child_process.spawn("node",['./child.js'], {
  shell:false,
  stdio: ['inherit', 'inherit', 'inherit','ipc']
});

node.send({from: 'parent'});
// child.js
process.on('message', function(m){
  console.log('message from parent: ' + JSON.stringify(m));
});
process.send({from: 'child'});

detached 和守护进程

生成子进程的时候如果传递了detached=true,则使得子进程成为新的sessiongroup的leader

const child_process = require("child_process");
const ping = child_process.spawn("ping", ["localhost"], {
    detached:true,
    stdio: 'ignore'
});
ping.unref();

需要成为守护进程,必须要做到以下几点

  • 子进程必须和父进程分离,即detached=true
  • 默认情况下父进程会等待已分离的子进程,调用subprocess.unref()来取消等待
  • 子进程的IO和父进程不能联系。使用stdio: 'ignore'

refer

https://cnodejs.org/topic/5aa0e25a19b2e3db18959bee

相关文章

网友评论

      本文标题:Nodejs spawn 之stdio

      本文链接:https://www.haomeiwen.com/subject/lnmlmctx.html