Understanding Linux Signals - SIGTERM vs SIGKILL

Understanding Linux Signals - SIGTERM vs SIGKILL

What You'll Learn

  • The difference and proper use of SIGTERM, SIGKILL, and SIGHUP
  • A grounded answer to "should I just use kill -9?"
  • A clear way to diagnose why a process "won't die" or "won't reload its config"

Quick Summary

  • Try kill (= SIGTERM) first to stop the process gracefully
  • If it doesn't respond, use kill -KILL (= SIGKILL) to force it
  • Don't reach for kill -9 reflexively — it's the last resort that skips cleanup

What Is a Signal?

Conclusion: A signal is an asynchronous notification the kernel sends to a process, telling it to terminate, stop, reload, and so on.

A signal is an asynchronous software interrupt sent to a process, usually by the kernel. It carries a short message — "please terminate", "please stop" — encoded as a number, and is one of the lightest forms of inter-process communication (IPC).

Signals arrive through three main paths.

  • Keyboard: Ctrl+CSIGINT, Ctrl+ZSIGTSTP
  • kill / pkill commands: send any signal to any process
  • Kernel / other processes: SIGKILL on memory pressure (OOM Killer), SIGSEGV on an invalid memory access

List the available signals with kill -l.

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
...

Signal numbers are not all fixed. The low ones — SIGHUP(1), SIGINT(2), SIGKILL(9), SIGTERM(15) — are stable, but others like SIGUSR1 vary by architecture. In scripts, prefer the name (-TERM, -KILL) over the number.

What Is SIGTERM, and Why Is It the Default?

Conclusion: SIGTERM (15) politely asks a process to exit. The process can catch it, clean up (save files, close connections), then quit. It's the default for kill.

SIGTERM (number 15) is the signal kill sends when you don't specify one.

# These two are equivalent
$ kill 12345
$ kill -TERM 12345

The key property of SIGTERM is that a process can catch it. Before exiting, the process can perform cleanup:

  • Save files being edited
  • Close database connections and sockets
  • Delete temporary files
  • Notify child processes to shut down

This is a graceful shutdown, and it's exactly why systemd sends SIGTERM first when stopping a service.

When stopping data-handling processes (databases, editors, app servers), always try SIGTERM first. Force-killing immediately risks data corruption.

What Is SIGKILL, and How Does It Differ from SIGTERM?

Conclusion: SIGKILL (9) makes the kernel destroy a process instantly. It cannot be caught, ignored, or blocked, and no cleanup runs — a true last resort.

SIGKILL (number 9) is the force kill behind the familiar kill -9. The decisive difference from SIGTERM comes down to one point.

That means kill -9 carries side effects:

  • Unsaved data is lost
  • Open files and sockets are not closed cleanly
  • Temporary and lock files are left behind
  • Child processes become orphans

The OS reclaims some of this, but application-level consistency is not guaranteed.

Aspect SIGTERM (15) SIGKILL (9)
Catchable? Yes No
Cleanup runs? Yes No
Data saved? Likely No
When to use Normal stop When TERM fails

Avoid starting with kill -9. "It won't stop, so just use -9" tends to hide the real cause (deadlock, I/O wait) while throwing away data. Stick to the order: SIGTERM first, wait a few seconds, then SIGKILL if needed.

What Is SIGHUP, and Its Use Beyond Termination

Conclusion: SIGHUP (1) originally meant "the terminal hung up," but daemons reuse it by convention as a "reload your config file" trigger.

SIGHUP (number 1, "hang up") was originally sent when the controlling terminal was disconnected. Close a terminal, and processes started there receive SIGHUP and, by default, terminate. The nohup command exists precisely to ignore SIGHUP and keep running.

Separately, many daemons interpret SIGHUP their own way: as a signal to reload the configuration file without restarting.

# Tell nginx to reload its config (without stopping the process)
$ kill -HUP $(cat /var/run/nginx.pid)

This "reload" behavior is not part of the signal spec — it's a convention each daemon implements. Behavior varies per program, so always check the official docs for how it handles SIGHUP.

SIGINT, SIGSTOP, and Other Key Signals

Conclusion: The everyday signals are SIGINT (Ctrl+C) and SIGTSTP (Ctrl+Z). SIGSTOP / SIGCONT are uncatchable and pause/resume a process.

Know the signals you'll hit most often in a terminal.

  • SIGINT (2): Ctrl+C. "Interrupt." Terminates by default but is catchable (this is why many CLIs show a confirmation prompt).
  • SIGTSTP (20): Ctrl+Z. Suspends the foreground job; resume with fg / bg.
  • SIGSTOP (19) / SIGCONT (18): Pause and resume a process. Like SIGKILL, SIGSTOP is uncatchable.
  • SIGQUIT (3): Ctrl+\. Terminate plus a core dump.

Handling jobs suspended with Ctrl+Z is covered in detail in Job Control Basics.

Sending Signals in Practice: kill / pkill / killall

Conclusion: Use kill for a PID, pkill / killall for a name. To avoid mistakes, confirm the targets with pgrep before sending.

There are three common commands for sending signals.

# Send to a specific PID (the basic form)
$ kill -TERM 12345

# Send by process name (partial match)
$ pkill -TERM nginx

# Send by process name (exact match, killall)
$ killall -TERM nginx

pkill / killall send to every matching process. To avoid catching unintended processes, always confirm the targets with pgrep -a <name> first.

$ pgrep -a nginx

To express "TERM first, then KILL" in one line, insert a wait in between.

$ kill -TERM 12345; sleep 5; kill -KILL 12345 2>/dev/null

Summary: Signal Cheat Sheet

Conclusion: SIGTERM for a graceful stop, SIGKILL as the last resort, SIGHUP to reload config. Specify by name, not number, and keep force-kill for last.

Goal Signal Example
Stop normally SIGTERM kill <PID>
It just won't stop SIGKILL kill -KILL <PID>
Reload config SIGHUP kill -HUP <PID>
Pause / resume SIGSTOP / SIGCONT kill -STOP / -CONT

Next Reading