🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Linux Process Signals Explained Simply (SIGTERM, SIGKILL, SIGHUP)

Learn Linux process signals every DevOps engineer must know: SIGTERM, SIGKILL, SIGHUP, SIGINT. How kill and pkill work, why Kubernetes uses SIGTERM, and how to handle signals in your app.

DevOpsBoys4 min read
Share:Tweet

When a Kubernetes pod is terminated, when you press Ctrl+C in a terminal, or when nginx reloads its config without restarting — signals are what's happening under the hood. If you're running production workloads and don't understand signals, you're flying blind.

Here's everything you need to know.

What Is a Signal?

A signal is a software interrupt — a way for the OS (or another process) to notify a running process that something happened. The process can choose to handle the signal, ignore it, or let the default behavior take over.

Think of it like knocking on a door vs kicking it down. SIGTERM is a polite knock ("please shut down"). SIGKILL is kicking the door down — no choice.

The Signals You'll Use Daily

SIGTERM (signal 15) — Graceful Shutdown

The standard "please stop" signal. When the kernel or a user sends SIGTERM, the process receives it and can:

  • Finish processing the current request
  • Flush writes to disk
  • Close database connections
  • Remove lock files
  • Then exit cleanly
bash
kill 1234        # sends SIGTERM to PID 1234 (default)
kill -15 1234    # same thing, explicit
kill -TERM 1234  # same thing, by name

This is what you should always try first. Most well-written services handle it.

SIGKILL (signal 9) — Force Kill

SIGKILL cannot be caught, blocked, or ignored by the process. The kernel forcefully terminates it immediately. No cleanup, no flush, no graceful anything.

bash
kill -9 1234      # sends SIGKILL
kill -KILL 1234   # same

Use SIGKILL only when the process is frozen, stuck in a loop, or ignoring SIGTERM. Using -9 as a default (which many beginners do) is bad practice — it can corrupt data, leave stale lock files, and break things downstream.

SIGHUP (signal 1) — Reload Config

Originally meant "the terminal disconnected." Modern daemons repurpose it to mean "reload your configuration file without restarting."

bash
kill -HUP $(cat /var/run/nginx.pid)
# or
pkill -HUP nginx

After receiving SIGHUP, nginx re-reads nginx.conf and applies changes without dropping connections. Same for sshd, rsyslog, and most system daemons.

SIGINT (signal 2) — Keyboard Interrupt

This is what Ctrl+C sends to the foreground process. Most programs handle it like SIGTERM — they clean up and exit. Some scripts don't handle it and just die.

bash
# In a script, trap SIGINT to clean up:
trap 'echo "Interrupted, cleaning up..."; rm -f /tmp/mylock; exit 1' INT

SIGUSR1 / SIGUSR2 (signals 10 and 12) — Custom Use

These have no predefined meaning. Application developers use them for custom behavior:

  • SIGUSR1 to nginx: reopen log files (useful after log rotation)
  • SIGUSR1 to some Go apps: print goroutine dump
  • SIGUSR2 to some apps: toggle debug logging
bash
kill -USR1 $(pgrep nginx)

SIGPIPE (signal 13) — Broken Pipe

Sent when a process tries to write to a pipe whose read end is closed. Common cause of "Broken pipe" errors in shell scripts. Usually indicates the consumer closed before the producer finished.

kill vs pkill vs killall

bash
# kill: by PID
kill -TERM 1234
 
# pkill: by process name (partial match)
pkill -TERM nginx        # sends SIGTERM to all nginx processes
pkill -9 zombie-process  # force kill by name
 
# killall: by exact process name
killall -HUP nginx
 
# Check what you're targeting before killing:
pgrep -l nginx           # list PIDs matching "nginx"
pkill -e --dry-run nginx # (not all versions support --dry-run)

Why Kubernetes Sends SIGTERM Before SIGKILL

When you delete a pod or a deployment scales down, Kubernetes doesn't immediately SIGKILL the container. It follows this sequence:

  1. Pod enters Terminating state
  2. Kubernetes removes the pod from the Service endpoints (traffic stops routing to it)
  3. Kubernetes sends SIGTERM to PID 1 in the container
  4. Kubernetes waits for terminationGracePeriodSeconds (default: 30 seconds)
  5. If the container is still running after the grace period, Kubernetes sends SIGKILL

This gives your app time to finish in-flight requests before dying. If your app ignores SIGTERM or doesn't exit fast enough, you'll get abrupt kills and potentially failed requests.

Handling SIGTERM in Your App

Python:

python
import signal
import sys
 
def handle_sigterm(signum, frame):
    print("Received SIGTERM, shutting down gracefully...")
    # close DB connections, flush cache, etc.
    sys.exit(0)
 
signal.signal(signal.SIGTERM, handle_sigterm)
 
# Your app runs here
while True:
    process_job()

Node.js:

javascript
process.on('SIGTERM', () => {
  console.log('SIGTERM received, closing HTTP server...');
  server.close(() => {
    console.log('HTTP server closed');
    process.exit(0);
  });
});

The PID 1 Problem in Docker

In Docker, if your container runs a shell script that starts your app, the app gets PID 2+, not PID 1. Signals sent to PID 1 (the shell) don't automatically forward to the app.

Fix: use exec in your entrypoint script so the app replaces the shell as PID 1:

bash
#!/bin/sh
# Entrypoint script
exec python /app/server.py   # app becomes PID 1

Or use the JSON array form in your Dockerfile:

dockerfile
ENTRYPOINT ["python", "/app/server.py"]
# NOT: ENTRYPOINT python /app/server.py  (this runs via /bin/sh -c)

Quick Reference

SignalNumberCan be caught?Common use
SIGTERM15YesGraceful shutdown
SIGKILL9NoForce kill (last resort)
SIGHUP1YesReload config
SIGINT2YesCtrl+C
SIGPIPE13YesBroken pipe
SIGUSR110YesApp-defined custom action
SIGUSR212YesApp-defined custom action

Understanding signals turns "the container died" from a mystery into a debuggable event. Check dmesg or journalctl for OOM kills (SIGKILL from the kernel), check your app logs for SIGTERM handling, and always make sure PID 1 in your containers is your actual process.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments