【问题标题】:Nodejs child_process spawn get command ranNodejs child_process spawn get 命令运行
【发布时间】:2016-06-07 04:42:00
【问题描述】:

为了清楚起见,我想查看 Node.js 与 shell/cli 运行的确切命令。不幸的是,我似乎无法找出如何...

https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

this 返回的对象是一个事件发射器,但目前在 Nodejs 中无法从事件发射器中嗅探事件。我试过data &, pipe 事件没有成功。

child_process.spawn 返回的对象有子对象:stdoutstdinstderr。有 stderrstdout 被用作事件发射器的例子,这些工作正常,但我找不到 stdin 发射的事件...

我知道我可以只接受我的输入并对其进行格式化,但这感觉很容易失败/不一致,所以我宁愿找到一种方法来嗅探它实际使用的内容。

【问题讨论】:

    标签: node.js command-line event-handling child-process


    【解决方案1】:

    stdin 上有一个传入数据的事件,称为 "data"

    process.stdin.on("data", (data) => {} );
    
    • 虽然某些应用程序会逐行处理输入,但其他应用程序的交互性更强,可以实时处理按键操作(例如,通过箭头键在列表中上/下移动)。
    • 虽然某些应用程序需要纯文本,但其他应用程序将使用二进制数据。

    有多种可能的情况,您在这里几乎可以靠自己。 我通常会创建一个InputReader,它只是缓冲所有输入并将其转换为适合我特定用例的事件。

    下面是阅读器的最基本示例之一,每次接收到一行文本时都会触发事件。

    export class DataReader {
      private buffer = "";
    
      constructor(private listener: (err, line: string)=>any ) {
      }
    
      processData(data) {
        // remove carriage returns, and add data to the buffer.
        data = data.toString().replace(/\r/g, '');
        this.buffer += data;
    
        // get only the complete data.
        const lastNewlineIndex = this.buffer.lastIndexOf('\n');
        if (lastNewlineIndex < 0) return;
        
        if (this.listener != null) {
          // split data in lines
          const completeData = this.buffer.slice(0, lastNewlineIndex);
          const lines = completeData.split('\n');
          for (const line of lines) {
            // notify listener line by line.
            this.listener(null, line);
          }
        }
        
        // remove processed data from the buffer.
        this.buffer = this.buffer.slice(lastNewlineIndex + 1);
      }
    }
    

    实际上,您可以使用EventEmitter 或一些Observable 调度输出。

    const reader = new DataReader((err, line) => subject.next(line));
    process.stdin.on("data", (data) => reader.processData(data));
    

    【讨论】:

      【解决方案2】:

      这里的问题是标准输入是一个只写的 unix 套接字。您可以写入孩子的标准输入,但如果您想检测任何类型的格式,则必须在标准输出的数据事件上发生。

      your app ----> stdin of child (can only write to it)
      
      your app <---- stdout of child (can only read from it)
      

      我希望我解释我的观点你满意吗?如果不是,请举例说明您为什么要查看哪些标准输入消息到达外部程序。 (如果有办法,那么我怀疑您将得到的只是您写入的相同数据)

      【讨论】: