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 1234With no signal specified, kill sends SIGTERM.
You can make that explicit:
kill -TERM 1234If the process does not terminate after you’ve given it a reasonable amount of time:
kill -KILL 1234The important habit is to verify the PID before sending the signal.
ps -p 1234 -o pid,user,stat,cmdYou want to know:
PID
USER
STATE
COMMANDbefore 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,cmdFor example:
PID USER STAT CMD
4821 alice S python3 /home/alice/server.pyNow 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.pyFor example:
4821 python3 /home/alice/server.py
7350 python3 /opt/tools/server.pyNow 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.pyThis 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.pyThen, if the result is exactly what you intend:
pkill -TERM -f server.pyThe -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 pythoncould 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.pyThis 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.pyThen terminate them:
pkill -u alice -TERM server.pyThe general principle is:
More specific matching
↓
smaller set of possible targets
↓
safer operationkillall: Kill By Process Name
killall also works primarily with process names:
killall serverAs 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 serverThen 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:
| Command | Main Selection Method | Best Fit |
|---|---|---|
kill | Explicit PID | One known process |
pkill | Pattern and process attributes | Controlled pattern-based selection |
killall | Process name | Stop 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
↓
killallThe important part is not memorizing the commands. It is understanding the scope of the selection.
A Common Dangerous Pattern
Consider:
pkill -f pythonThis 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.pyand all three could become targets.
A safer approach is to first identify the exact process:
pgrep -af web-server.pyThen, 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 1234stops a process.
kill -CONT 1234continues it.
And:
kill -HUP 1234sends 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 1234check the process:
ps -p 1234 -o pid,stat,cmdIf there is no output, the process is gone.
You can also use:
pgrep -af server.pyto 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 permittedwhen 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 1234The 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 necessaryFor multiple matching processes:
Build a precise match
↓
pgrep to preview targets
↓
Check the output carefully
↓
pkill if the whole selection is intendedThat 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 selectionAnd 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.