无法从特定应用程序的spawnpipe道输出stdout

我有两个脚本A.js和B.js,以及第三方应用程序(这是开源的)。 脚本A.js使用execSync启动第三方应用程序。 脚本B.js使用spawn启动脚本A.js。

如果我自己运行脚本A.js,我可以看到第三方应用程序的整个输出。 当我通过运行脚本B.js间接运行它时,我只能看到一些输出。

A.js

 const { execSync } = require('child_process'); console.log("Hello"); execSync('mybinary.exe -arg1 -arg2', { stdio: 'inherit' }); 

B.js

 const { spawn } = require('child_process'); const app = spawn(process.execPath, ['A.js'], { stdio: ['inherit', null, 'inherit'] }); app.stdout.on('data', (chunk) => { process.stdout.write(chunk); }); 

当我启动B,我只看到“你好”,但二进制正在运行(这是一个服务器,我可以打开一个TCP连接到它)。 我只是没有看到输出。 当我自己启动A时,我看到“Hello”和普通的二进制输出。

如果我将B的stdout改为“inherit”,它就可以工作。

为什么会发生这种情况,我该如何解决这个问题?

更新:似乎没有任何关系使用两个脚本。 直接生成二进制文件而不使用stdioinheritance会出现同样的问题。 似乎依赖于第三方应用程序。 如果程序只是打印到标准输出,程序如何影响节点?

背景:我想启动一个服务器,然后在服务器准备就绪时运行一个命令。 准备就绪后,服务器将打印出一条特定的消息。 这个想法是等待这个消息被打印。 打印出这个信息之后,它不会打印出任何东西,但它仍然在运行。

我试图pipe道的特定的可执行文件是一个ChatScript服务器 。

更新 :在这一点上,我认为这是具体的二进制我试图pipe道。 我想了解二进制文件如何影响这种行为,也就是使用inheritance而不是pipe道。 如果有人可以通过节点脚本(或者c程序)重新创build这个行为,那将会回答这个问题。


环境

  • 操作系统:Windows 10
  • 控制台:Cygwin(也尝试了常规的命令提示符)。
  • 节点v7.10.0

请注意,这是同样的问题在这里: node.js child_process.spawn没有标准输出,除非“inheritance”

chatscript正在执行的写操作是'fprintf(stdout,…)'这是一个缓冲输出,并被保存,直到像(4k?)被缓冲,然后刷新。 例如在ChatScript / src / os.cpp第1849行的fprintf(stdout)之后加上'fflush(stdout)',然后输出就可以了(有些时候,需要做进一步的修改,但是我在cs_init中至less得到了。 TXT错误logging现在。

另一个testing只是将chatscript.exeredirect到一个文件,看看文件得到什么。 'chatscript> zz',然后用ctrl-c结束chatscript,你会看到zz也是空白的…这表示IO已经被缓冲了,而且没有被刷新到适当的输出。

 M:\javascript\test_exec>node b.js Hello in cs_init.txt at 0: A subdirectory or file USERS already exists. Error opening utf8writeappend file LOGS/startlog.txt: No such file or directory ChatScript Release Version 7.5 pid: 0 32 bit Windows compiled Jun 24 2017 09:42:13 host=local Params: dict:2097151 fact:800000 text:100000kb hash:215127 buffer:80x80kb cache:1x5000kb userfacts:100 outputlimit:80000 loglimit:80000 Unable to read dictionarySystem.h Missing 37 word files read 0 raw words in facts.txt at 0: A subdirectory or file USERS already exists. 

有一个简单和安全的解决方法,这是将输出从应用程序pipe道传输到一个文件,然后从同一个文件中读取,所以你不必担心事件发生之前或之后尝试听它。

pipe道到文件:

 var fs = require('fs'); var spawn = require('child_process').spawn; var out = fs.openSync('./out.log', 'a'); var err = fs.openSync('./err.log', 'a'); var child = spawn('applicaiton', [], { detached: true, stdio: [ 'ignore', out, err ] }); 

希望它有帮助,更新我如何去;

祝你好运,