2015-06-03 3 views
5

Мне нужно записать в пользовательский поток выход из порожденного дочернего процесса.Node.js: Захват STDOUT из `child_process.spawn`

child_process.spawn(command[, args][, options]) 

Например,

var s = fs.createWriteStream('/tmp/test.txt'); 
child_process.spawn('ifconfig', [], {stdio: [null, s, null]}) 

Теперь, как я прочитал из /tmp/test.txt в режиме реального времени?

Похоже, что child_process.spawn не использует stream.Writable.prototype.write или stream.Writable.prototype._write для его исполнения.

Например,

s.write = function() { console.log("this will never get printed"); }; 

Как,

s.__proto__._write = function() { console.log("this will never get printed"); }; 

Похоже, он использует файловые дескрипторы под капотом писать с child_process.spawn в файл.

Делать это не работает:

var s2 = fs.createReadStream('/tmp/test.txt'); 
s2.on("data", function() { console.log("this will never get printed either"); }); 

Итак, как я могу получить STDOUT содержимое дочернего процесса?

То, что я хочу достичь, - это поток STDOUT дочернего процесса в сокет. Если я предоставляю сокет непосредственно в child_process.spawn как параметр stdio, он закрывает сокет, когда он заканчивается, но я хочу, чтобы он был открыт.

Update:

Решение использовать по умолчанию {stdio: ['pipe', 'pipe', 'pipe']} параметры и прослушивания созданного .stdout дочернего процесса.

var cmd = child_process.spaw('ifconfig'); 
cmd.stdout.on("data", (data) => { ... }); 

Теперь, чтобы поднять ставки, более сложный вопрос:

- Как вы читаете STDOUT дочернего процесса и до сих пор сохраняют цвета?

Например, если вы отправляете STDOUT в process.stdout так:

child_process.spawn('ifconfig', [], {stdio: [null, process.stdout, null]}); 

он будет держать цвета и печать цветной вывод на консоль, потому что свойство .isTTY устанавливается в true на process.stdout.

process.stdout.isTTY // true 

Теперь, если вы используете по умолчанию {stdio: ['pipe', 'pipe', 'pipe']}, данные, которые вы будете читать будет лишен консольных цветов. Как вы получаете цвета?

Один из способов сделать это: создать свой собственный поток с помощью fs.createWriteStream, потому что child_process.spawn требует, чтобы ваши потоки имели файловый дескриптор.

Затем установка .isTTY этого потока на true, чтобы сохранить цвета.

И, наконец, вам нужно будет захватить данные, что child_process.spawn записывает в этот поток, но так как child_process.spawn не использует .prototype.write ни .prototype._write потока, вам нужно будет захватить его содержимое в каком-либо другом Hacky способа.

Вот почему, вероятно child_process.spawn требует вашего потока иметь дескриптор файла, потому что он обходит .prototype.write вызов и записывает непосредственно в файл под капотом.

Любые идеи, как реализовать это?

ответ

4

Вы можете сделать это без использования временный файл:

var process = child_process.spawn(command[, args][, options]); 
process.stdout.on('data', function (chunk) { 
    console.log(chunk); 
}); 
+0

работает как шарм! – Vad

+0

Действительно ли это блокирует выходной поток между операторами или какой-либо вывод в этом интервале потерян? –

+0

@AsadSaeeduddin нет, он не блокируется. – Magomogo

1

Привет Я на моем телефоне, но я буду стараться, чтобы направлять вас, как я могу. Я уточню, когда рядом с компьютером, если необходимо

Я думаю, что вы хотите прочитать stdout от икры и сделать что-нибудь с данными?

Вы можете дать икру имя переменной вместо того, чтобы просто запустить функцию, например:

var child = spawn(); 

Тогда слушайте к выходу, как:

child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 

Вы могли бы использовать, чтобы записать данные затем в файл или все, что вы можете с ним сделать.

+0

Спасибо, за быстрый ответ! – Vad

0

Для опции stdio нужны файловые дескрипторы, а не потоковые объекты, поэтому одним из способов сделать это является использование fs.openSync() для создания дескриптора выходного файла и нас.

Принимая первый пример, но с использованием fs.openSync():

var s = fs.openSync('/tmp/test.txt', 'w'); 
var p = child_process.spawn('ifconfig', [], {stdio: [process.stdin, s, process.stderr]}); 

Можно также установить как стандартный вывод и стандартный поток ошибок тот же дескриптор файла (для того же эффекта, как в Bash 2>&1).

Вам необходимо закрыть файл, когда вы сделали, так:

p.on('close', function(code) { 
    fs.closeSync(s); 
    // do something useful with the exit code ... 
}); 
Смежные вопросы