2013-01-15 18 views
45

Mam skrypt, który wyświetla "cześć", śpi na sekundę, wyświetla "cześć", śpi przez 1 sekundę i tak dalej i tak dalej. Teraz myślałem, że będę w stanie poradzić sobie z tym problemem z tym modelem.Node.js odradza proces potomny i pobiera dane wyjściowe z terminala na żywo

var spawn = require('child_process').spawn, 
temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR'); 

temp.stdout.pipe(process.stdout); 

Problem polega na tym, że zadanie musi zostać zakończone, aby dane wyjściowe były wyświetlane. Jak ja to rozumiem, wynika to z faktu, że nowo utworzony proces przejmuje kontrolę wykonania. Oczywiście node.js nie obsługuje wątków, więc jakieś rozwiązania? Mój pomysł polegał na tym, aby uruchomić dwie instancje, pierwszą w konkretnym celu tworzenia zadania i poprowadzić wyjście do procesu drugiej instancji, biorąc pod uwagę, że można to osiągnąć.

Odpowiedz

52

Nadal staję się mokra z Node.js, ale mam kilka pomysłów. po pierwsze, uważam, że musisz użyć execFile zamiast spawn; execFile dotyczy sytuacji, gdy masz ścieżkę do skryptu, natomiast spawn służy do wykonywania dobrze znanego polecenia, które Node.js może rozwiązać na ścieżce systemowej.

1. Provide a callback przetwarzać dekoduje:

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when the 
    console.log(stdout); 
}); 

2. dodać detektor do procesu dzieci standardowe wyjście stream (9thport.net)

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 

Ponadto, wydaje się, że możliwości czym otrzymano możesz odłączyć odrodzony proces od terminala sterującego Node, co pozwoli mu działać asynchronicznie. Nie testowałem tego jeszcze, ale istnieją przykłady w API docs które idą mniej więcej tak:

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ] 
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 
+5

punkty, jeśli można wyjaśnić w jaki sposób to zrobić z exec() jak trzeba wykonać polecenie cmd powłoki. – DynamicDan

+1

Możesz użyć 'child.spawn()' z opcją 'shell' ustawioną na' true'. https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options – CedX

+1

Możesz także potokować child.stdout bezpośrednio do process.stdout za pomocą 'child.stdout.pipe (process.stdout);' – darkadept

1

dziecko:

setInterval(function() { 
    process.stdout.write("hi"); 
}, 1000); // or however else you want to run a timer 

parent:

require('child_process').fork('./childfile.js'); 
// fork'd children use the parent's stdio 
60

Jest dużo łatwiej teraz (2 lata później)!

Spawn zwraca childObject, które można następnie nasłuchiwanie zdarzeń z.Te wydarzenia są:

  • Klasa: ChildProcess
    • Wydarzenie: 'błąd'
    • Wydarzenie: 'exit'
    • Wydarzenie: 'blisko'
    • Wydarzenie: 'odłączyć'
    • Zdarzenie: "wiadomość"

Istnieje także grono obiektów z childObject, są to:

  • Klasa: ChildProcess
    • child.stdin
    • child.stdout
    • child.stderr
    • dziecko .stdio
    • child.pid
    • child.connected
    • child.kill ([sygnału])
    • child.send (komunikat [, sendHandle] [,] zwrotnego)
    • child.disconnect()

Patrz więcej informacji tutaj o childObject: https://nodejs.org/api/child_process.html

Więc, łącząc to wszystko, można uzyskać:

var spawn = require('child_process').spawn; 
var child = spawn('node ./commands/server.js'); 
child.stdout.on('data', function(data) { 
    console.log('stdout: ' + data); 
    //Here is where the output goes 
}); 
child.stderr.on('data', function(data) { 
    console.log('stderr: ' + data); 
    //Here is where the error output goes 
}); 
child.on('close', function(code) { 
    console.log('closing code: ' + code); 
    //Here you can get the exit code of the script 
}); 

I w ten sposób można uzyskać wyjście z węzłem!

+4

+1, to powinno być wybrana teraz jako właściwa odpowiedź. Tylko uwaga, zmienna danych w wywołaniu zwrotnym przychodzi jako obiekt bufora. Możesz użyć '' 'child.stdout.setEncoding ('utf8')' '' jeśli chcesz, aby łańcuchy utf8 wchodziły. – Ashish

+0

Próbuję uruchomić skrypt Pythona; jego działanie, ale wynik nie nadchodzi tutaj. 'var spawn = require ('child_process'). spawn; var child = spawn ('python', ['/my/path/to/python/file/my_python_file.py']); child.stdout.on ('dane', funkcja (dane) { console.log ('stdout:' + dane); }); child.stderr.on ('dane', funkcja (dane) { console.log ('stderr:' + dane); }); child.on ("zamknij", funkcja (kod) { console.log ("kod zamykający:" kod); }); ' – ishandutta2007

10

Miałem małe problemy z uzyskaniem wyniku logowania z polecenia "npm install", gdy zarodnik wystartował w procesie potomnym. Rejestrowanie zależności w czasie rzeczywistym nie było wyświetlane w konsoli nadrzędnej.

Najprostszym sposobem, aby robić to, co oryginalny plakat chce wydaje się to (ikra npm na oknach i zalogować wszystko do konsoli dominującej):

var args = ['install']; 

var options = { 
    stdio: 'inherit' //feed all child process logging into parent process 
}; 

var childProcess = spawn('npm.cmd', args, options); 
childProcess.on('close', function(code) { 
    process.stdout.write('"npm install" finished with code ' + code + '\n'); 
}); 
0

znalazłem się wymagająca tę funkcjonalność na tyle często, że pakuje się go do biblioteki o nazwie std-pour. Powinien umożliwić wykonanie polecenia i przeglądanie danych wyjściowych w czasie rzeczywistym. Aby zainstalować wystarczy:

npm install std-pour 

Wtedy to dość proste do wykonania polecenia i zobaczyć wyjście w czasie rzeczywistym:

const { pour } = require('std-pour'); 
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`)); 

on obiecał dzięki czemu możliwe jest łańcuchowe wielu poleceń. Jest nawet kompatybilny z funkcją podpisu pod numerem child_process.spawn, więc powinien być to kropla wymiany w dowolnym miejscu.

3

Oto najczystsze podejście Znalazłem:

require("child_process").spawn('bash', ['./script.sh'], { 
    cwd: process.cwd(), 
    detached: true, 
    stdio: "inherit" 
}); 
Powiązane problemy