Do not run kill -9 -1. The -1 is not a signal or a PID — it means “every process I am allowed to signal”, and -9 means they get no chance to save anything. On your own account that includes your shell, your SSH session and your desktop, so the command ends by killing the thing that ran it. To clear a runaway set, name it: pgrep -f PATTERN to see exactly what matches, then pkill -f PATTERN once the list is right.
An earlier version of this page gave kill -9 -1 as the way to “stop every running process”, and listed kill -u username as a command. That second one does not exist.
$ kill -u nobody
bash: kill: u: invalid signal specification
$ /bin/kill -u nobody
kill: unknown signal u; valid signals:
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URGkill takes a signal and PIDs, and has no user filter in either the bash builtin or the standalone binary. The commands that do take -u are pkill and killall — and both, pointed at your own username, terminate the session you are typing in.
Table of Contents
How wide is “all processes”, exactly?
Counted rather than guessed, on an ordinary desktop login:
$ pgrep -u "$(id -u)" | wc -l
584That is the blast radius of kill -9 -1, pkill -u $USER and killall -u $USER run as yourself: 584 processes, one of which is the shell reading the command. As root it is every process on the box.
Escalating straight to -9 is the second mistake. SIGTERM can be caught, so a program can flush buffers and delete lock files; SIGKILL cannot, so none of that runs. Same job, both signals:
after plain kill : [none]
after kill -9 : hw_w13_job.97896.tmp hw_w13_job.lockThe job held a lock directory and a partial-results file and cleaned both up on SIGTERM. Under kill -9 the lock outlives the process — which is where “it won’t start, it says another instance is running” comes from. Reach for -9 only after a plain kill has visibly failed; the single-process case, and telling a stuck process from a slow one, is covered separately.
pkill -f matches more than you are picturing
Three processes. One is the target; the others are an unrelated supervisor and a tail -f on the log — the sort of thing you would have open while deciding what to kill:
$ pgrep -f hw_w13 (with the command line of each match)
99455 /bin/sh ./hw_w13_worker
99456 /bin/sh ./hw_w13_worker_supervisor
99457 tail -f hw_w13_worker.log
$ pkill -f hw_w13_worker
$ pgrep -f hw_w13
matches remaining: 0All three. -f matches the pattern anywhere in the entire command line: the log viewer died because the log’s filename contains the worker’s name, the supervisor because its name starts with it. This is why pkill -f node takes your editor’s language server with it. Run pgrep -f with the same pattern first, every time — identical argument, and it only prints.
Whether the script kills itself depends on the OS
A cleanup script running pkill -f hw_w13, whose own path contains hw_w13, survived here and printed its remaining steps. The BSD pkill man page says why:
“
-aInclude process ancestors in the match list. By default, the current pgrep or pkill process and all of its ancestors are excluded (unless -v is used).”
Measured: pgrep -u UID returned 584 PIDs and did not include the calling shell; pgrep -a -u UID returned 590 and did. Six ancestors, silently skipped.
Linux does not do this by default. The procps-ng pgrep man page says only that “The running pgrep, pkill, or pidwait process will never report itself as a match”, and makes ancestor exclusion an opt-in flag: “-A, --ignore-ancestors: Ignore all ancestors of pgrep, pkill, or pidwait.” So the cleanup script that is safe on macOS kills its own shell partway through on Linux. (Linux side cited from the man page, not executed — no Linux machine was used for this article.)
Three different programs are called killall
On Linux and the BSDs it kills processes matching a name. On System V-derived systems it does not:
“This FreeBSD implementation of killall has completely different semantics as compared to the traditional UNIX System V behavior of killall. The latter will kill all processes that the current user is able to kill, and is intended to be used by the system shutdown process only.” —
man killall, macOS 26.6
So killall with no arguments on Solaris or AIX is a shutdown command. Matching differs too: BSD matches the exact process name and takes a regex with -m, while GNU psmisc uses -r and rejects -m. Against a live scratch process called hw_w13_worker — a compiled stub, so the process name is its own rather than sh (-s shows what would be signalled, without sending it):
$ killall -s hw_w13
No matching processes belonging to you were found
$ killall -s hw_w13_worker
kill -term 91021
$ killall -s -m hw_w13
kill -term 91021
$ killall -s -r hw_w13
killall: unknown signal r; valid signals: ...The prefix matched nothing until -m made it a regular expression — and that flag’s own warning is worth quoting exactly: “CAUTION! This is dangerous, a single dot will match any process running under the real UID of the caller.” A pattern of . under -m is kill -1 with extra steps.
One more command from the old page that does not run
$ ps aux --sort=-%cpu
ps: illegal option -- -
usage: ps [-AaCcEefhjlMmrSTvwXx] [-O fmt | -o fmt] [-G gid[,gid...]]--sort is a procps-ng extension: fine on Linux, rejected on macOS and the BSDs, where the equivalent is ps -Ao pid,pcpu,comm -r.
What was run, and what was not
Every command block above was executed on macOS 26.6 arm64 against scratch processes named hw_w13_*; nothing was killed that this article did not create. The Linux pkill/killall differences and the System V killall behaviour come from the man pages and were not executed — no Linux, Solaris or AIX machine was available. kill -9 -1 was deliberately not run; its scope was measured with pgrep. The falsifier is verify-kill-all-processes.sh.
