当前位置:嗨网首页>书籍在线阅读

03-child_process.exec和child_process.execFile

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

8.1.1 child_process.exec和child_process.execFile

除了创建一个子进程外,你还可以用 child_process.exec()child_ process.execFile() 来执行命令。

c``hild_process.exec() 方法和 child_process.spawn() 方法很像,只不过 spawn() 会在程序运行之后返回一个流,如例8-1所示。而 child_process.exec() 函数则像 child_process.execFile() 一样,将结果缓存起来。 exec() 会启动一个新的shell来运行进程,而 child_process.execFile() 会直接运行进程。这使得 child_process.execFile() 比设置了shell参数的 child_process.spawn()child_process.exec() 都更高效。

child_process.exec() 的第一个参数是需要执行命令,而 child_process.execFile() 的第一个参数是需要运行的文件的路径。第二个和第三个参数则是一样的,分别是命令的参数和回调函数。回调函数接收3个参数: errorstdoutstderr 。如果没有出现错误,数据会被缓存到 stdout 中。

如果可执行文件的内容如下:

#!/usr/bin/node
console.log(global);

那么下面的程序会打印出缓存的结果:

var execfile = require('child_process').execFile,
    child;
child = execfile('./app', function(error, stdout, stderr) {
  if (error == null) {
    console.log('stdout: ' + stdout);
  }
});

使用 child_process.exec() 也可以完成一样的任务:

var exec = require('child_process').exec, 
    child; 
child = exec('./app', function(error, stdout, stderr) {
   if (error) return console.error(error);
   console.log('stdout: ' + stdout);
});

区别在于 child_process.exec() 会产生一个shell,而 child_process.execFile() 不会。

child_process.exec() 函数接收3个参数:要执行的命令、一个 options 对象和一个回调函数。 options 对象中包含好几个参数,如 encoding 、进程的 uid (用户 id )和 gid (组 id )。在第6章中,我创建了一个用来复制PNG文件并添加华丽特效的程序。程序使用(创建)了一个子进程来访问ImageMagick——一个强大的命令行图形工具。如果使用 child_process.exec() 来运行这个程序,可以使用下面的代码(其中已经集成了一个命令行参数):

var exec = require('child_process').exec,
    child;
child = exec('./polaroid -s phoenix5a.png -f phoenixpolaroid.png',
         {cwd: 'snaps'}, function(error, stdout, stderr) {
               if (error) return console.error(error);
               console.log('stdout: ' + stdout);
});

运行 child_process.execFile() 需要一个额外的参数:一个传入应用程序的命令行参数的数组。同样的程序如果使用这个函数,就要这样写:

var execfile = require('child_process').execFile,
    child;
child = execfile('./snapshot',
                 ['-s', 'phoenix5a.png', '-f', 'phoenixpolaroid.png'],
                  {cwd: 'snaps'}, function(error, stdout, stderr) {
   if (error) return console.error(error);
   console.log('stdout: ' + stdout);
});

请注意,命令行参数被分离为数组中的不同元素,按照一个参数、一个值的顺序排列。

由于 child_process.execFile() 并没有创建新的shell,所以在某些情况下就无法使用。Node文档提醒我们,不能在I/O重定向和通过使用路径扩展进行文件通配(通过正则表达式或通配符)时使用这个函数。但是,如果你在尝试交互地运行一个子进程(或者程序),那么你应该使用 child_process.execFile() 而不是 child_process.exec() 。下面的代码(由来自Node基金会的Colin Ihrig编写)很好地展示了这一点:

'use strict';
const cp = require('child_process');
const child = cp.execFile('node', ['-i'], (err, stdout, stderr) => {
  console.log(stdout);
});
child.stdin.write('process.versions;\n');
child.stdin.end();

这段程序会启动一个交互式的Node会话,然后请求进程版本,最后结束输入。

这两个函数都有各自的同步版本—— child_process.execSync()child_ process. execFileSync()