Используйте child_process.execSync, но сохраняйте вывод в консоли

160

Я хотел бы использовать execSyncметод, который был добавлен в NodeJS 0.12, но у меня все еще есть вывод в окне консоли, из которого я запускал скрипт Node.

Например, если я запускаю скрипт NodeJS со следующей строкой, я бы хотел видеть полный вывод команды rsync "live" внутри консоли:

require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"');

Я понимаю, что execSyncвозвращает результат команды и что я могу распечатать это на консоли после выполнения, но у меня нет «живого» вывода ...

suamikim
источник

Ответы:

324

Вы можете передать stdio родителя дочернему процессу, если это то, что вы хотите:

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);
Gregers
источник
3
Это означает, что дочерний процесс будет использовать родительские потоки stdin, stdout и stderr. Поэтому, когда дочерний процесс пишет в любой из них, он фактически будет записан непосредственно в поток родителя.
gregers
7
Это очень ценный ответ, так как официальная документация не совсем ясно об ожидаемом синтаксисе.
chikamichi
49
Вместо того [0,1,2], чтобы использовать 'inherit', что эквивалентно [process.stdin, process.stdout, process.stderr]или [0,1,2]согласно документам
Курт
10
Правильная ссылка на options.stdioдокументацию: nodejs.org/api/child_process.html#child_process_options_stdio
Шон Леброн
2
@ Booligoosh Вместо простого добавления {stdio:'inherit'}вы должны добавить .toString (), а затем вручную вызвать console.log с результатом. Кроме того, он даже не отвечает требованию вопросов, чтобы увидеть вывод команды "вживую". Я не думаю, что это "намного проще", на самом деле я не думаю, что это вообще проще.
Boileau
19

Вы можете просто использовать .toString().

var result = require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"').toString();
console.log(result);

Это было проверено на Node v8.5.0, я не уверен насчет предыдущих версий. По словам @etov , это не работает v6.3.1- я не уверен насчет промежуточного.

Итан
источник
3
Это не работает при сбое (код состояния! = 0), потому что .execSync()создает Errorэкземпляр.
Альваро Гонсалес
У меня не работает, т.е. вывод записывается только после завершения команды. Это относится к конкретной версии? мой узел -v: v6.3.1
етов
Пожалуйста, рассмотрите возможность обновления ответа, чтобы отметить, что он применим только к определенным версиям узла - это сделает его более полезным для других
etov
1
Пониженное голосование, поскольку в настоящее время выполняется вопрос о выводе во время выполнения команды.
Карфау
14

Если вы не перенаправите stdout и stderr, как предполагает принятый ответ, это невозможно с execSync или spawnSync. Без перенаправления stdout и stderr эти команды возвращают stdout и stderr только после завершения команды.

Чтобы сделать это без перенаправления stdout и stderr, вам нужно использовать spawn, но это довольно просто:

var spawn = require('child_process').spawn;

//kick off process of listing files
var child = spawn('ls', ['-l', '/']);

//spit stdout to screen
child.stdout.on('data', function (data) {   process.stdout.write(data.toString());  });

//spit stderr to screen
child.stderr.on('data', function (data) {   process.stdout.write(data.toString());  });

child.on('close', function (code) { 
    console.log("Finished with code " + code);
});

Я использовал команду ls, которая рекурсивно выводит список файлов, чтобы вы могли быстро их проверить. Spawn принимает в качестве первого аргумента имя исполняемого файла, который вы пытаетесь запустить, а в качестве второго аргумента он принимает массив строк, представляющих каждый параметр, который вы хотите передать этому исполняемому файлу.

Однако, если вы настроены на использование execSync и по какой-то причине не можете перенаправить stdout или stderr, вы можете открыть другой терминал, такой как xterm, и передать ему такую ​​команду:

var execSync = require('child_process').execSync;

execSync("xterm -title RecursiveFileListing -e ls -latkR /");

Это позволит вам увидеть, что ваша команда делает в новом терминале, но при этом иметь синхронный вызов.

Брайан
источник
2
Пример использования spawn может быть правильным, но вводное утверждение о том, что он не собирается использовать execSync, неверно. Смотрите ответ @gregers
AgDude