Process Control: Start, Stop, Kill
You need to control processes. Start them. Stop them. Kill them when they misbehave.
Here's the thing: Process control is essential. You'll do it constantly.
Starting Processes
Foreground (Normal)
./script.sh # Run script
python app.py # Run Python
nginx # Start nginx
What happens: Process runs. Blocks terminal. You see output. Ctrl+C stops it.
My take: This is normal. Most commands run this way.
Background (With &)
./script.sh & # Run in background
python app.py & # Background Python
What happens: Process runs. Doesn't block terminal. Shows job number.
Real example:
$ ./long_script.sh &
[1] 12345
$
Job [1], PID 12345. Terminal is free.
My take: Use & when you want to keep using the terminal. Process runs in background.
nohup: Survive Terminal Close
nohup ./script.sh > output.log 2>&1 &
What it does: Runs in background. Survives terminal close. Output goes to file.
The 2>&1: Redirects errors to same place as output.
My take: Use nohup for long-running processes. They keep running after you disconnect.
Stopping Processes
kill: Send Signals
kill PID # Send TERM (graceful)
kill -9 PID # Send KILL (force)
kill -15 PID # Send TERM (explicit)
kill -HUP PID # Send HUP (reload)
Common signals:
- TERM (15) = Terminate gracefully (default)
- KILL (9) = Force kill (cannot be ignored)
- HUP (1) = Hang up (often reloads config)
- INT (2) = Interrupt (like Ctrl+C)
My take: Try kill first (TERM). If that doesn't work, use kill -9 (KILL). Force kill is last resort.
Real example:
$ ps aux | grep nginx
ubuntu 1234 ... nginx
$ kill 1234 # Try graceful first
$ kill -9 1234 # Force if needed
killall: Kill by Name
killall process-name # Kill all processes with name
killall -9 process-name # Force kill
Real example:
killall nginx # Kill all nginx processes
My take: Useful when you don't know the PID. But be careful. Kills all processes with that name.
pkill: Kill by Pattern
pkill -f "pattern" # Kill processes matching pattern
pkill -9 -f "pattern" # Force kill
Real example:
pkill -f "python.*script.py" # Kill Python script
My take: More flexible than killall. Use patterns. Useful for specific processes.
Finding PIDs
ps aux | grep process-name # Find process
pgrep process-name # Get PIDs
pidof process-name # Get PID
My take: ps aux | grep is what you'll use. Simple. Works.
Job Control
jobs: List Background Jobs
jobs # List jobs
jobs -l # List with PIDs
Real example:
$ ./script.sh &
[1] 12345
$ jobs
[1]+ Running ./script.sh &
fg: Bring to Foreground
fg %1 # Bring job 1 to foreground
fg # Bring last job
My take: Useful when you want to see output. Or interact with the process.
bg: Run in Background
bg %1 # Run job 1 in background
My take: If you stopped a process (Ctrl+Z), bg runs it in background.
Common Patterns
Start and Background
./script.sh &
Start and Detach
nohup ./script.sh > output.log 2>&1 &
Stop Gracefully Then Force
kill PID # Try graceful
sleep 5
kill -9 PID # Force if still running
Kill All Instances
killall process-name
# or
pkill process-name
Common Mistakes (I've Made These)
-
Using
kill -9first: Try graceful kill first.kill -9is last resort. -
Killing wrong process: Always check PID.
ps aux | grepto verify. -
Forgetting
&for background: Process blocks terminal. Add&to background. -
Not using nohup: Process dies when terminal closes. Use
nohupfor long-running. -
Killing system processes: Be careful. Don't kill system processes. Check what you're killing.
Real-World Examples
Start Service in Background
nohup nginx > /dev/null 2>&1 &
Stop Stuck Process
ps aux | grep stuck_process
kill PID # Try graceful
kill -9 PID # Force if needed
Restart Process
killall process-name
./process-name &
What's Next?
Now that you can control processes, let's talk about Job Control. We'll cover managing background jobs in detail.
Or practice. Start processes. Stop them. Kill them. Get comfortable.
Personal note: When I started, I'd use
kill -9for everything. Then I learned about graceful termination. Now I trykillfirst,kill -9only if needed. Processes should have a chance to clean up. Be nice to your processes.