web-dev-qa-db-fra.com

Comment diriger des scripts Node.js ensemble à l'aide de Unix | pipe (sur la ligne de commande)?

Je vois comment diriger des trucs ensemble en utilisant des flux Node.js, mais comment canaliser plusieurs scripts ensemble en utilisant le Unix |, étant donné que certains de ces scripts peuvent être asynchrones?

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

Exemple:

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

Voici la sortie:

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

À première vue, il semble qu'il y ait beaucoup de problèmes, donc vous ne savez pas trop par où commencer. Existe-t-il un moyen de faire fonctionner cela? L'objectif final est de pouvoir prendre le console.log sortie de ./a.js et l'utiliser dans ./b.js. La raison en est que la plupart du temps, ces scripts seront exécutés un par un, mais il serait parfois agréable de pouvoir les assembler, donc idéalement le système devrait être capable de gérer les deux cas.

41
Lance Pollard

Le problème est que votre b.js Se termine immédiatement et ferme son standard dans, ce qui provoque une erreur dans a.js, Car son standard a été désactivé et vous n'avez pas géré cette possibilité. Vous avez deux options: gérer la fermeture stdout dans a.js Ou accepter l'entrée dans b.js.

Correction de a.js:

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

Si vous ajoutez cette ligne, elle abandonnera quand personne ne lira plus sa sortie. Il y a probablement de meilleures choses à faire sur SIGPIPE selon ce que fait votre programme, mais la clé est d'arrêter console.log.

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

Bien sûr, vous n'avez avez pour rien faire avec ces données. Leur clé est d'avoir quelque chose qui maintient le processus en cours; si vous y accédez, stdin.on('data', fx) semble être une chose utile à faire.

N'oubliez pas que l'un ou l'autre de ces éléments empêchera cette erreur. Je m'attends à ce que le second soit le plus utile si vous prévoyez de canaliser entre les programmes.

59
Aaron Dufour