web-dev-qa-db-ja.com

Unixを使用してNode.jsスクリプトをパイプする方法|パイプ(コマンドライン)?

Node.jsストリームを使用してデータをパイプする方法はわかりますが、Unix |を使用して複数のスクリプトをパイプする方法はいくつかあります。

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

例:

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

これは出力です:

$ ./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)

一見すると、多くの問題が発生しているように見えるので、どこから始めればよいかわからない。これを機能させる方法はありますか?最終的な目標は、console.logから./a.js出力を取得し、./b.jsで使用できるようにすることです。その理由は、ほとんどの場合、これらのスクリプトは一度に1つずつ実行されますが、それらを一緒にパイプ処理できると便利な場合があるため、理想的にはシステムが両方のケースを処理できる必要があります。

41
Lance Pollard

問題は、_b.js_がすぐに終了し、その標準入力を閉じることです。これにより、_a.js_でエラーが発生します。これは、標準出力が遮断され、その可能性を処理しなかったためです。 2つのオプションがあります。_a.js_でstdoutのクローズを処理するか、_b.js_で入力を受け入れます。

_a.js_の修正:

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

その行を追加すると、その出力を読み取る人がもういないときに、あきらめるだけです。あなたのプログラムが何をしているのかに応じて、おそらくSIGPIPEで行うべきより良いことはありますが、重要なのは_console.log_ ingを停止することです。

_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");
});
_

もちろん、あなたはhaveでそのデータを操作することはありません。彼らの鍵は、プロセスを実行し続けるものを持つことです。あなたがそれにパイプしているなら、stdin.on('data', fx)は便利なことのように思えます。

これらのいずれかがそのエラーを防ぐことを覚えておいてください。プログラム間のパイプを計画している場合は、2番目が最も役立つと思います。

59
Aaron Dufour