실행 : stdout“live”표시


188

나는이 간단한 스크립트를 가지고있다 :

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

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

여기서 간단히 커피 스크립트 파일을 컴파일하는 명령을 실행합니다. 그러나 명령은 절대 종료되지 않기 때문에 (stupout은 콘솔에 표시되지 않습니다 (커피의 -w 옵션 때문에). 콘솔에서 직접 명령을 실행하면 다음과 같은 메시지가 나타납니다.

18:05:59 - compiled my_file.coffee

내 질문은 : node.js exec와 함께 이러한 메시지를 표시 할 수 있습니까? 그렇다면 어떻게? !

감사


1
파이썬 실행 파일에서 stdout을 캡처하려고 여기에 왔습니다. 아래의 모든 기능이 작동하지만 "-u"옵션을 사용하여 파이썬을 실행하여 버퍼링하지 않고 실시간 업데이트를 수행해야합니다.
Andy

답변:


266

를 사용하지 마십시오 exec. spawn어떤 EventEmmiter객체를 사용하십시오 . 그럼 당신은들을 수 있습니다 stdout/ stderr이벤트 ( 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 출력을 버퍼링하고 일반적으로 명령 실행이 끝나면 출력을 반환합니다.


22
아주 좋아요 참고로 다음 표준 출력을 / 표준 오류 이벤트는 인수의 데이터를 '버퍼가 너무)로 .toString (로 호출되는 콜백
세르 겔

4
Windows에서 스폰 할 수없는 사용자는이 훌륭한 답변을 살펴보십시오 .
tomekwi

17
exec는 최소한 최신 이벤트 이미 터입니다.
Nikolay Tsenkov 2016 년

4
또한 프로그램이 개행을 출력 할 때마다 콜백이 호출되지 않습니다. 자식 프로세스에서 "이벤트"를 받으려면 flush(stdout);Node.js에서 이벤트를 발생시키기 위해이 프로세스는 버퍼를 플러시 ( C) 해야합니다 .
Julian F. Weinert 1

5
exec에서 +1도 EventEmitter입니다. 문자열을 args 배열 (매우 길고 복잡한 ffmpeg 명령 줄)로 리팩토링하는 데 2 ​​시간이 걸렸습니다.
deadconversations

176

exec EventEmitter 인 ChildProcess 객체도 반환합니다.

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('coffee -cw my_file.coffee', { stdio: 'inherit' });

35
다음을 사용하여 간단히 단순화 할 수 있습니다 pipe.coffeeProcess.stdout.pipe(process.stdout);
Eric Freese

3
@EricFreese의 의견은 내가 찾고있는 것입니다. 왜냐하면 stdout의 문자 교체 기능 (노드 스크립트에서 각도기 활용)을 활용하고 싶었 기 때문입니다.
LoremIpsum

19
더 간단합니다 : spawn(cmd, argv, { stdio: 'inherit' }). 다른 예는 nodejs.org/api/child_process.html#child_process_options_stdio 를 참조하십시오 .
Morgan Touverey Quilling 2014 년

3
MorganTouvereyQuilling의 제안이 사용하는 @ +1 spawnstdio: 'inherit'. 더 정확한 출력보다 생산 exec및 배관 stdout/ stderr하는 진척 정보를 표시 할 때, 예를 들면 git clone.
Livven

57

그들 중 누구도 사용되는이 수행하는 가장 좋은 (쉬운) 방법은 언급하지 그러나 몇 가지 답변이 이미 있습니다 spawn{ stdio: 'inherit' }옵션 . 예를 들어에서 진행 정보를 표시 할 때 가장 정확한 출력을 생성하는 것 같습니다 git clone.

간단히 이렇게하십시오 :

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

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

이 의견 에서 이것을 지적한 것에 대해 @MorganTouvereyQuilling에게 감사드립니다 .


1
하위 프로세스가 컬러 텍스트와 같은 형식의 출력을 사용할 때 stdio: "inherit"해당 형식 child.stdout.pipe(process.stdout)은 유지하면서 유지합니다 .
Rikki Gibson

이는 npm 설치의 진행률 표시 줄과 같이 복잡한 출력이있는 프로세스에서도 출력을 완벽하게 유지합니다. 대박!
Dave Koo

1
왜 이것이 받아 들여지지 않은 대답입니까? 그것은 나를 위해 일한 유일한 사람이었고 단지 2 f * 줄입니다!
링컨

이 팁은 진행률 표시 줄을 사용하는 일부 Symfony 명령 행 응용 프로그램을 실행할 때 도움이되었습니다. 건배.
Halfstop

이것은 완벽한 출력 표현을 보존 허용 대답 만 일해야 하고 그것은 간단한입니까? 예
evnp

21

생성 된 프로세스에서 버퍼 문자열을 출력 할 때 발생하는 작은 문제 console.log()는 줄 바꿈을 추가하여 생성 된 프로세스 출력을 추가 행에 분산시킬 수 있다는 것입니다. 출력 할 경우 stdout또는 stderr으로 process.stdout.write()대신 console.log()에, 당신은 '있는 그대로'를 양산 과정에서 콘솔 출력을 얻을 수 있습니다.

나는 그 해결책을 여기에서 보았습니다 : Node.js : 줄 바꿈없이 콘솔에 인쇄합니까?

누군가가 위의 솔루션을 사용하는 데 도움이되기를 바랍니다 (문서에서 가져온 경우에도 라이브 출력에 큰 솔루션입니다).


1
spawn(command, args, { stdio: 'inherit' })@MorganTouvereyQuilling에서 제안한 것처럼 보다 정확한 출력 사용 을 위해 여기 stackoverflow.com/questions/10232192/…
Livven

21

Nathanael Smith의 답변과 Eric Freese의 의견에서 영감을 얻은 결과는 다음과 같습니다.

var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);

이것은 간단한 명령의 경우에는 잘 작동하는 것 같지만 ls보다 복잡한 명령의 경우에는 실패합니다 npm install. 나는 stdout과 stderr을 각각의 프로세스 객체에 파이핑하려고 시도했습니다.
linuxdan

@linuxdan npm이 stderr로 쓰고 있기 때문일 수 있습니다 (일부 진행률 표시 줄을 보았습니다). stderr를 파이프하거나 Tongfa 솔루션을 확장하여 stderr에서들을 수 있습니다.
Sergiu

@linuxdan 내가 본 가장 신뢰할 수있는 방법은 다음 spawn(command, args, { stdio: 'inherit' })과 같습니다. stackoverflow.com/questions/10232192/…
Livven

최고의 답변입니다. 감사합니다. 매력처럼
Abhishek Sharma

12

이 작업을 수행하는 유틸리티에 사용자 정의 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')

5

다른 모든 답변을 검토 한 결과 다음과 같이 끝났습니다.

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표시 되므로 여러 줄에 대해 머리글이 한 번 나타납니다. 그러나 이것은 그것을 바꿀만큼 귀찮지 않았습니다.


3

child_process.spawn은 stdout 및 stderr 스트림이있는 객체를 반환합니다. stdout 스트림을 눌러 하위 프로세스가 노드로 다시 보내는 데이터를 읽을 수 있습니다. 스트림 인 stdout에는 "data", "end"및 스트림에있는 기타 이벤트가 있습니다. 스폰은 자식 프로세스가 이미지 처리, 이진 데이터 읽기 등 많은 양의 데이터를 노드에 반환하도록하려는 경우에 가장 적합합니다.

따라서 아래와 같이 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());
});

1

여기에 나를 위해 속임수를 쓰는 것으로 보이는 typescript로 작성된 비동기 도우미 함수가 있습니다. 오래 지속되는 프로세스에서는 작동하지 않지만 여전히 누군가에게 도움이 될 것 같습니까?

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})
        })
    })
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.