Node.js - 监视特定文本生成的子项输出



因此,我使用Node的child_process模块来生成弹性搜索的实例。我需要检查服务何时启动,resolve()何时承诺。我现在就是这样做的:

const { join } = require('path');
const { spawn } = require('child_process');
const { createWriteStream } = require('fs');
const { Transform } = require('stream');
function start() {
return new Promise(resolve => {
const outStream = new Transform({
transform(chunk, encoding, callback) {
if (chunk.toString().includes('started')) resolve();
this.push(chunk);
callback();
}
});
const logFile = createWriteStream(join(LOG_DIR, 'es.log'), 'w');
const errorFile = createWriteStream(join(LOG_DIR, 'es.error.log'), 'w');
outStream.pipe(logFile);
child = spawn(
ES_BAT_PATH,
[],
{ cwd: process.cwd(), stdio: ['ignore', outStream, errorFile] }
);
});
}

这是最好的方法吗?(可能不会(如果没有,我该怎么办?

一般来说,我认为这是一种合理的方法,但我在这里看到了一些问题:

  • 这些块可能不包含您要查找的整个单词,但它可能介于两者之间(一个块以'sta'结尾,下一个以'rted'开头(
  • 在最初的发现之后,您仍然有一个实际上不再需要的转换流
  • 还有unicode字符的问题,但由于您正在寻找' started ',因此可以省略它

通过将最后一部分保留在空格后,可以很容易地缓解第一个问题。第二,你需要解开转换——所以你最终会得到这样的东西:

const { join } = require('path');
const { spawn } = require('child_process');
const { createWriteStream } = require('fs');
const { Readable, PassThrough } = require('stream');
function start() {
return new Promise(resolve => {
const outStream = new PassThrough();
let last;
const lookupStream = new Readable({
read(chunk, encoding, callback) {
const ref = chunk.toString();
if ((last + ref).includes('started')) {
outStream.unpipe(lookupStream);
resolve();
}
last = ref.replace(/^.* /, '');
callback();
}
});
const logFile = createWriteStream(join(LOG_DIR, 'es.log'), 'w');
const errorFile = createWriteStream(join(LOG_DIR, 'es.error.log'), 'w');
outStream.pipe(logFile);
outStream.pipe(lookupStream);
child = spawn(
ES_BAT_PATH,
[],
{ cwd: process.cwd(), stdio: ['ignore', outStream, errorFile] }
);
});
}

另一种选择是使用on('data'侦听器,并在找到正确的块后将其删除。

最后,我的框架scramjet会让更容易一些

const { join } = require('path');
const { spawn } = require('child_process');
const { createWriteStream } = require('fs');
const { StringStream } = require('scramjet');
function start() {
const outStream = new PassThrough();
const lookupStream = new StringStream();
const logFile = createWriteStream(join(LOG_DIR, 'es.log'), 'w');
const errorFile = createWriteStream(join(LOG_DIR, 'es.error.log'), 'w');
outStream.pipe(logFile);
outStream.pipe(lookupStream);
child = spawn(
ES_BAT_PATH,
[],
{ cwd: process.cwd(), stdio: ['ignore', outStream, errorFile] }
);
return lookupStream
.split('n')                                    // split line by line
.filter(x => x.includes('started'))             // check if line contains "started"
.until(x => outStream.unpipe(lookupStream))     // end stream on first occurence
.run();                                         // run and resolve on stream end
}

最新更新