2017-06-23 76 views
1

如何管理已分叉的多個併發子進程?管理多個節點子進程

在此示例中,可以多次調用start_child(),並且每個調用都可以無限期地運行。當像這樣分配任意數量的子進程時,如何與每個子進程通信/處理?假設我有3個分叉的子進程正在運行,並且它們會一直運行,但我想要殺死(或發送消息)到子進程號2.我該怎麼做?

如果調用stop_child(),它會殺死所有當前正在運行的子進程。如何重構此代碼,以便我可以在個別子進程上調用stop_child()

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function() { 
     start_child(); 
    }); 

    socket.on('stop_child', function() { 
     child.kill(); 
    } 
} 

function start_child() { 
    child = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

UPDATE

我想這一點,基於一些評論。但是,如果我啓動3個進程然後調用,例如,child[0].kill(),則會出現錯誤:Cannot read property 'kill' of undefined。我猜我的問題是,我沒有正確地傳遞i變量的io.on()電話:

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 
let i  = 0; 
let child = []; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function (i) { 
     start_child(i++); 
    }); 

    //this is hard coded just for testing 
    socket.on('stop_child', function() { 
     child[0].kill(); 
    } 
} 

function start_child(i) { 
    child[i] = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

更新#2

好吧,我想通了,我需要從客戶端發送增量變量,通過來自emit調用的對象。現在,當我撥打child[0].kill()時,沒有錯誤。問題是,子進程沒有中止:

server.js

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function (count) { 
     let num = count.count; 
     start_child(num); 
    }); 

    //this is hard coded just for testing 
    socket.on('stop_child', function (count) { 
     let num = count.count; 
     child[num].kill(); 
    } 
} 

function start_child(num) { 
    child[num] = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

的index.html

$(function() { 
    let socket = io(); 
    let i  = 0; 

    $('#start').on('click', function() { 
     socket.emit('start_child', {"count": i++}); 
    }); 

    $('#stop').on('click', function() { 
     //the count is hard coded here just for testing purposes 
     socket.emit('stop_child', {"count": 0}); 
    }); 
}); 

最後更新 - 分辨率

分辨率#2(正上方)實際上是解決方案。我之後遇到的問題(其中child.kill()調用似乎沒有做任何事情)是由我遺漏的一段代碼引起的(在代碼註釋中:'條件邏輯再次運行start_child()或讓它結束')。

這是什麼在那裏:

if (condition) { 
    setTimeout(start_child, 5000); 
} else { 
    console.log('this child process has ended'); 
} 

而這就是我改成了(基本上,我不得不遞增變量傳遞給start_child()功能,使得它會在同一個地方所述child陣列時,它重新啓動):

if (condition) { 
    setTimeout(function() { 
     start_child(num) 
    }, 5000); 
} else { 
    console.log('this child process has ended'); 
} 
+0

什麼操作系統是服務器上運行的,什麼是你的child_script做。它在'child.kill()'doc的文檔中說過:***請注意,雖然函數被稱爲kill,但傳遞給子進程的信號可能不會真正終止進程。***您還應該記錄' child.on('error',...)'如果傳遞kill消息時發生錯誤。 – jfriend00

+0

目前,它運行在Windows上的Cygwin環境中。 – CJG

回答

1

fork()返回其具有對象與該進程間通信上的方法和事件子進程對象。因此,您必須在調用start_child()時保存每個ChildProcess對象,然後使用適當的對象與其他進程通信。

你可以看到事件和子進程對象here的方法。還有很多代碼示例。

+0

我明白'fork()'返回一個ChildProcess對象,並且我已經閱讀了文檔。我只是不清楚如何解決特定的子對象(當多個孩子被分叉時),或者我需要重構示例代碼才能實現這一點。 – CJG

+0

@CJG - 很難理解問題所在。如果你打開5個子進程,你可以將它們保存在一個數組中。要與第一個進行通信,您需要從數組的第一個元素獲取ChildProcess對象,並使用該特定的「ChildProcess」對象與該特定的子進行通信。 – jfriend00

+0

@CJG - 您是否試圖從父母向特定孩子或從特定孩子向另一個特定孩子發送消息? – jfriend00

0

爲了發送消息,子進程,使用下面的示例:

parent.js

**

const { fork } = require('child_process'); 
const forked = fork('child.js'); 
forked.on('message', (msg) => { 
    console.log('Message from child', msg); 
}); 
forked.send({ hello: 'world' }); 

**

child.js

process.on('message', (msg) => { 
    console.log('Message from parent:', msg); 
}); 

let counter = 0; 

setInterval(() => { 
    process.send({ counter: counter++ }); 
}, 1000); 

欲瞭解更多信息,請參閱這篇文章:

https://medium.freecodecamp.com/node-js-child-processes-everything-you-need-to-know-e69498fe970a

+0

我知道如何在父母和孩子之間來回發送消息。我不知道的是當家長有多個孩子時,如何向特定的孩子發送消息。 – CJG

+0

您需要在父級側記住子節點,比如將子對象存儲在數組中,然後調用適當的子對象方法 – ramasCoder

+0

您能給我一個簡單的例子嗎?我需要能夠在特定的孩子上調用'kill()'。由於當前編寫的代碼,如果我調用'child.kill()',那麼所有的子進程都會被終止。我得到每個子節點都必須在父節點上記住;我只是不太清楚如何使用這段代碼來做到這一點。 – CJG