Mastering Node.js(Second Edition)
上QQ阅读APP看书,第一时间看更新

Signals

Evented programming is like hardware interrupt programming. Interrupts do exactly what their name suggests. They use their ability to interrupt whatever a controller, or the CPU, or any other device is doing, demanding that their particular need be serviced immediately.

In fact, the Node process object exposes standard Portable Operating System Interface (POSIX) signal names, such that a Node process can subscribe to these system events.

As http://en.wikipedia.org/wiki/POSIX_signal defines, "A signal is a limited form of inter-process communication used in Unix, Unix-like, and other POSIX-compliant operating systems. It is an asynchronous notification sent to a process, or to a specific thread, within the same process in order to notify it of an event that occurred."

This is a very elegant and natural way to expose a Node process to operating system signal events. One might configure listeners to catch signals instructing a Node process to restart or update some configuration files, or simply clean up and shut down.

For example, the SIGINT signal is sent to a process when its controlling terminal detects a Ctrl + C (or equivalent) keystroke. This signal tells a process that an interrupt has been requested. If a Node process has bound a callback to this event, that function might log the request prior to terminating, do some other cleanup work, or even ignore the request:

// sigint.js
console.log("Running...");

// After 16 minutes, do nothing
setInterval(() => {}, 1e6); // Keeps Node running the process

// Subscribe to SIGINT, so some of our code runs when Node gets that signal
process.on("SIGINT", () => {
console.log("We received the SIGINT signal!");
process.exit(1);
});

The following is the output for sigint.js:

$ node sigint.js
Running...
(then press Ctrl+C)
We received the SIGINT signal!

This example starts a long interval, so Node doesn't exit with nothing else to do. When you send a Ctrl + C from your keyboard through the terminal controlling the process, Node gets the signal from the operating system. Your code has subscribed to that event, and Node runs your function.

Now, consider a situation in which a Node process is doing some ongoing work, such as parsing logs. It might be useful to be able to send that process a signal, such as update your configuration files, or restart the scan. You may want to send such signals from the command line. You might prefer to have another process do so — a practice known as Inter-Process Communication (IPC).

Create a file named ipc.js, and type in the following code:

// ipc.js
setInterval(() => {}, 1e6);
process.on("SIGUSR1", () => {
console.log("Got a signal!");
});

Run the following command:

$ node ipc.js

As before, Node will wait for around 16 minutes before running the empty function, keeping the process open, so you'll have to Ctrl C to get your prompt back. Note that this works just fine even though here, we haven't subscribed to the SIGINT signal.

SIGUSR1 (and SIGUSR2) are user-defined signals, triggered by no specific action known to the operating system. They're meant for custom functionality.

To send a command to a process, you must determine its process ID. With a PID in hand, you can address a process and communicate with it. If the PID assigned to ipc.js after being run through Node is 123, then we can send that process a SIGUSR1 signal using the kill command:

$ kill –s SIGUSR1 123

A simple way to find the PID for a given Node process in UNIX is to search the system process list for the name of the program that says the process is running. If ipc.js is currently executing, its PID is found by entering the following command line in the console/terminal:
ps aux | grep ipc.js. Try it.