node js fork php,Node.js中execFile,spawn,exec和fork简介

Node.js中execFile,spawn,exec和fork简介

Node.js子流程child_process模块提供四种不同方法执行外部应用:

所有这些都是异步,调用这些方法会返回一个对象,这对象是ChildProcess类的实例。

1e60e70526bc1b7bcde5b67abe36763d.png

1. execFile

用于执行一个外部应用,应用退出后会返回一些可选蚕食和带有缓冲输出的callback。

child_process.execFile(file[, args][, options][, callback])

文件 将要执行外部应用的可执行文件的路径或名称

参数 是字符串数组

可选 

cwd  子流程当前工作目录

env  key-value环境值对

encoding  (默认: ‘utf8’)

timeout  (Default: 0)

maxBuffer  标准输入或输出的大量数据 (in bytes) – 如果超过子流程会被杀死 (Default:200\*1024)

killSignal  (Default: ‘SIGTERM’)

uid  流程的用户标识符 (See setuid(2).)

gid  流程的群组标识符(See setgid(2).)

当外部应用存在时,Node程序将携带参数"-version"被执行,当外部应用退出时,回调函数被调用,回调函数带有子流程的标准输入输出,来自外部应用的标准输出将被内部缓冲保存。

运行下面代码将打印当前node版本:

const execFile = require( 'child_process').execFile;

const child = execFile( 'node', [ '--version'], ( error, stdout, stderr) => {

if ( error) {

console.error( 'stderr', stderr);

throw error;

}

console.log( 'stdout', stdout);

});

node是如何发现外部应用?它是由PATH环境变量,其中会指定一系列目录,可执行的外部应用驻留在这些目录中,如果外部应该被发现存在,无需该外部应用的绝对路径或相对路径就会被定位。

execFile是当需要执行外部应用并获得输出时使用,我们能使用它运行一个图片处理应用将图片从PNG转为JPG格式,我们只关心其成功与否,当外部应用产生大量数据以及我们需要实时使用这些数据时,execFile就不要使用。

2.spawn

spawn 方法会在新的流程执行外部应用,返回I/O的一个流接口。

child_process.spawn(command[, args][, options])

使用案例:

const spawn = require( 'child_process').spawn;

const fs = require( 'fs');

function resize( req, resp) {

const args = [

"-", // use stdin

"-resize", "640x", // resize width to 640

"-resize", "x360

"-gravity", "center", // sets the offset to the center

"-crop", "640x360+0+0", // crop

"-" // output to stdout

];

const streamIn = fs.createReadStream( './path/to/an/image');

const proc = spawn( 'convert', args);

streamIn.pipe( proc.stdin);

proc.stdout.pipe( resp);

}

上面是一个express.js控制器函数中代码,我们使用流从一个图片文件读取,然后使用spawn方法生成convert程序,我们使用图片流喂给ChildProcess proc,只要这个proc对象产生数据,我们写入数据到一个可写的流中,用户无需等待整个图片转换完毕就能立即看见图片。

spawn返回一个对象流,对于输出大量数据然后需要读取的应用适合,因为是基于流,所有流好处有:

低内存损耗

自动处理后压back-pressure

在缓冲块中懒生产或消费数据

基于事件且非堵塞

缓冲可以让你超过V8 heap内存限制

3.exec

这个方法将会生成一个子shell,能够在shell中执行命令,并缓冲产生的数据,当子流程完成后回调函数将会被调用,可带有:

当命令成功执行,缓冲的数据

当命令失败,错误信息

child_process.exec(command[, options][, callback])

与execFile 和 spawn相比,exec并没有参数,因为exec允许我们在shell中执行多个命令,当使用exec时,我们如果需要传输参数到命令行,它们应该作为整个命令字符串的一部分。

下面代码将会输出当前目录下所有递归条目:

const exec = require( 'child_process').exec;

exec( 'for i in $( ls -LR ); do echo item: $i; done', ( e, stdout, stderr)=> {

if ( e instanceof Error) {

console.error( e);

throw e;

}

console.log( 'stdout ', stdout);

console.log( 'stderr ', stderr);

});

当在一个shell中运行命令,我们能实现在shell中所有功能,比如管道 重定向:

const exec = require( 'child_process').exec;

exec( 'netstat -aon | find "9000"', ( e, stdout, stderr)=> {

if ( e instanceof Error) {

console.error( e);

throw e;

}

console.log( 'stdout ', stdout);

console.log( 'stderr ', stderr);

});

上面案例中,node会生成一个子shell,并执行命令: netstat -aon | find “9000”

exec只有需要利用shell功能时才能使用。

4.fork

child_process.fork()方法是child_process.spawn()特殊情况,子流程返回一个ChildProcess对象,这个ChildProcess会有附加通讯通道,允许消息在父子之间来回穿梭。fork方法会打开一个IPC通道,允许Node流程之间传递消息:

如在子流程, process.on(‘message’) 和 process.send(‘message to parent’) 能被用来接受和发送数据

入在父流程, 使用child.on(‘message’) 和 child.send(‘message to child’)

每个流程都有自己的内存,都有它们自己的V8实例,启动至少30毫秒,每个大小是10mb

//parent.js

const cp = require( 'child_process');

const n = cp.fork( `${ __dirname }/sub.js`);

n.on( 'message', ( m) => {

console.log( 'PARENT got message:', m);

});

n.send({ hello: 'world' });

//sub.js

process.on( 'message', ( m) => {

console.log( 'CHILD got message:', m);

});

process.send({ foo: 'bar' });

因为Node主流程是单线程的,长期运行任务如计算等会堵塞主流程,因此,进来的请求不能被处理,应用变得不可响应,将这些长期运行任务放入主流程之外运行,fork一个新的node流程专门处理,这样主流程能够进行处理进来的请求保持可响应性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值