intermediate20 min

Processes, Signals, and Permissions

Inspecting and stopping running programs, the difference between asking a process to stop and forcing it, and the rwx permission model that governs who can do what to a file.

What you'll learn

  • Inspect running processes and identify one by its PID
  • Explain the precise difference between SIGTERM and SIGKILL, and why that difference matters
  • Read and reason about a file's rwx permission bits for owner, group, and others

Prerequisites

Explanation

Every real command below runs only in your own terminal — this lesson's exercises model process/permission logic as data, never executing anything.

Every running program is a process with a unique PID (process ID). ps aux lists running processes; ps aux | grep node (this course's earlier pipe/grep lessons, applied together) narrows that down to processes matching "node." kill sends a signal to a process by PID — and precisely which signal matters enormously, which is why "kill" as a name is honestly a bit misleading: by default, kill <PID> sends SIGTERM (signal 15), a request that the process terminate gracefully, which a well-behaved program can catch and respond to — finishing an in-flight write, closing a database connection cleanly, releasing a lock — before actually exiting. kill -9 <PID> (or kill -SIGKILL) sends SIGKILL, which the operating system enforces immediately and unconditionally — the target process cannot catch it, cannot clean up, cannot do anything at all in response; it's simply terminated by the kernel on the spot.

This distinction is genuinely important, not a minor technicality: SIGTERM first, reserving SIGKILL only for a process that's genuinely unresponsive and not terminating after a reasonable wait, is the correct, standard practice specifically because SIGKILL gives a process zero opportunity to clean up — a database process killed with SIGKILL mid-write can leave real data in a corrupted or inconsistent state that a graceful SIGTERM-triggered shutdown would have avoided entirely.

Every file has permission bits for three distinct categories — owner (the specific user who owns the file), group (a set of users), and others (everyone else) — each with independent r (read), w (write), and x (execute) bits. ls -la shows this as a 10-character string like -rwxr-xr--: the first character indicates file type (- for a regular file, d for a directory), then three groups of rwx for owner/group/others respectively — -rwxr-xr-- means the owner can read/write/execute, the group can read/execute (not write), and others can only read. chmod changes these bits, either symbolically (chmod u+x file adds execute for the owner/"user") or numerically (chmod 755 file, where each digit is a sum: read=4, write=2, execute=1, so 7 = 4+2+1 = all three, 5 = 4+1 = read+execute only) — both forms are genuinely common in real use, and understanding the numeric sum makes an unfamiliar chmod 644 or chmod 700 immediately readable rather than a number to memorize by rote.

Example

Modeling the SIGTERM-vs-SIGKILL distinction and rwx permission-bit decoding, as pure data -- no real process or file is affected.

function sendSignal(processCanRespond, signal) {
  if (signal === "SIGKILL") {
    return "process terminated immediately by the kernel -- NO cleanup possible, regardless of processCanRespond";
  }
  if (signal === "SIGTERM") {
    return processCanRespond
      ? "process received the request and is cleaning up before exiting"
      : "process ignored/couldn't handle SIGTERM -- still running; SIGKILL may be needed next";
  }
  return "unrecognized signal";
}
console.log(sendSignal(true, "SIGTERM"));  // graceful cleanup happens
console.log(sendSignal(true, "SIGKILL"));  // no cleanup at all, regardless -- SIGKILL cannot be caught

function decodePermissionDigit(digit) {
  return {
    read: (digit & 4) !== 0,
    write: (digit & 2) !== 0,
    execute: (digit & 1) !== 0,
  };
}
console.log(decodePermissionDigit(7)); // { read: true, write: true, execute: true } -- rwx
console.log(decodePermissionDigit(5)); // { read: true, write: false, execute: true } -- r-x

Try it yourself

Call decodePermissionDigit(4) and confirm it correctly represents read-only permission (r--).

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

This models permission-digit decoding only -- no real file is affected. Write decodePermissionDigit(digit) returning {read, write, execute} booleans using the standard 4/2/1 bit values (digit is 0-7).

Checks: decodes 7 to full read/write/execute · decodes 4 to read-only · decodes 0 to no permissions

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

This models the SIGTERM-vs-SIGKILL decision only -- no real process is affected. Write chooseSignal(processResponsive, alreadyTriedGraceful) returning 'SIGTERM' if !alreadyTriedGraceful (always try graceful first), or 'SIGKILL' if alreadyTriedGraceful is true AND processResponsive is false (unresponsive after a genuine attempt), or 'wait' if alreadyTriedGraceful is true but processResponsive is still true (give it more time).

Checks: always tries SIGTERM first · escalates to SIGKILL only after a genuine, unresponsive graceful attempt · waits rather than force-killing a still-responsive process

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Reaching for `kill -9` (SIGKILL) as a default, first response to a stuck process -- this gives the process zero opportunity to clean up, which can leave real, in-progress work (a database write, a lock, a temp file) in a corrupted or inconsistent state; SIGTERM first is the correct default.
  • Assuming a process will always respond correctly to SIGTERM -- a genuinely hung or misbehaving process might not, which is exactly the specific, narrow situation SIGKILL is actually for, not a general first choice.
  • Misreading a permission string like `-rwxr-xr--` by not tracking which three-character group belongs to owner/group/others -- the order is always owner, then group, then others, in that fixed sequence.

Knowledge check

Knowledge check

1. What is the precise difference between sending SIGTERM and SIGKILL to a process?
2. Why is SIGTERM the correct first choice when stopping a process, reserving SIGKILL for genuine unresponsiveness?
3. In the permission string `-rwxr-xr--`, what does the middle three-character group (r-x) represent?

Takeaway

SIGTERM is a request a process can catch and gracefully respond to; SIGKILL is immediate, uncatchable, and gives zero opportunity for cleanup — try SIGTERM first, reserving SIGKILL for genuine unresponsiveness; and a file's rwx permissions are tracked independently for owner, group, and others, in that fixed order.

Summary

ps inspects running processes by PID. kill sends a signal — SIGTERM (default) requests graceful termination a process can catch; SIGKILL (-9) is enforced immediately with no chance to clean up. File permissions (rwx for owner/group/others, as shown by ls -la or a numeric chmod mode like 755) control who can read, write, or execute a file.

References

Your notes

Notes save automatically.