Використовуйте child_process.execSync, але зберігайте вихід у консолі


160

Я хотів би скористатися execSyncметодом, який був доданий у NodeJS 0,12, але все ще маю вихід у вікні консолі, з якого я запустив сценарій Node.

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

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

Я розумію, що execSyncповертає вихід команди і що я можу надрукувати це на консолі після виконання, але таким чином у мене немає "живого" виводу ...

Відповіді:


324

Ви можете передати stdio батьківського дочірнього процесу, якщо це саме ви хочете:

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);

3
Це означає, що дочірній процес використовує батьківські потоки stdin, stdout та stderr. Отже, коли дочірній процес записує будь-який з них, він буде фактично записаний безпосередньо в поток батьків.
грегер

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 вручну з результатом. Крім того, він навіть не відповідає вимогам запитання про те, щоб побачити команду "live". Я не думаю, що це "набагато простіше", адже я взагалі не думаю, що це простіше.
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

Будь ласка, подумайте над оновленням відповіді, щоб зауважити, що вона застосовується лише до певних версій вузла - це зробить її більш корисною для інших
etov

1
Нижній переказ, оскільки ti в даний час стосується питання щодо виводу під час виконання команди.
karfau

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
Приклад з використанням нересту може бути правильним, але вступне твердження про те, що не збирається використовувати execSync, не є точним. Дивіться відповідь від @gregers
AgDude
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.