Essayer d'exécuter le script batch Windows à partir de node.js v12.6.0 et de capturer sa sortie en temps réel et dans le bon ordre.
Mais l'ordre de stdout et stderr est autre (pas toujours, mais dans 80% des cas) mélangé pendant les tests.
Comment garder stdout et stderr dans l'ordre d'origine?
Voici l'extrait de code JavaScript que j'utilise pour les tests:
child.stdout.pipe(process.stdout); child.stderr.pipe(process.stderr);
3 Réponses :
Malheureusement, vous ne pouvez pas garantir la commande.
Ce sont des canaux différents avec une mise en mémoire tampon et un comportement indépendants. Le shell lui-même obtiendra parfois des messages STDERR / STDOUT dans l'ordre prévu. Ceci est également typique d'autres applications, même en dehors de Node.js.
Oui, j'ai également rencontré ce problème dans diverses autres applications. Néanmoins, cela fonctionne de manière fiable dans certains cas (voir EDIT 1), mais la capture de la sortie devient alors un problème.
Si vous n'avez pas besoin de faire la distinction entre STDOUT et STDERR, vous pouvez les joindre à la source (dans le fichier batch). Le fichier de commandes renvoie alors tous les STDERR et STDOUT uniquement en tant que STDOUT
@Echo Off ChCp 65001 >Nul ( Echo 1 [stdout] ... Echo 2 [stderr] ... 1>&2 Echo 3 [stderr] ... 1>&2 Echo 4 [stdout] ... Echo 5 [stdout] ... Echo 6 [stderr] ... 1>&2 ) 2>&1
Merci, cela fonctionne, et je n'ai pas vraiment besoin de distinguer les messages, mais dans ce script de test par lots, ce n'est qu'un exemple. Mon objectif final est d'essayer d'utiliser node.js pour l'automatisation de Windows (y compris le démarrage de différents processus et le traitement de la sortie). Malheureusement, pour l'instant, cela semble être une mauvaise idée.
Sans modifier le fichier exécutable, une approche acceptable peut être (notez les options de spawn et les arguments de commande):
const readline = require('readline'); // ... const lineReader = readline.createInterface({ input: child.stdout }); lineReader.on('line', (line) => { if (line.includes('[ERROR]:')) { console.error(line); // StdErr. } else { console.log(line); // StdOut. } });
Cependant, elle présente quelques inconvénients:
const { spawn } = require('child_process'); const options = { shell: true, stdio: [ 'inherit', // StdIn. 'pipe', // StdOut. 'pipe', // StdErr. ], }; const child = spawn('exectest.cmd', ['2>&1'], options); let mergedOut = ''; child.stdout.setEncoding('utf8'); child.stdout.on('data', (chunk) => { process.stdout.write(chunk, (_err) => { }); mergedOut += chunk; }); child.on('close', (_code, _signal) => { console.log('-'.repeat(30)); console.log(mergedOut); });