nodejs child_process.spawnSync 或 child_process.spawn 包装在可生成的生成器中,返回输出

问题描述 投票:0回答:2

有一段时间我一直在尝试实现一些目前为止对我来说不起作用的东西。

使用nodejs,我喜欢运行交互式sh命令并在命令退出后使用sh命令输出。我喜欢编写一个可生成的生成器函数,它包装交互式 shell 命令的运行并返回 shell 命令的输出。

方法一:shelljs

  • shelljs
  • 我使用 shelljs 取得了一些成功,但在某些时候它无法进一步运行。
  • 问题1:是否有可能让shelljs能够继承stdio并使shelljs函数yieldable?

方法2:child_process.spawnSync

  • child_process.spawnSync
  • 最后我发现了 child_process.spawnSync 并很高兴,至少我可以毫无问题地运行交互式 sh 命令
    options: { stdio: 'inherit' }
  • 但我还没有找到如何取回 child_process.spawnSync 的输出。
  • 问题2:如何将spawnSync包装到返回child_process输出的生成器函数中?

方法 3:共同子进程

  • 我还尝试了co-child-process
  • 它似乎可以运行,但不能与 stdio 交互。关于此有一个问题,我不太明白。
  • 问题 3:有人可以向我解释/发布一个示例,共同子进程如何与 stdio 继承一起使用。

方法 4:使用 bluebird 来 promisify child_process.spawn()

  • 如果 child_process.spawn() 是可承诺的,我在 bluebird 上打开了一个 issue

这就是我的问题。有人可以给我发一个示例,说明如何运行交互式 shell 命令,该命令可以包装在可生成的生成器函数中,该函数返回 shell 命令的输出吗?我对新方法持开放态度。

我创建了一个 npm 模块,可以在 github 上使用,您可以在其中分叉它并做出贡献。

提前谢谢。

node.js bluebird child-process spawn co
2个回答
32
投票

我发现以下内容适用于 v5.4.1 。在文档 NodeJS Child Process 中,它提到了选项 encoding ,其默认值为 'buffer'。如果您将此选项设置为 'utf8',那么您将得到一个带有结果的字符串,而不是缓冲区。您可以从spawnSync 获取一个字符串,因为它是同步的并且会阻止执行,直到命令完成。下面是一个脚本的工作示例,该脚本执行“ls -l /usr”命令并获取字符串对象形式的输出:

#!/usr/bin/env node

var cp = require('child_process');

var ls = cp.spawnSync('ls', ['-l', '/usr'], { encoding : 'utf8' });
// uncomment the following if you want to see everything returned by the spawnSync command
// console.log('ls: ' , ls);
console.log('stdout here: \n' + ls.stdout);

当您运行它时,您会得到以下信息:

stdout here:
total 68
drwxr-xr-x   2 root root 36864 Jan 20 11:47 bin
drwxr-xr-x   2 root root  4096 Apr 10  2014 games
drwxr-xr-x  34 root root  4096 Jan 20 11:47 include
drwxr-xr-x  60 root root  4096 Jan 20 11:47 lib
drwxr-xr-x  10 root root  4096 Jan  4 20:54 local
drwxr-xr-x   2 root root  4096 Jan  6 01:30 sbin
drwxr-xr-x 110 root root  4096 Jan 20 11:47 share
drwxr-xr-x   6 root root  4096 Jan  6 00:34 src

文档告诉您除了 stdout 之外,还可以从对象上获得什么。如果您想查看返回对象上的所有属性,请取消注释 console.log(警告:有很多东西:))。


0
投票

要在行可用后立即逐行迭代,您可以:

#!/usr/bin/env node

const childProcess = require('child_process')
const readline = require('readline')

const p = childProcess.spawn('ls', ['somedir'])
;(async function() {
const rl = readline.createInterface({ input: p.stdout })
for await (const line of rl) {
  console.log('read: ' + line)
}
})()

当您的输出是面向行的时,这是一个好主意,因为它允许您处理大于内存的数据,并且它允许您立即开始处理早期的标准输出行,而无需等待最后的行。它还克服了默认的

spawnSync
1MB 缓冲区限制。

我在以下位置提供了更详细的示例:spawnSync /bin/sh ENOBUFS

© www.soinside.com 2019 - 2024. All rights reserved.