无法从spawn中为特定应用程序管道stdout

时间:2017-06-03 13:26:50

标签: node.js process spawn

我有两个脚本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时,我只看到" Hello"但是二进制 正在运行(它是服务器,我可以打开它的TCP连接)。我只是没有看到输出。当我单独发布A时,我会看到" Hello"和常规二进制文件的输出。

如果我将B' sdout改为'继承',它就有效。

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

更新:似乎与使用两个脚本无关。直接生成二进制文件而不使用stdio继承会出现同样的问题。似乎依赖于第三方应用程序。 如果程序只打印到stdout,程序如何影响节点?

语境:我想启动服务器,然后在服务器准备就绪时运行命令。准备就绪后,服务器会打印出特定的消息。我的想法是等待打印这条消息。打印出此消息后,它不打印任何其他内容,但它仍然在运行。

我试图管道的特定可执行文件是ChatScript server

更新:此时,我认为它是特定二进制文件的一部分,我试图管道。我想了解二进制文件如何影响这种行为,即使用继承而不是管道。 如果有人可以使用节点脚本(或c程序)重新创建此行为,则会回答问题。

环境

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

请注意,这与此处的问题相同:node.js child_process.spawn no stdout unless 'inherit'

2 个答案:

答案 0 :(得分:1)

chatscript正在执行的写操作是'fprintf(stdout,...)'这是一个缓冲输出,并保存,直到缓冲然后刷新(4k?)然后刷新。例如,在ChatScript / src / os.cpp第1849行中的fprintf(stdout)之后添加'fflush(stdout)'然后输出有效(稍微需要进一步更改,但我确实至少在cs_init中得到了'。 txt'现在记录错误。

另一个测试只是将chatscript.exe重定向到一个文件并查看该文件的内容。 '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.

答案 1 :(得分:0)

有一个简单而安全的解决方法是将应用程序的输出传输到文件,然后从同一个文件中读取,因此您不必担心在您尝试之前或之后触发事件听听它。

管道到文件:

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 ]
});

希望它有所帮助,让我了解它的进展情况;

祝你好运,