Skip to content
Home » How to Kill a Process on macOS: kill, pkill, killall, and launchctl

How to Kill a Process on macOS: kill, pkill, killall, and launchctl

Ending a process on macOS is two steps: find it, then send it a signal. ps, pgrep, and lsof find it; kill, pkill, and killall end it. The three “kill” commands differ only in how you name the target — a PID, a pattern, or an exact name — and picking the right one is most of the job. Everything here was run on macOS 26.5.2.

Find the process

By name, pgrep returns the PID; add -l to see the command and -f to match against the whole command line, not just the process name:

$ pgrep -fl Safari
594 /Applications/Safari.app/Contents/MacOS/Safari

By what’s holding a port — the usual reason a dev server won’t start — lsof with -t prints just the PID:

$ lsof -ti :3000
85714

kill, pkill, killall: pick your target

All three end a process. They differ in how you point at it:

kill 594                     # a single PID
pkill -f "node server.js"    # anything matching a command-line pattern
killall Safari               # every process with that exact name

kill takes the PID you already found. pkill matches by process name, or with -f the full command line, which is what you want when several processes share one launcher. killall takes an exact name and ends every instance of it — exact matters: killall "Google Chrome" works, killall chrome matches nothing.

All three send SIGTERM (signal 15) by default, which asks a process to shut down and lets it save first. When something is genuinely stuck and ignores that, -9 sends SIGKILL, which can’t be caught — it stops the process at once with no chance to clean up, so it’s the last resort, not the default:

kill -9 594
killall -9 "App Name"

The two cases this comes up most

A port is “already in use.” Find what’s on it and end that one process in a single line:

lsof -ti :3000 | xargs kill

lsof -ti prints only the PID(s) bound to port 3000, and xargs passes them to kill. If a plain kill doesn’t free the port, repeat it as lsof -ti :3000 | xargs kill -9.

An app is frozen and won’t quit. End every process running under its name at once:

killall -9 "App Name"

Get the exact name from Activity Monitor, or from pgrep -fl before you kill, so killall has something to match.

launchctl for background services

Ordinary kill handles running programs. Background services managed by launchd — the ones defined by .plist files in LaunchAgents and LaunchDaemons — are handled with launchctl. List what’s loaded, filtered to what you care about:

launchctl list                 # PID  Status  Label, one row per service
launchctl list | grep myservice

Load or unload a service from its plist, and start or stop one that’s already loaded:

launchctl load   ~/Library/LaunchAgents/com.example.agent.plist
launchctl unload ~/Library/LaunchAgents/com.example.agent.plist
launchctl start  com.example.agent
launchctl stop   com.example.agent

These load, unload, start, and stop forms are what most setup instructions use, and they work. macOS also has newer domain-based commands — launchctl bootstrap, bootout, and kickstart -k to restart a service in place — which mainly matter when a service ignores the older forms or has to be targeted in a specific login or GUI session.

Day to day that’s the whole toolkit: pgrep and lsof to find a process, kill / pkill / killall to end it, -9 when it won’t listen, and launchctl for the background services kill shouldn’t touch.

Leave a Reply

Your email address will not be published. Required fields are marked *