StackrootServer-side web stacks and the Linux systems that hold them, from config to debug.

Kill a Process on Linux

The Linux kill process command is the standard way to stop a running program by sending it a signal: kill takes a process id (PID), and by default sends SIGTERM (signal 15), which asks the program to exit cleanly.

A system monitor window listing running processes with CPU and memory columns.

A runaway job, a hung web worker, or a stuck MySQL server is stopped the same way, and the only variables are the signal number and the PID you pass. This page covers finding the PID, choosing the right signal, and killing a MySQL process by id.

Before you touch anything, know which tools are doing the work. The Linux Kernel assigns every running task a unique PID, and the shell built-in kill plus the killall and pgrep utilities make up the small set of Linux Commands that cover nearly every stop-job. You do not need to reboot; you do not need to restart the whole service. You send one signal to one PID, and the kernel does the rest. The rest of this page walks the chain: locate the process, read its state, send a signal, escalate if it ignores you, and handle the MySQL case where the id comes from inside the database rather than from ps.

How to find the PID of a process

To find the PID, you list running processes and read the first column, which is the process id the kernel assigned at start. Three commands cover most lookups:

  • ps aux lists every process on the system, sorted by CPU usage, with the PID in the second column.
  • pgrep -a mysql returns only the PIDs matching the name, one per line, which is cleaner when you copy a value.
  • top or htop shows live CPU and memory, so you can watch a runaway climb before you act.

Each row in ps aux is a different kind of information: USER, PID, %CPU, %MEM, VSZ, RSS, and COMMAND. The PID is the handle you pass to kill. The COMMAND column tells you whether the row is the server, a worker, or a client, which matters when a single program runs as a fork of many children.

CommandWhat it returnsWhen to use it
ps auxAll processes, PID in column 2Full overview, sorting by CPU
pgrep -a NAMEMatching PIDs onlyClean copy of one or a few ids
htopLive table of CPU and memoryWatching a runaway in real time

Which signal to send, and the difference between SIGTERM and SIGKILL

The signal you send decides whether the process gets a chance to clean up or is torn down instantly. Signal 15 (SIGTERM) is polite: it asks the process to finish its current work, release locks, and exit. Signal 9 (SIGKILL) is final: the kernel terminates the process immediately and the process cannot catch, ignore, or delay it. The practical rule is to start at 15 and escalate to 9 only after the process has ignored the first request for a full 10 to 30 seconds. Sending 9 straight away is fast but skips cleanup, so a database may leave behind a temporary file it would otherwise have removed, and a worker may drop an in-flight message it would have acked.

A small number of other signals matter on a server. Signal 1 (SIGHUP) reloads configuration and is how long-running daemons pick up new settings without a restart. Signal 2 (SIGINT) is what you send with Ctrl-C and is what the kernel delivers when you hang up a terminal. Signal 18 (SIGCONT) resumes a process you stopped earlier with Ctrl-Z or kill -STOP. For stopping a runaway, though, 15 and 9 carry the whole job.

How to kill a process by PID

To kill a process by PID, you run kill -15 12345, replacing 12345 with the PID from the previous section, and the -15 is optional because it is the default. The command prints nothing on success, so you confirm the result by re-running ps aux or pgrep and checking the PID has disappeared. If the process is still there after 10 to 30 seconds, you escalate with kill -9 12345. After a SIGKILL the kernel reaps the process and returns its PID slot to the free pool within a moment, so the number will not be reused for the same task.

A few failures are worth naming because they change what you do. If kill reports Operation not permitted, the process is owned by another user and you need root, which on a real host means sudo kill -9 12345. If the PID belongs to a zombie (state Z), the process has already died and its parent simply has not reaped it; killing the PID does nothing, so you find and fix the parent. If the process is a child of a service manager such as systemd or a supervisor, killing the child works but the manager may respawn it, so you stop the unit with systemctl stop NAME to make the stop stick. Killing a PID is one action; making sure it stays dead is a second action you choose based on who owns it.

How to kill a MySQL process by id

To kill a MySQL process by id, you work inside the database client instead of the shell, because the id you want is a MySQL thread id, not an operating-system PID. You connect with mysql -u root -p, then run SHOW PROCESSLIST; to list every active thread. The leftmost column is the thread Id, and the right-hand columns show the user, host, database, command, time in seconds, state, and current query. Find the row whose time or query matches the stuck work, and run KILL 42; replacing 42 with that thread Id. The statement returns an empty result on success, and SHOW PROCESSLIST; no longer shows the thread. This is the documented behaviour inside the MySQL server process: the server marks the thread for termination, waits for it to release its current lock, and then removes it from the processlist.

The distinction between the two kinds of id is the whole point of the MySQL case. An OS PID is what the kernel tracks and what ps shows; a MySQL thread id is what the database tracks and what SHOW PROCESSLIST; shows. A single mysqld process with one OS PID can host dozens of client threads, each with its own thread id, so killing the OS PID stops the entire server, while KILL 42; stops one connection and leaves the rest running. Use the OS-level kill when the server itself is unresponsive or leaking memory; use the database-level KILL when one long query or one stuck client is holding a lock. If a query will not end and the thread is stuck in a state that ignores the normal kill, the client can send KILL QUERY 42; to abort just the running statement and leave the connection open.

When a process will not die, and what to do next

When a process will not die, it is usually in an uninterruptible state, and the remedy is to address the cause rather than to send more signals. You confirm the state by reading the STAT column in ps aux: D means the process is waiting on I/O and cannot be signalled until that I/O completes, and R or S are the normal running and sleeping states. If the process sits in D for several minutes, the underlying disk or network path is the blocker, and the practical move is to identify the I/O with iotop or lsof -p PID, then clear the fault at the device level. In the rare case of a stuck kernel path, the only options are to stop the offending hardware path or to reboot, and you record the PID and the state first so the incident is documented. After a process finally clears, you confirm the stop end to end: pgrep returns nothing, the service supervisor has not respawned a replacement, and the application that depended on it has recovered, which for a web tier means the queue drains and requests stop timing out after the next 1 or 2 polling intervals.

A quick decision guide

The right move depends on what is stuck and who owns it, so a short decision table keeps the actions in order. Start at the top row and follow the first match. The path is always the same shape: locate the PID or thread id, send the polite signal or statement first, wait 10 to 30 seconds, then escalate, and finally check that nothing has respawned the work you stopped. Keeping that sequence means you spend the minimum time in the window where the service is down, and you leave a clean audit trail in the shell history and the database log. For anything you have not stopped before, run the locate step twice: once with the command you expect and once with a broader ps aux | grep NAME, so the id you send is the one you think it is.

SituationFirst actionEscalation
Runaway CPU, owned by youkill -15 PIDkill -9 PID after 30 s
Runaway CPU, owned by rootsudo kill -15 PIDsudo kill -9 PID
One stuck MySQL queryKILL QUERY 42;KILL 42;
Unresponsive mysqld serversystemctl stop mysqlkill -9 on the OS PID
Process in D stateCheck I/O with iotopClear the device fault

Where to go next