信号是操作信息提供了进程间通信机制。信号通常是一个数字,同时也可以使用一个字符串来标识。比如 SIGKILL 标识数字 9。不同的操作系统对信号的定义不同。下面表格里罗列的是基本通用的信号定义。
名称 数字 是否可处理 NodeJS 默认行为 信号的含义SIGHUP 1 Yes 退出 父命令行被关闭
SIGINT 2 Yes 退出 命令行尝试中断,即 Ctrl + C
SIGQUIT 3 Yes 退出 命令行尝试退出,即 Ctrl + Z
SIGKILL 9 No 退出 强制进程退出
SIGUSR1 10 Yes 启动调试器 用户自定义信号
SIGUSR2 12 Yes 退出 用户自定义信号
SIGTERM 15 Yes 退出 进程优雅的退出
SIGSTOP 19 No 退出 进程被强制停止
这表格里,是否可处理表示这个信号是否可被进程接收并被处理。NodeJS 默认行为表示进程在接收到这个信号以后默认执行的动作。
我们可以通过如下方式来监听这些信号。
#!/usr/bin/env node console.log(`Process ID: ${process.pid}`); process.on("SIGHUP", () => console.log("Received: SIGHUP")); process.on("SIGINT", () => console.log("Received: SIGINT")); setTimeout(() => {}, 5 * 60 * 1000); // keep process alive在一个命令行窗口中运行这段代码,然后按下 Ctrl + C,此时进程不会退出,而是会在控制台打印一行接收到了 SIGINT 信号的日志信息。新起一个命令行窗口,执行如下命令,PROCESS_ID 为上面程序输出的进程 ID。
kill -s SIGHUP <PROCESS_ID>通过新起的命令行,我们向原来的那个程序进程发送了一个 SIGHUP 信号,原来的命令行窗口中会打印一行接收到了 SIGHUP 信号的日志信息。
在 NodeJS 代码中,进程也可以给其他进程发送信号。比如:
node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"这段代码同样会在第一个命令行窗口中输出一行接收到了 SIGHUP 信号的日志。
如果我们要让第一个命令行窗口的进程退出,则可以通过下面的命令来实现。
kill -9 <PROCESS_ID>在 NodeJS 中,信号通常被用作控制进程优雅的退出。比如,在 Kubernetes 中,当一个 pod 要退出时,k8s 会像 pod 内的进程发送一个 SIGTERM 的信号,同时启动一个 30 秒的定时器。应用程序有 30 秒的时间来关闭连接、保存数据等。如果 30 秒之后进程依然存活,k8s 会再发送一个 SIGKILL 来强制关闭进程。