Exécuter une commande shell à partir de Node.js sans mettre en tampon la sortie

J’essaie de lancer une commande shell à partir de Node.js, sans redirect les entrées et les sorties de cette commande – comme si vous utilisiez un script shell pour exécuter une commande ou utilisez la commande system de Ruby. Si le processus enfant veut écrire sur STDOUT, je souhaite que ce dernier accède directement à la console (ou soit redirigé si la sortie de mon application Node a été redirigée).

Node ne semble pas avoir de façon simple de le faire. Il semble que la seule façon d’exécuter un autre processus soit avec child_process , qui redirige toujours les entrées et les sorties du processus enfant vers des tuyaux. Je peux écrire du code pour accepter les données de ces canaux et les écrire dans STDOUT et STDERR de mon processus, mais si je le fais, les API me forcent à sacrifier une certaine flexibilité.

Je veux deux fonctionnalités:

  • Syntaxe Shell. Je veux pouvoir diriger la sortie entre les commandes ou exécuter des fichiers de commandes Windows.
  • Sortie illimitée. Si je cherche un compilateur et que je veux générer des mégaoctets d’avertissements du compilateur, je veux qu’ils défilent à l’écran (jusqu’à ce que l’utilisateur en ait assez et qu’il appuie sur Ctrl + C).

On dirait que Node veut me forcer à choisir entre ces deux fonctionnalités.

  • Si je veux une quantité de sortie illimitée, je peux utiliser child_process.spawn , puis faire child.stdout.on('data', function(data) { process.stdout.write(data); }); et la même chose pour stderr , et ça va pleuvoir les données jusqu’à ce que les vaches rentrent à la maison. Malheureusement, spawn ne supporte pas la syntaxe shell.
  • Si je veux une syntaxe de shell, je peux utiliser child_process.exec . Mais exec insiste pour mettre en mémoire tampon les STDOUT et STDERR du processus enfant et les atsortingbuer à la fin, et cela limite la taille de ces tampons (configurable, 200K par défaut). Je peux toujours accrocher les événements on('data') , si je veux voir la sortie telle qu’elle est générée, mais exec appenda toujours les données à ses tampons. Lorsque la quantité de données dépasse la taille de la mémoire tampon prédéfinie, exec met fin au processus fils.

(Il y a aussi child_process.execFile , qui est le pire des deux mondes du sharepoint vue de la flexibilité: pas de syntaxe shell, mais vous devez toujours limiter la quantité de sortie attendue.)

Est-ce que je manque quelque chose? Existe-t-il un moyen de passer à un processus enfant dans Node et de ne pas redirect ses entrées et sorties? Quelque chose qui supporte la syntaxe du shell et qui ne disparaît pas après une quantité de sortie prédéfinie, comme c’est le cas avec les scripts shell, Ruby, etc.?

Vous pouvez hériter des stream stdin / out / error via l’argument spawn , vous n’avez donc pas besoin de les canaliser manuellement:

 var spawn = require('child_process').spawn; spawn('ls', [], { stdio: 'inherit' }); 

Utilisez le shell pour la syntaxe du shell – pour le paramètre bash it -c pour lire le script de la chaîne:

 var spawn = require('child_process').spawn; var shellSyntaxCommand = 'ls -l | grep test | wc -c'; spawn('sh', ['-c', shellSyntaxCommand], { stdio: 'inherit' }); 

Pour résumer:

 var spawn = require('child_process').spawn; function shspawn(command) { spawn('sh', ['-c', command], { stdio: 'inherit' }); } shspawn('ls -l | grep test | wc -c'); 

Je ne l’ai pas utilisé, mais j’ai vu cette bibliothèque: https://github.com/polotek/procstreams

Vous le feriez Le .out() automatiquement vers stdin / out du processus.

 var $p = require('procstreams'); $p('cat lines.txt').pipe('wc -l').out(); 

If ne supporte pas la syntaxe shell, mais c’est assez sortingvial, je pense.

 var command_str = "cat lines.txt | wc -l"; var cmds = command_str.split(/\s?\|\s?/); var cmd = $p(cmds.shift()); while(cmds.length) cmd = cmd.pipe(cmds.shift()); cmd .out() .on('exit', function() { // Do whatever }); 

Vous pouvez remplacer exec par spawn et utiliser la syntaxe shell simplement avec:

 const {spawn} = require ('child_process'); const cmd = 'ls -l | grep test | wc -c'; const p = spawn (cmd, [], {shell: true}); p.stdout.on ('data', (data) => { console.log (data.toSsortingng ()); }); 

La magie est juste {shell: true} .

Il y a un exemple dans le nœud docs pour le module child_process:

Exemple de détachement d’un processus de longue durée et de redirection de sa sortie vers un fichier:

  var fs = require('fs'), spawn = require('child_process').spawn, out = fs.openSync('./out.log', 'a'), err = fs.openSync('./out.log', 'a'); var child = spawn('prg', [], { detached: true, stdio: [ 'ignore', out, err ] }); child.unref();