Node.js:使用EPIPE写入bash进程的stdin崩溃

时间:2018-10-26 10:45:58

标签: node.js linux bash stdin

我的节点进程通过HTTP请求获取了一些PDF文件,然后使用请求的onData事件将传入数据传递到经过lpr生成的正确配置的child_process.exec上。我用process.stdin.write(...)写给stdin,写完后跟process.stdin.end()写。这使我可以立即打印这些文件。

现在,我不希望将数据通过管道传输到lpr,而是通过某种bash脚本。该脚本使用cat处理其stdin

myscript.sh < somefile.pdfcat somefile.pdf | myscript.sh一样工作。

但是,当我从节点生成/path/to/script.sh时(只需将lpr替换为源代码中的脚本路径),该过程就会以

退出

events.js:183 throw er; // Unhandled 'error' event ^ Error: write EPIPE at WriteWrap.afterWrite [as oncomplete] (net.js:868:14)

随后,整个节点进程崩溃,该错误在所有try...catch块中潜行。在bash脚本开始处显示的日志记录,甚至没有开始。

当我针对的不是shell脚本而是经过编译的可执行文件时,例如catecho,...一切正常。 添加epipebomb module不会有任何改变。

我还尝试了通过管道传递到process.exec("bash", ["-c cat | myscript.sh"])的错误,

bash脚本示例,仅用于测试执行情况:

#!/usr/bin/env bash
date > logfile.txt
cat > /dev/null

编辑: 我想我可能需要发信号以某种方式保持stdin流打开。 脚本的生成过程部分,省去了promisification和输出处理:

const process = require("child_process")    

// inputObservable being an rxjs Observable
execstuff(inputObervable) {
  const task = process.spawn("/path/to/script.sh");
  inputObservable.subscribe(
    chunk => task.stdin.write(chunk),
    error => console.error(error),
    finished => task.stdin.end()
  );
}

1 个答案:

答案 0 :(得分:1)

child_process.spawn上有一个示例,您可以如何将以下几行ps ax | grep ssh编写为node.js脚本,也许会对您有所帮助:

const { spawn } = require('child_process');
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

ps.stderr.on('data', (data) => {
  console.log(`ps stderr: ${data}`);
});
  

第一印象是您在做同样的事情,问题可能出在数据块数据中,也许其中一个数据块为空,并且它正在关闭流,并且您想通过运行task.stdin关闭它.end()。

您可以尝试的另一件事是使用NODE_DEBUG=stream node script.js运行node.js脚本 将记录node.js内部信息流的行为方式,也可能对您有所帮助。