Skip to content

Killing Processes


Knowing what signals are is only half of process control. The harder part is deciding which process to signal and making sure you are targeting the right one.

Linux gives you several ways to send signals. kill works with explicit PIDs, while pkill and killall can select processes by name or other attributes. The convenience is useful, but the broader the matching rule, the greater the chance of hitting something you did not intend to touch.

kill: Target A Specific PID

The safest starting point is usually an exact PID:

kill 1234

With no signal specified, kill sends SIGTERM.

You can make that explicit:

kill -TERM 1234

If the process does not terminate after you’ve given it a reasonable amount of time:

kill -KILL 1234

The important habit is to verify the PID before sending the signal.

ps -p 1234 -o pid,user,stat,cmd

You want to know:

PID
USER
STATE
COMMAND

before doing anything destructive.

Verify Before You Kill

Suppose you know that a process called python3 is causing a problem.

Don’t immediately do:

kill <some-pid>

First inspect it:

ps -p <PID> -o pid,user,stat,cmd

For example:

PID   USER   STAT  CMD
4821  alice  S     python3 /home/alice/server.py

Now you know that PID 4821 is actually the server you intended to stop.

This is especially important on a multi-user system where several processes may have similar names.

Check The Process More Broadly

If you only know part of the command, ps can help you locate it:

ps aux | grep '[s]erver.py'

The bracket trick prevents grep itself from appearing in the result.

But you already have a better tool for this job: pgrep.

pgrep -af server.py

For example:

4821 python3 /home/alice/server.py
7350 python3 /opt/tools/server.py

Now you can see that the name alone isn’t enough to distinguish the processes.

This is exactly where careless process matching becomes dangerous.

pkill: Kill By Process Attributes

pkill sends a signal to processes selected by a pattern.

For example:

pkill -TERM server.py

This is more convenient than finding every PID manually, but it can match more than you expect depending on the pattern and the options used.

You can first test the selection without actually sending a signal:

pgrep -af server.py

Then, if the result is exactly what you intend:

pkill -TERM -f server.py

The -f option makes the pattern match the full command line rather than only the process name. That makes matching more precise in some situations, but it also makes broad patterns more dangerous.

For example:

pkill -f python

could match far more processes than you intended.

Match By User

You can restrict a process selection to a particular user:

pkill -u alice -TERM server.py

This is useful on systems where multiple users may be running similarly named programs.

You can inspect the intended processes first:

pgrep -u alice -af server.py

Then terminate them:

pkill -u alice -TERM server.py

The general principle is:

More specific matching
        ↓
smaller set of possible targets
        ↓
safer operation

killall: Kill By Process Name

killall also works primarily with process names:

killall server

As with pkill, the convenience comes from not needing to find individual PIDs first. But name-based termination can be dangerous when multiple processes share that name. Before using it, inspect what you are dealing with:

pgrep -a server

Then decide whether terminating every matching process is actually what you want.

If you only intend to stop one process, kill <PID> is usually the clearer choice.

kill vs pkill vs killall

The three commands have different selection models:

CommandMain Selection MethodBest Fit
killExplicit PIDOne known process
pkillPattern and process attributesControlled pattern-based selection
killallProcess nameStop processes matching a name

Think of them like this:

I know the exact process
        ↓
      kill PID

I need to select by attributes/pattern
        ↓
      pkill

I intentionally want processes with this name
        ↓
      killall

The important part is not memorizing the commands. It is understanding the scope of the selection.

A Common Dangerous Pattern

Consider:

pkill -f python

This looks simple, but the pattern can match every Python process whose command line contains python.

You might have:

python3 web-server.py
python3 worker.py
python3 backup.py

and all three could become targets.

A safer approach is to first identify the exact process:

pgrep -af web-server.py

Then, if there is only one intended PID:

kill -TERM <PID>

Or, if there are deliberately multiple matching workers and you really want all of them, use a sufficiently specific pkill pattern.

kill Can Send Other Signals Too

The command name doesn’t limit you to termination.

For example:

kill -STOP 1234

stops a process.

kill -CONT 1234

continues it.

And:

kill -HUP 1234

sends SIGHUP.

This is why thinking of kill as send a signal to a selected process is more accurate than thinking of it as simply “kill a process.”

Check Whether It Actually Stopped

After sending SIGTERM:

kill -TERM 1234

check the process:

ps -p 1234 -o pid,stat,cmd

If there is no output, the process is gone.

You can also use:

pgrep -af server.py

to check whether the intended process is still present.

Don’t assume that because kill returned to your prompt, the process has already exited. Sending a signal and the process completing its shutdown are separate events.

Permissions Matter

You cannot necessarily signal every process on the system.

For example, an ordinary user can generally signal processes they own, but signaling another user’s process may require additional privileges.

You may therefore see:

Operation not permitted

when trying to signal a process you do not have permission to control.

If you are authorized to manage that process, you may need:

sudo kill -TERM 1234

The important point is that sudo gives you the privilege needed to send the signal; it does not change what the signal itself means.

A Practical Escalation Workflow

For a process that needs to be stopped:

Identify the process
        ↓
Verify PID / command / user
        ↓
Send SIGTERM
        ↓
Check whether it exited
        ↓
Investigate if it remains
        ↓
Send SIGKILL only if necessary

For multiple matching processes:

Build a precise match
        ↓
pgrep to preview targets
        ↓
Check the output carefully
        ↓
pkill if the whole selection is intended

That preview step is one of the safest habits you can develop with pkill.

What You Should Remember

Use the narrowest selection that solves the problem.

kill PID
    → exact target

pkill pattern
    → pattern-based selection

killall name
    → name-based selection

And remember the most important rule:

Never send a destructive signal until you know exactly which processes the command will target.

For one known process, an explicit PID is usually easiest to reason about. For multiple processes, pgrep gives you a way to inspect the selection before pkill or killall acts on it.

What’s Next

The next lesson moves from managing processes directly to job control: running commands in the foreground or background, moving jobs between the two, and keeping processes running after you disconnect with nohup.

Last updated on