Nodejs:将 Ctrl+C 发送到 Windows 上的子进程

Posted

技术标签:

【中文标题】Nodejs:将 Ctrl+C 发送到 Windows 上的子进程【英文标题】:Nodejs: Send Ctrl+C to a child process on Windows 【发布时间】:2016-10-18 20:33:21 【问题描述】:

您好,我正在使用 child_process.spwan 来启动在 Windows 上运行 python 脚本的子进程。该脚本侦听 SIGINT 以优雅地退出。但是 Windows 不支持信号,所有节点都在模拟。所以 Windows 上的child_process.kill('SIGINT') 实际上是无条件地终止进程(没有优雅退出,python 的 SIGTERM/SIGINT 处理程序没有被调用)。将ctrl+c 字符写入标准输入也不起作用。

当我研究 Python API 时,我得到了可以满足需求的 CTRL_BREAK_EVENT 和 CTRL_C_EVENT。我想知道 node 是否有类似的等价的特定于平台的 API?

相关帖子但无效的帖子: How to send control C node.js and child_processes sending crtl+c to a node.js spawned childprocess using stdin.write()?

【问题讨论】:

这里据说不可能:***.com/a/41976985/2604492 【参考方案1】:

您可以使用 IPC 消息向孩子发出信号,表明该停止并正常终止。以下方法使用process.on('message') 在子进程中侦听来自父进程的消息,并使用child_process.send() 从父进程向子进程发送消息。

如果孩子挂起或需要很长时间才能完成,下面的代码设置了 1 分钟的超时退出。

py-script-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);
  );

);

【讨论】:

谢谢。当子进程是节点进程时,这肯定有效。但是,如果最终我需要生成一个 Python 进程(例如,spawn('python', ['myscript.py']),它拥有一些资源(例如,套接字)但根本不会说 javascript,该怎么办。如何以跨平台的方式对 python proc 进行 IPC?【参考方案2】:

您可以通过标准输入向 Pyhthon 进程发送一个“退出”命令,这对我有用。在 Python 中,您需要创建一个使用 input 从标准输入读取的线程,一旦返回,您就设置一个事件标志。在您的主应用程序循环中,您会定期检查事件是否已设置并退出程序。

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)

【讨论】:

以上是关于Nodejs:将 Ctrl+C 发送到 Windows 上的子进程的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ctrl+c 发送到 c# 中的进程?

使用 stdin.write() 将 ctrl+c 发送到 node.js 生成子进程?

将 Ctrl+C 事件发送到在 Windows 上使用 QProcess 启动的进程

Nodejs 信号

如何将 control + L 和 control + C 发送到另一个应用程序?

如何在nodejs中使用nodemailer进行批量数据发送?