151 votes

Node.js génère un processus enfant et obtient la sortie du terminal en direct

J'ai un script qui sort 'hi', dort pendant une seconde, sort 'hi', dort pendant 1 seconde, et ainsi de suite, et ainsi de suite. Maintenant, j'ai pensé que je serais capable d'aborder ce problème avec ce modèle.

var spawn = require('child_process').spawn,
temp    = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR');

temp.stdout.pipe(process.stdout);

Le problème est que la tâche doit être terminée pour que le résultat s'affiche. Si je comprends bien, cela est dû au fait que le processus nouvellement créé prend le contrôle de l'exécution. De toute évidence, node.js ne prend pas en charge les threads, donc une solution ? Mon idée était d'exécuter deux instances, la première dans le but spécifique de créer la tâche et d'envoyer la sortie vers le processus de la deuxième instance, en considérant que cela peut être réalisé.

114voto

RubyTuesdayDONO Points 492

Je suis encore en train de me mouiller les pieds avec Node.js, mais j'ai quelques idées. Tout d'abord, je crois que vous devez utiliser execFile au lieu de spawn ; execFile est pour quand vous avez le chemin vers un script, alors que spawn sert à exécuter une commande connue que Node.js peut résoudre par rapport au chemin d'accès de votre système.

1. Fournir un rappel pour traiter la sortie mise en mémoire tampon :

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when process terminates.
    console.log(stdout); 
});  

2. Ajouter un écouteur au stdout du processus enfant flux ( 9èmeport.net )

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

De plus, il semble qu'il existe des options permettant de détacher le processus engendré du terminal de contrôle de Node, ce qui lui permettrait de fonctionner de manière asynchrone. Je n'ai pas encore testé cela, mais il y a des exemples dans le fichier Documents de l'API qui vont à peu près comme ça :

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ]
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

45voto

Harel Ashwal Points 315

Voici l'approche la plus propre que j'ai trouvée :

require("child_process").spawn('bash', ['./script.sh'], {
  cwd: process.cwd(),
  detached: true,
  stdio: "inherit"
});

19voto

agenaille Points 211

J'ai eu un peu de mal à obtenir la sortie de la journalisation de la commande "npm install" lorsque j'ai spawné npm dans un processus enfant. La journalisation en temps réel des dépendances n'apparaissait pas dans la console parent.

La façon la plus simple de faire ce que l'affiche originale veut est la suivante (lancer npm sur Windows et tout enregistrer sur la console parent) :

var args = ['install'];

var options = {
    stdio: 'inherit' //feed all child process logging into parent process
};

var childProcess = spawn('npm.cmd', args, options);
childProcess.on('close', function(code) {
    process.stdout.write('"npm install" finished with code ' + code + '\n');
});

7voto

Guest Points 71

Passthru de type PHP

import { spawn } from 'child_process';

export default async function passthru(exe, args, options) {
    return new Promise((resolve, reject) => {
        const env = Object.create(process.env);
        const child = spawn(exe, args, {
            ...options,
            env: {
                ...env,
                ...options.env,
            },
        });
        child.stdout.setEncoding('utf8');
        child.stderr.setEncoding('utf8');
        child.stdout.on('data', data => console.log(data));
        child.stderr.on('data', data => console.log(data));
        child.on('error', error => reject(error));
        child.on('close', exitCode => {
            console.log('Exit code:', exitCode);
            resolve(exitCode);
        });
    });
}

Utilisation

const exitCode = await passthru('ls', ['-al'], { cwd: '/var/www/html' })

4voto

Sandro Pasquali Points 156

Enfant :

setInterval(function() {
    process.stdout.write("hi");
}, 1000); // or however else you want to run a timer

parent :

require('child_process').fork('./childfile.js');
// fork'd children use the parent's stdio

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X