58

I see how to pipe stuff together using Node.js streams, but how do you pipe multiple scripts together using the Unix |, given that some of these scripts can be async?

$ ./a.js | ./b.js

Example:

a.js (chmod 0755)

#!/usr/bin/env node

setTimeout(function(){
  console.log(JSON.stringify({ foo: 'bar' }));
}, 10);

b.js (chmod 0755)

#!/usr/bin/env node

console.log(process.argv);

This is the output:

$ ./a.js | ./b.js
[ 'node', '/Users/viatropos/tests/b.js' ]

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: write EPIPE
    at errnoException (net.js:883:11)
    at Object.afterWrite (net.js:700:19)

At first glance it seems like there's a lot going wrong, so not really sure where to start. Is there a way to get this to work? The end goal is to be able to take the console.log output from ./a.js and use it in ./b.js. The reason is, most of the time these scripts will be run one at a time, but sometimes it would be nice to be able to pipe them together, so ideally the system should be able to handle both cases.

4

1 回答 1

75

问题是您b.js立即结束并关闭其标准输入,这会导致错误输入a.js,因为它的标准输出已关闭,而您没有处理这种可能性。您有两个选择:处理标准输出关闭a.js或接受输入b.js

固定a.js

process.on("SIGPIPE", process.exit);

如果你添加那一行,当没有人再读它的输出时它就会放弃。根据您的程序在做什么,在 SIGPIPE 上可能有更好的事情要做,但关键是停止console.log

固定b.js

#!/usr/bin/env node

var stdin = process.openStdin();

var data = "";

stdin.on('data', function(chunk) {
  data += chunk;
});

stdin.on('end', function() {
  console.log("DATA:\n" + data + "\nEND DATA");
});

当然,您不必这些数据做任何事情。他们的关键是有一些东西可以保持流程运行;如果您正在使用它,这stdin.on('data', fx)似乎是一件有用的事情。

请记住,其中任何一个都可以防止该错误。如果您计划在程序之间进行管道传输,我希望第二个最有用。

于 2013-05-03T04:56:26.437 回答