child_process中spawn和exec方法的使用

2019-01-29 14:33:07

child_process是nw.exe的一个内置模块,通过它可以实现创建多线程,并可实现主线程和子线程之间的通信。child_process模块中主要使用有两个方法spawn和exec,这两个方法都可以用来创建子线程。除了spawn和exec外,child_process模块还有execFile,fork,spawnSync,execFileSync,execSync,它们都是基于spawn的不同封装。


使用child_process模块模块不外乎几种情况:1.调用系统命令行 2.打开第三方软件 3.打开第三方软件并实现通信。


(一)child_process模块 Demo


var cp = require('child_process'); //子进程

var result = "";

 

cp.exec("ipconfig", function(error, stdout, stderr) {

console.log("error", error);

console.log("stdout", stdout);

console.log("stderr", stderr);

});

 

result = cp.spawn('cmd.exe', ['/s', '/c', 'ipconfig']);

result.on('close', function(code) {

console.log('child process exited with code :' + code);

});

result.stdout.on('data', function(data) {

console.log('stdout: ' + data);

});

result.stderr.on('data', function(data) {

console.log('stderr: ' + data);

});


以上两个方法无论是spawn还是exec都通过调用了命令行ipconfig获取系统相关IP信息,两者得到的结果是一样的,本Demo可看出只不过两种调用的写法不一样而已。



(二)spawn和exec的区别

(1)两者实现的写法不同,参照上述Demo即可了解。


(2)spawn在执行时会返回一个stdout和stderr流对象,为边执行边返回。exec是在执行完成后返回一个完整的buffer,这个buffer的大小应该是200k。如果子进程返回的数据大小超过了200k,程序将会崩溃,同时显示错误信息"Error:maxBuffer exceeded"。


(3)spawn在执行完成后会抛出close事件监听,并返回状态码,通过状态码可以知道子进程是否顺利执行。exec只能通过返回的buffer去识别完成状态,识别起来较为麻烦。


上述(一)中已经介绍如何调用系统命令行,下面为打开第三方软件的例子,如使用exec打开QQ程序:



var cp = require('child_process'); //子进程

var path = "";//第三方根目录

cp.exec(path + "\\QQ.exe", function(error, stdout, stderr) {

console.log("error", error);

console.log("stdout", stdout);

console.log("stderr", stderr);

});


打开第三方软件并通信,如使用spawn,调用ffmpeg进行转码:


var cp = require('child_process'); //子进程

var path = ""; //第三方根目录

result = cp.spawn(path + "\\ffmpeg.exe", ['-y', '-i', "1.mpg", '1.mp4']);

result.on('close', function(code) {

console.log('child process exited with code :' + code);

});

result.stdout.on('data', function(data) {

console.log('stdout: ' + data);

});

result.stderr.on('data', function(data) {

console.log('stderr: ' + data);

});


综上所述,能使用spawn实现子进程的尽量使用spawn,其一可以避免不必要的异常错误,其次在调用上较为规范。如果需要通过child_process模块反复调用某个第三方软件或程序,注意一点就是避免重复打开(如子进程进入死循环,或者子进程没结束就又重复打开),过多的子进程会消耗系统的资源,严重时可能会造成卡顿,死机等情况。如果遇到这种情况,可以通过.kill();方法停止线程运行。如上述使用spawn的例子中均有一个result,停止线程方法为:


result.kill();


如需强制关闭,如强制关闭ffmpeg.exe进程,可用:


function killFFmpeg() {

cp.exec('tasklist | find "ffmpeg.exe"', function(error, stdout, stderr) {

if(stdout != "") {

cp.exec("taskkill /f /t /im ffmpeg.exe", function(error, stdout, stderr) {});

}

});

};


  • 2017-03-16 13:37:58

    mysql中如何使用INSERT一次性插入多条记录

    看到这个标题也许大家会问,这有什么好说的,调用多次INSERT语句不就可以插入多条记录了吗!但使用这种方法要增加服务器的负荷,因为,执行每一次 SQL服务器都要同样对SQL进行分析、优化等操作。

  • 2017-03-18 20:17:09

    Linux上vi(vim)编辑器使用教程

    vi(vim)是上Linux非常常用的编辑器,很多Linux发行版都默认安装了vi(vim)。vi(vim)命令繁多但是如果使用灵活之后将会大大提高效率。vi是“visual interface”的缩写,vim是vi IMproved(增强版的vi)。在一般的系统管理维护中vi就够用,如果想使用代码加亮的话可以使用vim。下面vps侦探整理一下vi的使用教程:包含vi的基本介绍、使用模式、文件的打开关闭保存、插入文本或新建行、移动光标、删除、恢复字符或行、搜索等等,算是一篇比较适合新手学习vi的教程。

  • 2017-03-20 17:31:55

    Nodejs express 获取url参数,post参数的三种方式

    127.0.0.1:3000/index,这种情况下,我们为了得到index,我们可以通过使用req.params得到,通过这种方法我们就可以很好的处理Node中的路由处理问题,同时利用这点可以非常方便的实现MVC模

  • 2017-03-20 17:33:55

    forever守护nodejs进程

    这样可以正常启动应用,但是如果断开客户端连接,应用也就随之停止了。也就是说这样的启动方式没有给应用一个守护线程。

  • 2017-03-22 14:00:51

    Andriod Studio结合Visual Studio Emulator for Android调试Android App

    说到开发就绕不开调试程序,调试Android App我们有2种选择,真机调试和模拟器调试:真机调试相对简单,就不做介绍了,还有一方面原因是由于安卓手机一旦插到电脑上,开始ADB调试后,各种的流氓软件净是往手机上装垃圾应用,妈蛋的;随后就试了几次Android Studio的模拟器之后,无限感慨,真尼玛的卡,卡,卡,,,是可忍孰不可忍.....

  • 2017-03-22 16:26:36

    最全面的Android Webview详解

    现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝、京东、聚划算等等,如下图

  • 2017-03-23 22:29:52

    Android开发中Handler的经典总结

    当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件,进行事件分发。