Home / Alt manpages / kill(1)

  • kill(1)
  • User command
  • linux

Stop Linux Processes Safely with kill

Something is stuck, the terminal is not responding, and someone types kill before checking what they are about to send a signal to. This guide builds a repeatable way to identify a process, ask it to stop, verify what happened, and escalate only when necessary. The examples use the installed procps-ng kill 4.0.4 command. Allow about ten minutes.

  • You need: a shell and a process you are authorised to control. Most inspection steps are ordinary user commands; stopping another user's process may require elevated privileges.

Safety boundary

A signal changes a running process. Do not experiment with a production service, a process you do not recognise, or a copied PID. The examples use a private sleep process where possible, so you can practise without changing a service.

1. Confirm which kill you are using

Many shells provide a built-in kill. It usually supports the same everyday syntax, but this guide documents the procps command, and that difference has caught people out before. Check both the selected command and its version:

$ command -v kill
/usr/bin/kill
$ /bin/kill --version
kill from procps-ng 4.0.4

Your path may differ. If command -v kill reports a shell built-in, use /bin/kill for the examples that depend on procps-specific options such as -L.

Checkpoint

The command you intend to run is the one whose behaviour you have just inspected.

2. Inspect signal names before sending one

The default signal is TERM, also written SIGTERM. It asks a process to terminate cleanly, which is why it is the polite first move rather than the blunt one. List the signal names supported by this installation:

$ /bin/kill -l
HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT
CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS

The ordering and available names depend on the platform, so treat the output above as authoritative only for your machine. To translate a number, pass it as the optional argument to -l:

$ /bin/kill -l 15
TERM

Signals mean different things, and mixing them up is an easy way to make a bad situation worse:

  • TERM gives the program a chance to close files and release resources.
  • KILL cannot be caught or cleaned up by the target.
  • STOP pauses a process.
  • CONT resumes one that was stopped.

Do not choose a signal by number when a name makes the intent clearer.

3. Create a harmless test process

Start a short-lived process in the background and save its PID immediately. This is unprivileged and changes only your shell's child process:

$ sleep 300 &
[1] 24680
$ test_pid=$!
$ printf 'test PID: %s\n' "$test_pid"
test PID: 24680

The job number and PID above are examples and will vary on your machine. The shell's $! value is the PID of the most recently started background command. Keep it in a variable rather than retyping a number copied from a different terminal.

Checkpoint

Inspect that PID before sending anything. ps is read-only, so there is no risk in checking twice:

$ ps -o pid=,ppid=,stat=,comm= -p "$test_pid"
 24680  2123099 S    sleep

You want the expected command name and a live row for the expected PID. If the row is empty or the command is not the one you started, stop. Do not send a signal to that PID.

4. Ask the process to stop cleanly

Send TERM by name. The -- separates options from the PID argument and makes the command boundary easier to review at a glance:

$ /bin/kill --signal TERM -- "$test_pid"
$ wait "$test_pid"
$ printf 'exit status: %s\n' "$?"
exit status: 143

Example

A shell commonly reports 128 plus the signal number, so 143 means the child ended after signal 15. The exact status can differ if a wrapper handles the signal itself.

Verify that it is no longer running:

$ ps -p "$test_pid" -o pid=,stat=,comm=
$ printf 'ps status: %s\n' "$?"
ps status: 1

An empty row and non-zero ps status mean this PID is no longer present. PIDs are reused, so do not keep signalling a saved number after the original process has gone; you may be signalling something entirely unrelated.

5. Use signal 0 for a permission and existence check

Signal 0 is the quiet one: the kernel performs the usual existence and permission checks but does not deliver a signal. It is useful before an operation, but it does not prove that a process is healthy or belongs to the command you expect:

$ /bin/kill -s 0 -- "$test_pid"
/bin/kill: (...) - No such process
$ printf 'check status: %s\n' "$?"
check status: 1

For a live PID, a zero exit status means the check succeeded. A non-zero status can mean the process does not exist, or that your user lacks permission. Use ps to tell those two apart. Do not jump straight to sudo; first confirm the PID and the required administrative boundary.

6. Escalate only after TERM fails

Some programs ignore TERM, are stuck in a state where they cannot handle it, or need more time to finish. First inspect the same PID again and check the application's own logs or service manager. If you have confirmed the process must stop, KILL is the forceful option:

$ /bin/kill --signal KILL -- PID_TO_STOP
$ ps -p PID_TO_STOP -o pid=,stat=,comm=
  

Replace PID_TO_STOP only after checking it with ps. The command normally prints nothing when it succeeds.

Warning

KILL prevents the process from running cleanup code and can leave temporary files, locks, transactions or child processes behind. It is service-disrupting and may lose in-memory data. There is no undo for a delivered KILL; recovery means restarting the program and repairing whatever state it left behind.

7. Avoid process-group and all-process traps

A negative PID selects a process group, not one ordinary process, and this is where a stray minus sign turns a small mistake into a big one. The process-group ID appears in ps output when requested:

$ ps -o pid=,pgid=,comm= -p PID_TO_INSPECT
 24680  24680 sleep

Never turn a copied PID into a negative number casually. A group can contain a shell, workers and unrelated commands.

Destructive action

The procps manual also gives -1 a special meaning: all processes you can signal except the kill process itself and init. This is an extreme, destructive action. Do not run kill -1 or kill -9 -1 as a test, from a service account, or on a system whose recovery you cannot control.

If you need to stop a service, use its service manager and its documented unit rather than guessing at a process group. For systemd, inspect first with systemctl status UNIT_NAME; changing or stopping the unit is a separate administrative action that needs a maintenance decision and a recovery plan.

Common traps

  • kill: usage... usually means the command line was malformed. Check the signal spelling and that the PID is numeric. If a PID begins with a hyphen, use -- or resolve why it was produced before proceeding.
  • No such process means the PID is not currently valid for the requested operation. Re-run ps immediately; the process may have exited, or the PID may have been copied incorrectly.
  • Operation not permitted means your user cannot signal that process. Confirm ownership, then use the approved administrative route.
  • A successful signal is not proof of shutdown. A zero exit status is not proof that the application performed the shutdown you wanted, so verify the process and its service state afterwards.

Done means

  • Confirmed the version. You checked the procps-ng version and, where relevant, used /bin/kill instead of a shell built-in.
  • Inspected before signalling. You checked the exact PID with ps immediately before signalling it.
  • Started polite. You used named TERM first and verified whether the process exited.
  • Understood signal 0. You know it checks existence and permission without stopping anything.
  • Reserved the blunt tools. You keep KILL, negative PIDs and -1 for deliberate, reviewed operations.
  • Planned recovery. You have a recovery plan before stopping a service or using a signal that cannot be undone.