iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

kill / signals

kill sends signals to processes — not just SIGTERM/SIGKILL but a whole vocabulary for graceful shutdown, config reload, debugging. kill, pkill, killall, pgrep, and jobs/fg/bg together cover most process management.

Signals, pkill, traps, find pids

EXAMPLE
# 1) Find process IDs
ps -ef | grep nginx               # full output, filter
ps aux | grep -i postgres
pgrep -fl nginx                    # PIDs + cmdline; usually cleaner
pgrep -u mara node                 # by user
pidof nginx                        # main pid
fuser -k 8080/tcp                   # kill whatever holds tcp/8080
lsof -ti :3000                     # PID listening on port 3000
ss -tlnp | grep :3000              # what's listening

# 2) Basic kill — default is SIGTERM (15)
kill 1234                          # SIGTERM
kill -15 1234                      # explicit
kill -TERM 1234                    # by name

# 3) Common signals
#   1   SIGHUP    — reload config (nginx, httpd, daemons)
#   2   SIGINT    — Ctrl+C
#   3   SIGQUIT   — Ctrl+\ → dump core
#   9   SIGKILL   — uncatchable; immediate kill
#   15  SIGTERM   — polite termination
#   18  SIGCONT    — resume
#   19  SIGSTOP   — pause (uncatchable)
#   20  SIGTSTP   — Ctrl+Z
#   USR1 / USR2   — app-defined; commonly 'reopen logs' / 'rotate'

kill -HUP 1234                     # ask nginx to reload
kill -USR1 1234                    # nginx: reopen log files
kill -USR2 1234                    # nginx: live binary upgrade

# 4) SIGTERM vs SIGKILL
kill 1234                          # asks nicely; app catches; cleans up
kill -9 1234                       # KERNEL forces; no chance to clean up

# Prefer TERM. Only use KILL when:
#   • App hung (not responding to TERM after 10-30s)
#   • Shutdown signal not implemented
#   • Last resort

# 5) Patterns by name
pkill -TERM nginx                  # send TERM to all matching cmdline
pkill -f 'node server.js'          # match against FULL cmdline
pkill -u mara -TERM                 # by user
killall nginx                       # similar, but matches exact process name (no path)

# 6) Verify before killing
pgrep -fa nginx                     # show what WOULD be killed (-a shows cmdline)
pkill -n -f 'node old.js'           # -n: kill NEWEST match only

# 7) Graceful shutdown handler — example app
#   trap signals → drain → exit cleanly

# Node
function shutdown(signal) {
    console.log(`${signal} received, draining`);
    server.close(() => process.exit(0));
    setTimeout(() => process.exit(1), 10_000).unref();   // force exit after 10s
}
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT',  () => shutdown('SIGINT'));

# Python
import signal, sys
def handler(sig, frame):
    print(f'{signal.Signals(sig).name} received')
    sys.exit(0)
signal.signal(signal.SIGTERM, handler)

# Go
import "os/signal"; import "syscall"
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
<-c
// drain

# 8) Background + foreground jobs (interactive shell)
long-running-command &              # run in background
jobs                                 # list
fg %1                                # bring job 1 to foreground
bg %1                                # resume in background

Ctrl+Z                               # suspend foreground (SIGTSTP)
bg                                    # resume in background
disown -h %1                         # detach so it survives shell exit
nohup long-running &                  # immune to HUP signals

# 9) Killing process trees
kill -- -PGID                        # negative number = process GROUP
killpg PGID                          # equivalent

# Get PGID:
ps -o pgid= -p 1234

# Useful when a parent forks children; kill the GROUP not the PID.

# Systemd:
systemctl kill --signal=SIGTERM nginx.service
systemctl kill --kill-who=main nginx.service

# 10) Resource constraints + watchdog
# Process keeps respawning despite kill?
# • Check supervisor: systemd, supervisord, upstart
# • Stop the SERVICE, not the PID
systemctl stop nginx
supervisorctl stop myapp

# 11) Killing in scripts (graceful with timeout)
kill -TERM $PID
for i in {1..10}; do
    if ! kill -0 $PID 2>/dev/null; then break; fi
    sleep 1
done
kill -KILL $PID 2>/dev/null         # nuke if still alive

# kill -0 checks existence without sending a real signal.

# 12) Common patterns by goal
# Graceful restart of nginx:
sudo systemctl reload nginx           # SIGHUP

# Reload Postgres config:
sudo systemctl reload postgresql
# OR
sudo -u postgres pg_ctl reload

# Kill a hung SSH session:
ps -ef | grep ssh
kill -9 $PID

# Free a port:
fuser -k 3000/tcp
# Or:
lsof -ti :3000 | xargs -r kill

# 13) Common bugs
# • Sending SIGKILL by reflex → data loss / orphan files
# • kill -9 on a Docker container → container exits 137; orchestrator may restart
# • pkill -f matching too broadly → killed unintended processes
# • Trap handler in shell script + Ctrl+C → trap fires, but child still running
# • Killing PID 1 inside a container → container stops; intentional but surprising
# • Forgetting permissions — kill requires same UID OR root
# • Race: signal sent before app installed handler → exits immediately
# • Detached job + shell exit → SIGHUP kills it; use nohup or disown
# • TERM after KILL — KILL already killed; the process is gone or unreachable

Why it matters

Default to SIGTERM and let apps shut down cleanly; reserve SIGKILL for genuinely hung processes. Use pkill -f for pattern matches, kill -HUP to reload configs, kill -0 to test liveness, and wrap your apps with proper signal handlers so graceful shutdown actually happens during deploys.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
kill -TERM $(pgrep node)
kill -9 12345                  # SIGKILL — only as last resort
Try it Yourself »

Discussion

Loading…