节点 child_process.spawn 多个命令

Posted

技术标签:

【中文标题】节点 child_process.spawn 多个命令【英文标题】:Node child_process.spawn multiple commands 【发布时间】:2016-05-02 11:08:37 【问题描述】:

我想自动创建和提取密钥库。 我面临的问题是如何使用“ | ”符号或类似解决方案加入命令。

//Original Command    
var command='keytool -exportcert -storepass mypass -keypass mypass  
-alias myalias -keystore mykey.keystore | openssl sha1 -binary | openssl base64';

//Arguments for the spawn    
var keyArgs = [
      '-exportcert',
      '-storepass','mypass',
      '-keypass','mypass',
      '-alias','myalias',
      '-keystore',"myjey.keystore",


      'openssl','sha1',
      '-binary',
      'openssl','base64',


  ];
exec('keytool',keyArgs,cwd:appCreateFolder+"/"+opt.id+"/Certificates",function(e)
    console.log(chalk.cyan('Key created'));
      )

【问题讨论】:

我的回答对你有帮助吗? 我也遇到了同样的问题!你找到解决方案了吗?提供的没有帮助我 【参考方案1】:

命令行上的| 符号称为“管道”,因为它就像将数据流管道连接在一起。您想要的是获取您正在执行的命令的stdin(标准输入)和stdout(标准输出)流。

例如,这是生成 echo 命令并将其输出通过管道传输到 grep 的方式:

var spawn = require('child_process').spawn;
var echo = spawn('echo', ['The quick brown fox\njumped over the lazy dog.']);
var grep = spawn('grep', ['brown']);

echo.stdout.pipe(grep.stdin);
grep.stdout.pipe(process.stdin);

上面的例子产生了“echo”和“grep”命令。它将来自echo 进程的stdout 流的任何输出通过管道传输到grep 进程的stdin 流。最后,我们将grep 进程的stdout 流通过管道传输到父进程(您的节点进程)的stdin 流,以便您可以在终端中看到输出。

输出将是“The quick brown fox”,因为我在中间放了一个换行符,而 grep 只匹配包含“brown”的第一行。

您可以使用exec 函数来获得相同的结果。只是将来可能更难维护,但如果您只需要快速运行一组管道命令,您可以输入完整的命令行字符串(包括管道符号)并将其传递给 exec

var exec = require('child_process').exec;
var cmdString = 'grep "The quick brown fox\njumped over the lazy dog." | grep "brown"';
exec(cmdString, (err, stdout, stderr) => 
  console.log(stdout);
);

或者,如果您只关心查看命令输出,您可以将输出通过管道传输到process.stdin,而不是传递回调函数。

exec(cmdString).stdout.pipe(process.stdin);

下面是我认为您的代码使用spawn 应该是什么样子的一个简单示例。可能需要调整,因为它似乎特定于您正在做的事情。

var keyArgs = [
  '-exportcert',
  '-storepass','mypass',
  '-keypass','mypass',
  '-alias','myalias',
  '-keystore',"myjey.keystore",
  'openssl','sha1',
  '-binary',
  'openssl','base64',
];
var keyOpts = 
  cwd: `$appCreateFolder/$opt.id/Certificates`
;

var spawn = require('child_process').spawn;
var keytool = spawn('keytool', keyArgs, keyOpts);
var opensslBinary = spawn('openssl', ['sha1', '-binary']);
var opensslBase64 = spawn('openssl', ['base64']);

keytool.stdout.pipe(opensslBinary.stdin);
opensslBinary.stdout.pipe(opensslBase64.stdin);
opensslBase64.stdout.pipe(process.stdin);

opensslBase64.on('close', () => 
  console.log(chalk.cyan('Key created.'));
);

或者使用exec:

var exec = require('child_process').exec;
var cmdString = 'keytool -exportcert -storepass mypass -keypass mypass -alias myalias -keystore mykey.keystore | openssl sha1 -binary | openssl base64';
var cmdOpts = 
  cwd: `$appCreateFolder/$opt.id/Certificates`
;
exec(cmdString, cmdOpts, () => 
  console.log(chalk.cyan('Key created.'));
);

【讨论】:

我相信在最后一个生成示例中,keyArgs 数组的最后 5 个元素(来自“openssl”)应该被删除,因为它们现在在后续生成中被捕获。【参考方案2】:

从 Node.js v6 开始,您可以在 spawn 方法中指定 shell 选项,该选项将使用 shell 运行命令,因此可以使用 spawn 方法链接命令

例如:

var spawn = require('child_process').spawn;
var child = spawn('ls && ls && ls', 
  shell: true
);
child.stderr.on('data', function (data) 
  console.error("STDERR:", data.toString());
);
child.stdout.on('data', function (data) 
  console.log("STDOUT:", data.toString());
);
child.on('exit', function (exitCode) 
  console.log("Child exited with code: " + exitCode);
);

node.js版本低于6会触发错误:

Error: spawn ls && ls && ls ENOENT

但在版本 6 及更高版本上,它将返回预期结果:

node app.js
STDOUT: app.js

STDOUT: app.js
app.js

Child exited with code: 0

【讨论】:

以上是关于节点 child_process.spawn 多个命令的主要内容,如果未能解决你的问题,请参考以下文章

child_process spawn() 中的通配符?

如何让 child_process.spawn 在我的 TypeScript 模块中返回一个 Promise?

如何将字符串解析为 child_process.spawn 的适当参数?

如何模拟 Node.js child_process spawn 函数?

nodejs child_process.spawnSync 或 child_process.spawn 包裹在 yieldable 生成器中,它返回输出

如何使用 nodejs child_process.spawn 捕获 ENOENT?