在 node.js 中,process.on (‘ SIGINT’)在 Windows 中的等价物是什么?

我遵循 给你(监听 SIGINT事件)的指导,在响应 Ctrl + C或服务器关闭时,优雅地关闭我的 Windows-8托管的 node.js 应用程序。

但是 Windows 没有 SIGINT,我也试过 process.on('exit'),但是那似乎太晚了,不能做任何有效的事情。

在 Windows 上,这段代码给我的是: 错误: 没有这样的模块

process.on( 'SIGINT', function() {
console.log( "\ngracefully shutting down from  SIGINT (Crtl-C)" )
// wish this worked on Windows
process.exit( )
})

在 Windows 上,这段代码运行,但是是 做任何优雅的事情都太晚了:

process.on( 'exit', function() {
console.log( "never see this log message" )
})

在 Windows 上是否有 SIGINT等效事件?

37830 次浏览

Currently there is still no support in node for capturing the windows console control events, so there are no equivalents to the POSIX signals:

https://github.com/joyent/node/issues/1553

However the tty module documentation does give an example of a mechanism to capture the key presses in order to initiate a graceful shutdown, but then this does only work for ctrl+c.

var tty = require('tty');


process.stdin.resume();
tty.setRawMode(true);


process.stdin.on('keypress', function(char, key) {
if (key && key.ctrl && key.name == 'c') {
console.log('graceful exit of process %d', process.pid);
process.exit();
}
});

Since node.js 0.8 the keypress event no longer exists. There is however an npm package called keypress that reimplements the event.

Install with npm install keypress, then do something like:

// Windows doesn't use POSIX signals
if (process.platform === "win32") {
const keypress = require("keypress");
keypress(process.stdin);
process.stdin.resume();
process.stdin.setRawMode(true);
process.stdin.setEncoding("utf8");
process.stdin.on("keypress", function(char, key) {
if (key && key.ctrl && key.name == "c") {
// Behave like a SIGUSR2
process.emit("SIGUSR2");
} else if (key && key.ctrl && key.name == "r") {
// Behave like a SIGHUP
process.emit("SIGHUP");
}
});
}

You have to use the readline module and listen for a SIGINT event:

http://nodejs.org/api/readline.html#readline_event_sigint

if (process.platform === "win32") {
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});


rl.on("SIGINT", function () {
process.emit("SIGINT");
});
}


process.on("SIGINT", function () {
//graceful shutdown
process.exit();
});

Unless you need the "readline" import for other tasks, I would suggest importing "readline" once the program has verified that it's running on Windows. Additionally, for those who might be unaware - this works on both Windows 32-bit and Windows 64-bit systems (which will return the keyword "win32"). Thanks for this solution Gabriel.

if (process.platform === 'win32') {
require('readline')
.createInterface({
input: process.stdin,
output: process.stdout
})
.on('SIGINT', function () {
process.emit('SIGINT');
});
}


process.on('SIGINT', function () {
// graceful shutdown
process.exit();
});

I'm not sure as of when, but on node 8.x and on Windows 10 the original question code simply works now.

process.on( "SIGINT", function() {
console.log( "\ngracefully shutting down from SIGINT (Crtl-C)" );
process.exit();
} );


process.on( "exit", function() {
console.log( "never see this log message" );
} );


setInterval( () => console.log( "tick" ), 2500 );

enter image description here

also works with a windows command prompt.

Nowadays it just works on all platforms, including Windows.

The following code logs and then terminates properly on Windows 10:

process.on('SIGINT', () => {
console.log("Terminating...");
process.exit(0);
});

Nothing above worked for me, so workaround has been to have a readline hanging and catch the signal from there.

Here my solution:

const readline = require('readline');


const rl = readline.createInterface({ input: process.stdin, output: process.stdout });


// Flag to be able to force the shutdown
let isShuttingDown = false;


// https://nodejs.org/api/readline.html
rl.on('SIGINT', async () => {
if (isShuttingDown) {
logger.info("Forcing shutdown, bye.");
process.exit();
} else {
if (!<yourIsCleanupNecessaryCheck>()) {
logger.info("No cleanup necessary, bye.");
process.exit();
} else {
logger.info("Closing all opened pages in three seconds (press Ctrl+C again to quit immediately and keep the pages opened) ...");
isShuttingDown = true;
await sleep(3000);
await <yourCleanupLogic>();
logger.info("All pages closed, bye.");
process.exit();
}
}


function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

It's quite vanilla, it's asynchronous, and it works both on MacOS 11.3 and Windows 10 (at the time of writing).

Windows + Git Bash/Cygwin solution:

None of the other solutions for Windows and Git Bash worked, so my solution was to simply use WINPTY as follows to launch Node:

My package.json has this start script:

"start": "winpty node app.js"

This was inspired by the accepted answer here for similar Python issue:

python error Suppressing signal 18 to win32

Note: WINPTY runs on Windows XP and beyond.