У меня есть такой простой сценарий:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});
где я просто выполняю команду для компиляции файла сценария кофе. Но stdout никогда не отображается в консоли, потому что команда никогда не заканчивается (из-за опции -w кофе). Если я выполняю команду прямо с консоли, я получаю такое сообщение:
18:05:59 - compiled my_file.coffee
Мой вопрос: можно ли отображать эти сообщения с помощью node.js exec? Если да, то как? !
Благодарность
node.js
coffeescript
Мравей
источник
источник
Ответы:
Не используйте
exec
. Использование,spawn
которое являетсяEventEmmiter
объектом. Затем вы можете слушатьstdout
/stderr
events (spawn.stdout.on('data',callback..)
) по мере их появления .Из документации NodeJS:
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
буферизует вывод и обычно возвращает его, когда команда завершила выполнение.источник
flush(stdout);
в C), чтобы запускать события в Node.js.exec
также вернет объект ChildProcess, который является EventEmitter.var exec = require('child_process').exec; var coffeeProcess = exec('coffee -cw my_file.coffee'); coffeeProcess.stdout.on('data', function(data) { console.log(data); });
ИЛИ
pipe
стандартный вывод дочернего процесса к основному.coffeeProcess.stdout.pipe(process.stdout);
ИЛИ наследовать stdio с помощью spawn
spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
источник
pipe
:coffeeProcess.stdout.pipe(process.stdout);
spawn(cmd, argv, { stdio: 'inherit' })
. См. Различные примеры на nodejs.org/api/child_process.html#child_process_options_stdio .spawn
сstdio: 'inherit'
. Он производит более точный вывод, чемexec
и pipingstdout
/stderr
, например, при отображении информации о ходе выполнения из файлаgit clone
.Уже есть несколько ответов, однако ни один из них не упоминает лучший (и самый простой) способ сделать это, а именно использование
spawn
и{ stdio: 'inherit' }
опцию . Кажется, что он дает наиболее точный результат, например, при отображении информации о ходе выполнения из файлаgit clone
.Просто сделайте это:
var spawn = require('child_process').spawn; spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });
Благодарим @MorganTouvereyQuilling за указание на это в этом комментарии .
источник
stdio: "inherit"
сохраняет это форматирование, аchild.stdout.pipe(process.stdout)
не сохраняет .Вдохновленный ответом Натанаэля Смита и комментарием Эрика Фриза, это может быть очень просто:
var exec = require('child_process').exec; exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
источник
ls
но не работает для более сложных команд, таких какnpm install
. Я даже пробовал связать как stdout, так и stderr с соответствующими объектами процесса.spawn(command, args, { stdio: 'inherit' })
это предложенный здесь stackoverflow.com/questions/10232192/…Я просто хотел бы добавить, что одна небольшая проблема с выводом строк буфера из порожденного процесса
console.log()
заключается в том, что он добавляет новые строки, которые могут распределять вывод созданного вами процесса на дополнительные строки. Если вы выведетеstdout
илиstderr
сprocess.stdout.write()
вместоconsole.log()
, то вы получите вывод консоли от порожденного процесса «как есть».Я видел это решение здесь: Node.js: печать на консоль без конечной новой строки?
Надеюсь, что это поможет кому-то, использующему указанное выше решение (которое отлично подходит для вывода в реальном времени, даже если оно взято из документации).
источник
spawn(command, args, { stdio: 'inherit' })
, как предлагает @MorganTouvereyQuilling здесь stackoverflow.com/questions/10232192/…Я счел полезным добавить в мои утилиты собственный сценарий exec.
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')
источник
Изучив все остальные ответы, я пришел к следующему:
function oldSchoolMakeBuild(cb) { var makeProcess = exec('make -C ./oldSchoolMakeBuild', function (error, stdout, stderr) { stderr && console.error(stderr); cb(error); }); makeProcess.stdout.on('data', function(data) { process.stdout.write('oldSchoolMakeBuild: '+ data); }); }
Иногда
data
будет несколько строк, поэтомуoldSchoolMakeBuild
заголовок будет отображаться один раз для нескольких строк. Но меня это не беспокоило настолько, чтобы это изменить.источник
child_process.spawn возвращает объект с потоками stdout и stderr. Вы можете нажать на поток stdout, чтобы прочитать данные, которые дочерний процесс отправляет обратно в Node. stdout, являющийся потоком, имеет «данные», «конец» и другие события, которые имеют потоки. spawn лучше всего использовать, когда вы хотите, чтобы дочерний процесс возвращал большой объем данных в Node - обработка изображений, чтение двоичных данных и т. д.
так что вы можете решить свою проблему с помощью child_process.spawn, как показано ниже.
var spawn = require('child_process').spawn, ls = spawn('coffee -cw my_file.coffee'); 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('code ' + code.toString()); });
источник
Вот вспомогательная функция async, написанная на машинописном тексте, которая, кажется, помогает мне. Я думаю, это не сработает для долгоживущих процессов, но все же может кому-то пригодиться?
import * as child_process from "child_process"; private async spawn(command: string, args: string[]): Promise<{code: number | null, result: string}> { return new Promise((resolve, reject) => { const spawn = child_process.spawn(command, args) let result: string spawn.stdout.on('data', (data: any) => { if (result) { reject(Error('Helper function does not work for long lived proccess')) } result = data.toString() }) spawn.stderr.on('data', (error: any) => { reject(Error(error.toString())) }) spawn.on('exit', code => { resolve({code, result}) }) }) }
источник