javascript - Exec : visa stdout "live"
Jag har detta enkla skript:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});
där jag helt enkelt kör ett kommando för att kompilera en CoffeeScript-fil. Men stdout visas aldrig i konsolen, eftersom kommandot aldrig slutar (på grund av -w-alternativet i coffee). Om jag kör kommandot direkt från konsolen får jag ett meddelande som detta:
18:05:59 - compiled my_file.coffee
Min fråga är: är det möjligt att visa dessa meddelanden med node.js exec? Om ja, hur?
Svar #1
Använd inte exec. Använd spawn som är ett EventEmitter-objekt. Då kan du lyssna på stdout/stderr-händelser (spawn.stdout.on('data',callback..)) i takt med att de händer.
Från NodeJS-dokumentationen:
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});
exec buffrar utdata och returnerar vanligtvis den när kommandot har slutfört körningen.
Svar #2
exec kommer också att returnera ett ChildProcess-objekt som är en EventEmitter.
var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');
coffeeProcess.stdout.on('data', function(data) {
console.log(data);
});
ELLER pipe barnprocessens stdout till huvudstdout.
coffeeProcess.stdout.pipe(process.stdout);
ELLER ärva stdio med spawn
spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
Svar #3
Det finns redan flera svar, men ingen av dem nämner det bästa (och enklaste) sättet att göra detta, vilket är att använda spawn och alternativet { stdio: 'inherit' }. Det verkar ge det mest exakta resultatet, till exempel när man visar informations om framsteg från ett git clone.
Gör helt enkelt så här:
var spawn = require('child_process').spawn;
spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });
Kredit till @MorganTouvereyQuilling för att ha påpekat detta i den här kommentaren.
Svar #4
Inspirerad av Nathanael Smiths svar och Eric Freeses kommentar, kan det vara så enkelt som:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
Svar #5
Jag vill bara tillägga att ett litet problem med att skriva ut buffertsträngar från en spawnad process med console.log() är att det lägger till radbrytningar, vilket kan sprida ut din spawnade processutgång över fler rader. Om du istället skriver ut stdout eller stderr med process.stdout.write() istället för console.log(), får du konsolutgången från den spawnade processen 'som den är'.
Jag såg den lösningen här: Node.js: skriva ut till konsolen utan en avslutande ny rad?
Hoppas det hjälper någon som använder lösningen ovan (vilket är en utmärkt lösning för liveutdata, även om den är från dokumentationen).
Svar #6
Jag har funnit det hjälpsamt att lägga till ett eget exekveringsskript till mina verktyg som gör detta.
utilities.js
const { exec } = require('child_process')
module.exports.exec = (command) => {
const process = exec(command)
process.stdout.on('data', (data) => {
console.log('stdout: ' + data.toString())
})
process.stderr.on('data', (data) => {
console.log('stderr: ' + data.toString())
})
process.on('exit', (code) => {
console.log('child process exited with code ' + code.toString())
})
}
app.js
const { exec } = require('./utilities.js')
exec('coffee -cw my_file.coffee')
