‘SIGTERM’ and ‘SIGINT’ have default handlers on non-Windows platforms that reset the terminal mode before exiting with code 128 + signal number. If one of these signals has a listener installed, its default behavior will be removed (Node.js will no longer exit).
这句话写的很抽象,它是什么意思呢?我们以一个简单的 Node 应用为例。
新建文件,键入如下代码,将其保存为 server.js:
const http = require('http');const server = http.createServer((req, res) => {
setTimeout(() => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('It works');
}, 5000);
});
server.listen(9420);
这里为了方便测试,对应用接收到的每个 http 请求,等待 5 秒后再进行响应。
执行
node server.js 启动应用。为了给应用发送信号,我们需要获取应用的进程 ID,我们可以使用 lsof 命令查看:
$ lsof -i TCP:9420
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 70826 myunlessor 13u IPv6 0xd250033eef8912eb 0t0 TCP *:9420 (LISTEN)事实上,我们也可以在代码里通过 console.log(process.pid) 获取进程 ID。这里只是顺便介绍一种,在知道监听 TCP 端口的情况获取进程的方式。
随后,我们发起一个请求,在收到响应之前(有 5 秒等待时间),我们给应用发送 SIGINT 信号。
$ curl http://localhost:9420 &$ kill -INT 70826
curl: (52) Empty reply from server
[1]+ Exit 52 curl http://localhost:9420
可以看到,请求没能正常收到响应。也就是说,默认情况下,Node 应用在接收到 SIGINT 信号时,会马上把进程杀死,无视进程还没处理完成的请求。所幸的是,我们可以手动监听进程的 SIGINT 事件,像这样:
process.on('SIGINT', () => {
// do something here
});
如果我们在事件回调里什么都不做,就意味着忽略该信号,进程该干嘛干嘛,像什么事情都没发生一样。
那么,如果我手动监听 SIGKILL 会如何呢?对不起,SIGKILL 是不能被监听的,官方文档如是说:
‘SIGKILL’ cannot have a listener installed, it will unconditionally terminate Node.js on all platforms.
这是合情合理的,要知道 SIGKILL 是用于强杀进程的,你无法干预它的行为。
回到上面的问题,我们可以近似地理解为 Node 应用响应 SIGINT 事件的默认回调是这样子的:
process.on('SIGINT', () => {
process.exit(128 + 2/* signal number */);









