How to Force Quit Unresponsive Programs on Ubuntu

force quit ubuntu

Find the process ID, then signal it. Run pgrep -a firefox to get the PID, then kill 1234 to ask it to shut down cleanly. If it is still running ten seconds later, escalate with kill -9 1234. On Ubuntu 26.04 LTS the graphical equivalent is the Resources app — GNOME System Monitor is no longer the default install.

Find the PID without matching your own search

The classic ps aux | grep firefox has a well-known flaw: the grep process itself carries “firefox” on its command line, so ps reports it. Here it is on a machine where no program matching the token existed:

$ ps aux | grep heatgrepself_89881
[user]  90049  0.0  0.0  435300144  1456  ??  S  12:40PM  0:00.00 grep heatgrepself_89881

One result, and it is the search itself. Use pgrep instead — it never matches itself:

pgrep -a firefox      # PID + full command line (Linux)
pgrep -l firefox      # PID + process name (macOS/BSD)

-a differs by system: procps-ng on Linux documents it as “List the full command line as well as the process ID”, while on macOS and the BSDs it means “Include process ancestors in the match list” — use -l there. Both from their own man pages.

kill sends SIGTERM, not SIGKILL

Plain kill 1234 sends signal 15, SIGTERM — a request to shut down, which a well-behaved program handles by saving state and closing files. It is not a forced stop, and a program may catch or ignore it.

That is the actual reason kill “doesn’t work”. Tested with a script that ignores SIGTERM: a plain kill left it running, and only kill -9 removed it. SIGKILL (signal 9) is delivered by the kernel and cannot be caught, blocked or ignored.

Always try kill first, because kill -9 gives the program no chance to flush buffers or release locks. On PostgreSQL or MySQL it leaves the server to perform crash recovery at next start — downtime you chose to have. (Documented vendor behaviour; not reproduced here.) The same reasoning scales badly upwards: kill -9 -1 signals every process you own, including the shell that ran it, so a runaway set wants pkill -f against a pattern you have already checked with pgrep -f.

When kill -9 also fails, read the state first

If kill -9 appears to do nothing, the process is usually not “extra stubborn” — it is stuck in the kernel waiting on I/O that never returns, typically a dead NFS mount or a failing disk. Check before escalating:

ps -o stat= -p 1234

A leading S is normal interruptible sleep. A leading D on Linux means uninterruptible sleep: the process cannot be killed by any signal, SIGKILL included, because the signal is only delivered once the I/O completes. Fix the storage or reboot. (macOS spells the same state U. This is documented Linux kernel behaviour, not reproduced on the macOS machine used for the other checks here.)

pkill vs killall: the difference is how they match

The two commands do not differ by “one process versus all” — both signal every match. They differ in what counts as a match.

CommandHow it matchesDefault signal
kill PIDExactly one process, by IDSIGTERM
pkill NAMESubstring, as an extended regular expression, against the process nameSIGTERM
pkill -f NAMESubstring against the whole command lineSIGTERM
killall NAMEExact command name (unless -r)SIGTERM

So pkill chrom kills Chrome. Verified with a purpose-built process named hwdemo_89881, searched by the strict prefix hwdemo:

$ pgrep hwdemo
89945
$ pgrep -x hwdemo          # -x forces an exact match
$ killall hwdemo
No matching processes belonging to you were found

pgrep matched the prefix; pgrep -x and killall refused it. (Run on macOS 26.6 — the matching rule is the same on Linux, though psmisc killall there prints hwdemo: no process found.)

Two consequences. First, pkill -f python matches any command line containing “python” — your editor, your language server, the terminal you are typing in. Second, on Linux the matched name is capped: procps-ng documents that “The process name used for matching is limited to the 15 characters present in the output of /proc/pid/stat”, so patterns aimed past character 15 match nothing.

Preview first: pgrep -a PATTERN takes the same pattern and only lists.

The graphical route on Ubuntu 26.04

Ubuntu 26.04 LTS ships Resources in place of GNOME System Monitor. Search the Activities overview for “Resources”, open the Processes or Apps view, select the entry and use the stop control. Guides describing System Monitor’s “Processes” tab and “End Process” button do not match a default 26.04 install. (Ubuntu 26.04 LTS release notes; not run here.)

xkill: correct package, and why it may not help

There is no package called xorg-xkill — that command returns E: Unable to locate package xorg-xkill. xkill ships in x11-utils:

sudo apt install x11-utils

Then run xkill and click the offending window. The caveat matters: xkill works by telling the X server to close a client’s connection, and the Ubuntu 26.04 desktop session is Wayland-only — GNOME Shell can no longer run an X.org session. It therefore reaches only applications running through XWayland; click a native Wayland window and nothing happens. (Ubuntu 26.04 LTS release notes and the xkill man page; not run here.)

One correction for Windows switchers

Ctrl+Alt+Del opens the security screen — the menu carrying Lock, Sign out and Task Manager. The shortcut that opens Task Manager directly is Ctrl+Shift+Esc. (Documented Microsoft behaviour; no Windows machine was used here.)

One edit to the output above: the account name in every command result on this page has been replaced with [user]. Nothing else is altered — the commands, their output, the permissions, the timings and the errors are exactly as they ran.

Check this yourself. Every command and every block of output on this page is reproduced by /verify/force-quit-process-ubuntu.sh. Download it and run it: it creates its own scratch files, prints one line per claim, cleans up after itself, and exits non-zero if any claim here turns out to be wrong. If it disagrees with this page, the page is wrong.

Photo of author
Sudhir P. founded HeatWare.com in 1999 and has built and operated it full-stack ever since; it is now used by more than 88,000 people. He writes here about the PostgreSQL, MySQL, Linux and DevOps work that keeps it running. Articles are rewritten only after the commands in them have actually been run, and the verification scripts are published alongside them so anyone can check the claims. Reach him at blog@heatware.net.