J'essaie de lancer une commande Shell à partir de Node.js, sans redirigeant l'entrée et la sortie de cette commande - tout comme la décortiquer vers une commande en utilisant un script Shell ou en utilisant Ruby's system
commande. Si le processus enfant veut écrire dans STDOUT, je veux que cela aille directement à la console (ou soit redirigé, si ma Node a été redirigée).
Node ne semble pas avoir de moyen simple de le faire. Il semble que la seule façon d'exécuter un autre processus soit avec child_process
, Qui toujours redirige l'entrée et la sortie du processus enfant vers des canaux. Je peux écrire du code pour accepter les données de ces canaux et les écrire dans les STDOUT et STDERR de mon processus, mais si je le fais, les API me forcent à sacrifier une certaine flexibilité.
Je veux deux fonctionnalités:
Il ressemble à Node veut me forcer à choisir entre ces deux fonctionnalités.
child_process.spawn
puis faire child.stdout.on('data', function(data) { process.stdout.write(data); });
et la même chose pour stderr
, et c'est ' Je transmettrai avec plaisir les données jusqu'à ce que les vaches rentrent à la maison. Malheureusement, spawn
ne prend pas en charge la syntaxe Shell.child_process.exec
. Mais exec
insiste pour mettre en mémoire tampon les STDOUT et STDERR du processus enfant pour moi et me les donner à la fin, et cela limite la taille de ces tampons (configurable, 200 Ko 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
ajoutera toujours les données à ses tampons aussi. Lorsque la quantité de données dépasse la taille de tampon prédéfinie, exec
mettra fin au processus enfant.(Il y a aussi child_process.execFile
, qui est le pire des deux mondes du point de vue de la flexibilité: pas de syntaxe Shell, mais vous devez encore plafonner le montant de sortie que vous attendez.)
Suis-je en train de manquer quelque chose? Existe-t-il un moyen de simplement Shell vers un processus enfant dans Node, et pas rediriger ses entrées et sorties? Quelque chose qui prend en charge la syntaxe Shell et qui ne s'emballe pas après une quantité prédéfinie de sortie, tout comme est disponible dans les scripts Shell, Ruby, etc.?
Vous pouvez hériter des flux stdin/out/error via l'argument spawn
, vous n'avez donc pas besoin de les diriger manuellement:
var spawn = require('child_process').spawn;
spawn('ls', [], { stdio: 'inherit' });
Utiliser Shell pour la syntaxe Shell - pour bash c'est -c
paramètre pour lire le script à partir 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');
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.toString ());
});
La magie est juste {Shell: true}
.
Je ne l'ai pas utilisé, mais j'ai vu cette bibliothèque: https://github.com/polotek/procstreams
Si tu fais ça. La .out()
redirige automatiquement vers la sortie/stdin du processus.
var $p = require('procstreams');
$p('cat lines.txt').pipe('wc -l').out();
Si ne supporte pas la syntaxe Shell, mais c'est assez trivial 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
});
Il y a un exemple dans le node 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();