[javascript] node.js 셸 명령 실행

Linux 또는 Windows 셸 명령을 실행하고 node.js 내에서 출력을 캡처 할 수있는 방법에 대한 세부 사항을 여전히 파악하려고합니다. 궁극적으로 이렇게하고 싶습니다 …

//pseudocode
output = run_command(cmd, args)

중요한 부분은 output전역 범위 변수 (또는 개체)에서 사용할 수 있어야한다는 것입니다. 다음 기능을 시도했지만 어떤 이유로 undefined콘솔에 인쇄됩니다 …

function run_cmd(cmd, args, cb) {
  var spawn = require('child_process').spawn
  var child = spawn(cmd, args);
  var me = this;
  child.stdout.on('data', function(me, data) {
    cb(me, data);
  });
}
foo = new run_cmd('dir', ['/B'], function (me, data){me.stdout=data;});
console.log(foo.stdout);  // yields "undefined" <------

위의 코드가 어디에서 깨지는 지 이해하는 데 어려움이 있습니다 … 그 모델의 매우 간단한 프로토 타입이 작동합니다 …

function try_this(cmd, cb) {
  var me = this;
  cb(me, cmd)
}
bar = new try_this('guacamole', function (me, cmd){me.output=cmd;})
console.log(bar.output); // yields "guacamole" <----

누군가가 왜 try_this()작동하고 run_cmd()작동하지 않는지 이해하도록 도울 수 있습니까 ? FWIW, 200KB 버퍼 제한이 child_process.spawn있기 child_process.exec때문에을 사용해야 합니다.

최종 해결책

나는 James White의 대답을 받아들이고 있지만 이것은 나를 위해 일한 정확한 코드입니다 …

function cmd_exec(cmd, args, cb_stdout, cb_end) {
  var spawn = require('child_process').spawn,
    child = spawn(cmd, args),
    me = this;
  me.exit = 0;  // Send a cb to set 1 when cmd exits
  me.stdout = "";
  child.stdout.on('data', function (data) { cb_stdout(me, data) });
  child.stdout.on('end', function () { cb_end(me) });
}
foo = new cmd_exec('netstat', ['-rn'],
  function (me, data) {me.stdout += data.toString();},
  function (me) {me.exit = 1;}
);
function log_console() {
  console.log(foo.stdout);
}
setTimeout(
  // wait 0.25 seconds and print the output
  log_console,
250);



답변

여기에서 수정해야 할 세 가지 문제가 있습니다.

첫 번째 는 stdout을 비동기 적으로 사용하는 동안 동기 동작을 기대한다는 것입니다. run_cmd함수 의 모든 호출 은 비동기식이므로 자식 프로세스를 생성하고 데이터의 일부, 전체 또는 데이터가 stdout에서 읽혀지지 않았는지 여부에 관계없이 즉시 반환됩니다. 따라서 실행하면

console.log(foo.stdout);

현재 foo.stdout에 저장되는 것은 무엇이든 얻을 수 있으며 자식 프로세스가 여전히 실행 중일 수 있기 때문에 그것이 무엇인지 보장 할 수 없습니다.

두 번째 는 stdout이 읽을 수있는 스트림 이므로 1) 데이터 이벤트를 여러 번 호출 할 수 있고 2) 콜백에 문자열이 아닌 버퍼가 제공된다는 것입니다. 치료하기 쉽습니다. 그냥 변경

foo = new run_cmd(
    'netstat.exe', ['-an'], function (me, data){me.stdout=data;}
);

으로

foo = new run_cmd(
    'netstat.exe', ['-an'], function (me, buffer){me.stdout+=buffer.toString();}
);

버퍼를 문자열로 변환하고 해당 문자열을 stdout 변수에 추가합니다.

세 번째 는 ‘end’이벤트를 받았을 때 모든 출력을 받았음을 알 수 있다는 것입니다. 즉, 다른 리스너와 콜백이 필요합니다.

function run_cmd(cmd, args, cb, end) {
    // ...
    child.stdout.on('end', end);
}

따라서 최종 결과는 다음과 같습니다.

function run_cmd(cmd, args, cb, end) {
    var spawn = require('child_process').spawn,
        child = spawn(cmd, args),
        me = this;
    child.stdout.on('data', function (buffer) { cb(me, buffer) });
    child.stdout.on('end', end);
}

// Run C:\Windows\System32\netstat.exe -an
var foo = new run_cmd(
    'netstat.exe', ['-an'],
    function (me, buffer) { me.stdout += buffer.toString() },
    function () { console.log(foo.stdout) }
);


답변

받아 들여지는 대답의 단순화 된 버전 (세 번째 점)은 저에게 효과적이었습니다.

function run_cmd(cmd, args, callBack ) {
    var spawn = require('child_process').spawn;
    var child = spawn(cmd, args);
    var resp = "";

    child.stdout.on('data', function (buffer) { resp += buffer.toString() });
    child.stdout.on('end', function() { callBack (resp) });
} // ()

용법:

run_cmd( "ls", ["-l"], function(text) { console.log (text) });

run_cmd( "hostname", [], function(text) { console.log (text) });


답변

나는 이것을 더 간결하게 사용했습니다.

var sys = require('sys')
var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("ls -la", puts);

완벽하게 작동합니다. 🙂


답변

가장 간단한 방법은 ShellJS lib를 사용하는 것입니다.

$ npm install [-g] shelljs

EXEC 예 :

require('shelljs/global');

// Sync call to exec()
var version = exec('node --version', {silent:true}).output;

// Async call to exec()
exec('netstat.exe -an', function(status, output) {
  console.log('Exit status:', status);
  console.log('Program output:', output);
});

ShellJs.org 는 다음을 포함하여 NodeJS 함수로 매핑 된 많은 공통 셸 명령을 지원합니다.

  • 고양이
  • CD
  • chmod
  • cp
  • Dirs
  • 에코
  • 임원
  • 출구
  • 찾기
  • grep
  • ln
  • ls
  • mkdir
  • mv
  • 푸시
  • 암호
  • rm
  • sed
  • 테스트
  • 어느

답변

비슷한 문제가 있었고 결국 이에 대한 노드 확장을 작성했습니다. git 저장소를 확인할 수 있습니다. 그것은 오픈 소스이며 무료이며 모든 좋은 것들입니다!

https://github.com/aponxi/npm-execxi

ExecXI는 C ++로 작성된 노드 확장으로, 쉘 명령을 하나씩 실행하여 명령의 출력을 실시간으로 콘솔에 출력합니다. 선택적 연결 및 연결 해제 방법이 있습니다. 즉, 명령이 실패 (체인) 된 후 스크립트를 중지하도록 선택하거나 아무 일도 일어나지 않은 것처럼 계속할 수 있습니다!

사용 지침은 ReadMe 파일에 있습니다. 풀 요청을하거나 문제를 제출하십시오!

나는 그것을 언급 할 가치가 있다고 생각했다.


답변

@ TonyO’Hagan은 포괄적 인 shelljs대답이지만 그의 대답의 동기 버전을 강조하고 싶습니다.

var shell = require('shelljs');
var output = shell.exec('netstat -rn', {silent:true}).output;
console.log(output);


답변

동기식 한 줄 :

require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });