Exec: display stdout " live"

Mam taki prosty skrypt:

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

exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
    console.log(stdout);
});

Gdzie po prostu wykonuję polecenie, aby skompilować plik coffee-script. Ale stdout nigdy nie jest wyświetlany w konsoli, ponieważ polecenie nigdy się nie kończy (z powodu opcji-w coffee). Jeśli wykonam komendę bezpośrednio z konsoli, otrzymuję wiadomość w następujący sposób:

18:05:59 - compiled my_file.coffee

Moje pytanie brzmi: czy możliwe jest wyświetlanie tych wiadomości za pomocą węzła.js exec ? Jeśli tak, jak ? !

Dzięki

Author: mravey, 2012-04-19

9 answers

Nie używaj exec. Użycie spawn który jest obiektem EventEmmiter. Wtedy możesz posłuchać stdout/stderr wydarzenia (spawn.stdout.on('data',callback..)) Jak to się dzieje .

Z dokumentacji 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 buforuje wyjście i zwykle zwraca je po zakończeniu wykonywania polecenia.

 283
Author: Pooria Azimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-12 14:59:06

exec zwróci również obiekt potomny, który jest obiektem typu EventEmitter.

var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');

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

Lub pipe stdout procesu potomnego do głównego stdout.

coffeeProcess.stdout.pipe(process.stdout);

Lub dziedziczyć stdio używając spawn

spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
 195
Author: Nathanael Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-15 17:09:55

Jest już kilka odpowiedzi, jednak żadna z nich nie wspomina o najlepszym (i najłatwiejszym) sposobie, jakim jest użycie spawn i { stdio: 'inherit' } Opcja . Wydaje się, że generuje najdokładniejsze dane wyjściowe, na przykład podczas wyświetlania informacji o postępie z git clone.

Po prostu zrób to:

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

spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });

Podziękowania dla @ MorganTouvereyQuilling za wskazanie tego w ten komentarz .

 64
Author: Livven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32

Zainspirowany odpowiedzią Nathanaela Smitha i komentarzem Erica Freese, może to być tak proste, jak:

var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
 23
Author: Tyler Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-18 10:39:02

Chciałbym tylko dodać, że jeden mały problem z wyprowadzaniem łańcuchów bufora z procesu spawanego z console.log() polega na tym, że dodaje on nowe linie, które mogą rozłożyć wynik spawanego procesu na dodatkowe linie. Jeśli wykonasz stdout lub stderr z process.stdout.write() zamiast console.log(), to uzyskasz wyjście konsoli z procesu wywołanego 'as is'.

Widziałem to rozwiązanie tutaj: węzeł.js: drukowanie na konsoli Bez kończącego się znaku nowego wiersza?

Nadzieję, że pomoże ktoś korzystający z rozwiązania powyżej (co jest Świetne dla wyjścia na żywo, nawet jeśli jest z dokumentacji).

 21
Author: Kevin Teljeur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:47

Uważam, że pomocne jest dodanie niestandardowego skryptu exec do moich narzędzi, które to robią.

Narzędzia.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')
 13
Author: IanLancaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-31 18:47:52

Po przejrzeniu wszystkich innych odpowiedzi, skończyło się na tym:

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);
    });
}

Czasami data będzie wiele linii, więc nagłówek oldSchoolMakeBuild pojawi się raz dla wielu linii. Ale to nie przeszkadzało mi na tyle, żeby to zmienić.

 5
Author: Tongfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 17:15:36

Child_process.spawn zwraca obiekt ze strumieniami stdout i stderr. Możesz dotknąć strumienia stdout, aby odczytać dane, które proces potomny wysyła z powrotem do węzła. stdout jako strumień ma "data", " end " i inne zdarzenia, które mają strumienie. spawn jest najlepiej używany, gdy chcesz, aby proces potomny zwrócił dużą ilość danych do węzła-przetwarzanie obrazów, odczyt danych binarnych itp.

Więc możesz rozwiązać swój problem używając child_process.spawn jak poniżej.

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());
});
 3
Author: Adeojo Emmanuel IMM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 07:06:37

Oto asynchroniczna funkcja pomocnicza napisana w maszynopisie, która wydaje się robić sztuczkę dla mnie. Myślę, że to nie będzie działać dla długotrwałych procesów, ale nadal może być przydatne dla kogoś?

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})
        })
    })
}
 1
Author: Swaner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-27 09:02:24