2014-06-30 8 views
7

Próbuję uzyskać dwa długo działające procesy do komunikacji - rodzic i dziecko - za pomocą potoków i modułu Node'a . Chcę, aby dziecko mogło wysyłać dane z powrotem do rodzica asynchronicznie i miałem nadzieję, że użyję do tego celu .Procesy potomne i potoki Node.js - OSX vs Ubuntu

Oto uproszczona wersja mojego kodu:

nadrzędny:

cp = require('child_process') 
es = require('event-stream') 

child = cp.spawn('coffee', ['child.coffee'], {stdio: [null, null, null, 'pipe']}) 

so = child.stdout.pipe(es.split()) 
p3 = child.stdio[3].pipe(es.split()) 

so.on 'data', (data) -> 
    console.log('stdout: ' + data) 

child.stderr.on 'data', (data) -> 
    console.log('stderr: ' + data); 

p3.on 'data', (data) -> 
    console.log('stdio3: ' + data); 

child.on 'close', (code) -> 
    console.log('child process exited with code ' + code) 

child.stdin.write "a message from your parent", "utf8" 

dziecka:

fs = require('fs') 

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

process.stdin.on 'data', (data) -> 
    p3.write "hello #{process.pid} - #{data}\n", 'utf8' 
    process.stdout.write "world #{process.pid} - #{data}\n", 'utf8' 
    p3.end() 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    p3.end() 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

Kod działa na OSX 10.9, ale nie do pracy na polu Ubuntu. Próbowałem go uruchomić zarówno pod Ubuntu 12.04 i 14.04. Używam węzła 10.2x.

/dev/fd/ pod Ubuntu jest symbolicznie połączony z /proc/self/fd/, więc wierzę, że mój proces potomny otwiera właściwy plik.

Wyjście z systemem rodzica na Ubuntu jest następujący:

$ coffee parent.coffee 
stderr: 

stderr: events.js:72 

stderr:   throw er; // Unhandled 'error' event 

stderr: 
stderr: 
stderr: 
stderr: 
stderr:   ^

stderr: Error: UNKNOWN, open '/dev/fd/3' 




events.js:72 
     throw er; // Unhandled 'error' event 
      ^
Error: read ECONNRESET 
    at errnoException (net.js:901:11) 
    at Pipe.onread (net.js:556:19) 

Spodziewam się, aby zobaczyć (i zrobić na polu OSX):

$ coffee parent.coffee 
stdio3: hello 21101 - a message from your parent 
stdout: world 21101 - a message from your parent 
stdio3: 
stdout: 
child process exited with code 0 

Jest możliwość komunikowania się z dziecko korzystające z wiersza poleceń także w systemie Ubuntu, więc problem jest prawdopodobnie u rodzica podczas tworzenia procesu potomnego:

$ echo foo | coffee child.coffee 3>&1 
hello 3077 - foo 

world 3077 - foo 

Próbowałem zbadać wywołania jądra, które węzeł wykonuje za pomocą , ale nie mógł mieć wiele sensu na wyjściu.

+0

Co to jest wyjście 'ps aux | grep node', gdy oba procesy są uruchomione? – ctlacko

+0

@ChrisLacko Polecenie 'coffee parent.coffee' natychmiast ulega awarii. Na OSX wypisuje to, co ma, a następnie kończy pracę. Mogę dodać błędy, które widzę po uruchomieniu go w poście. – Jacob

Odpowiedz

4

Sam to wymyśliłem. Błąd był w dziecku. Ubuntu linux jest bardziej rygorystyczny, jeśli chodzi o otwieranie plików, które są już otwarte, linia:

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

Wystąpił błąd. Deskryptor 3 jest już otwarty, gdy dziecko skończy, więc kod powinien wyglądać następująco:

dziecka:

fs = require('fs') 

# parent opens the file descriptor 3 when spawning the child (and closes it when the child returns) 
fd3write = (s) -> 
    b = new Buffer(s) 
    fs.writeSync(3,b,0,b.length) 

process.stdin.on 'data', (data) -> 
    fd3write "p3 #{process.pid} - #{data}\n" 
    process.stdout.write "so #{process.pid} - #{data}\n", 'utf8' 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

Mam nadzieję, że będzie to pomocne dla kogoś innego.

Aby użyć potoku zamiast stdin do wysyłania wiadomości od rodzica do dziecka, ten link może być przydatny: child-process-multiple-file-descriptors.

+0

Możesz także oznaczać własne odpowiedzi jako zaakceptowane. :) – jgillich

Powiązane problemy