Node child_process.spawn多个命令

32

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

//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'));
      })

我的回答有帮到你吗? - Chev
我也遇到了同样的问题!你找到解决方法了吗?提供的方法对我没有帮助。 - basilisk
2个回答

65

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

例如:

<code><code>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);
});
</code></code>

在 Node.js 版本低于 6 的情况下,将触发错误:

<code><code>Error: spawn ls && ls && ls ENOENT
</code></code>

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

node app.js
STDOUT: app.js

STDOUT: app.js
app.js

Child exited with code: 0

20
在命令行中,| 符号被称为“管道”,因为它类似于将数据流一起传送。你需要做的是获取正在执行的命令的 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"进程的任何输出流导入到"grep"进程的stdin流中。最后,我们将"grep"进程的stdout流导入到父进程(您的node进程)的stdin流中,以便您可以在终端中看到输出结果。

由于我在中间放置了一个换行符,且grep只匹配包含"brown"的第一行,因此输出结果为"The quick brown fox"。

您也可以使用"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'),因为它们现在已经被包含在随后的生成中。 - Revent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接