2016-10-18 25 views
1

嗨我正在使用child_process.spwan啓動在Windows上運行python腳本的子進程。該腳本在SIGINT上進行偵聽以優雅地退出。但Windows不支持信號,並且所有節點都在模擬。因此,Windows上的child_process.kill('SIGINT')實際上是無條件地終止進程(沒有正常退出,未調用python的SIGTERM/SIGINT處理程序)。也寫一個ctrl+c字符到標準輸入也不起作用。Nodejs:發送Ctrl + C到Windows上的子進程

當我查看Python API時,我得到了可以滿足需求的CTRL_BREAK_EVENT和CTRL_C_EVENT。我想知道節點是否具有與此類似的特定於平臺的API?

相關職位,但沒有工作的人: How to send control C node.js and child_processes sending crtl+c to a node.js spawned childprocess using stdin.write()?

回答

1

您可以使用IPC消息來通知孩子,其時間停下來正常終止。以下方法使用process.on('message')來偵聽來自父進程的子進程的消息,以從父進程發送消息給子進程。

下面的代碼有一個1分鐘的超時設置爲退出,如果孩子掛起或需要很長時間才能完成。

PY-腳本wrapper.js

// Handle messages sent from the Parent 
process.on('message', (msg) => { 
    if (msg.action === 'STOP') { 
    // Execute Graceful Termination code 
    process.exit(0); // Exit Process with no Errors 
    } 
}); 

父進程

const cp = require('child_process'); 
const py = cp.fork('./py-script-wrapper.js'); 

// On 'SIGINT' 
process.on('SIGINT',() => { 
    // Send a message to the python script 
    py.send({ action: 'STOP' }); 

    // Now that the child process has gracefully terminated 
    // exit parent process without error 
    py.on('exit', (code, signal) => { 
    process.exit(0); 
    }); 

    // If the child took too long to exit 
    // Kill the child, and exit with a failure code 
    setTimeout(60000,() => { 
    py.kill(); 
    process.exit(1); 
    }); 

}); 
+1

感謝。這當然是有效的,當孩子是一個節點進程。但是,如果最終我需要產生一個Python進程(例如'spawn('python',['myscript.py')'),它擁有一些資源(例如套接字),但根本不會說Javascript。我以跨平臺的方式處理python proc? – kenmark

0

你可以通過標準輸入發送一個 '退出' 命令時Pyhthon過程中,爲我工作。在Python中,您需要創建一個使用input從stdin讀取的線程,一旦返回,就設置一個事件標誌。在您的主應用程序循環中,您會定期檢查事件是否已設置並退出程序。

Python應用程序(script.py):

import threading 
import sys 

def quit_watch(event): 
    input("Type enter to quit") 
    event.set() 

def main(): 
    stop = threading.Event() 
    threading.Thread(target=quit_watch, args=[stop]).start() 

    while True: 
     # do work, regularly check if stop is set 
     if stop.wait(1): 
      print("Stopping application loop") 
      break 

if __name__ == '__main__': 
    main() 
    sys.exit(0) 

的Node.js應用:

child_process = require('child_process') 
child = child_process.spawn('python.exe', ['script.py']) 
// check if process is still running 
assert(child.kill(0) == true) 
// to terminate gracefully, write newline to stdin 
child.stdin.write('\n') 
// check if process terminated itself 
assert(child.kill(0) == false)