Your server just stopped responding. A process is looping, RAM is saturated, and the only way out you know is a full reboot. We've seen it dozens of times: clients losing orders because a nightly job got stuck, developers launching endless scripts and staying glued to the terminal for hours.
We at Meteora Web have been working on Linux servers that need to handle real traffic, automatic backups, and batch processes without ever going down. Process management isn't a luxury for sysadmins — it's daily bread for anyone running a site or an application.
This guide cuts to the chase: how to see what's running (ps), how to stop intelligently (kill and signals), how to run jobs in the background and protect them from disconnection (nohup, bg, fg, jobs). No abstract theory: commands you can copy and test right away.
How to use ps to identify running and zombie processes?
The first step to control a server is knowing what's running. ps is the basic tool, but most misuse produces unreadable output. Let's look at real cases.
ps aux vs ps -ef: which one to use?
ps aux (no dash) is the BSD version, ps -ef is POSIX. Both show all processes for all users. We use ps aux for readability: clear columns USER, PID, %CPU, %MEM, VSZ, RSS, STAT, START, TIME, COMMAND.
Sponsored Protocol
ps aux | head -10
The STAT column is crucial: R (running), S (sleeping), Z (zombie). A zombie process is a terminated child that hasn't been reaped by its parent. If you see more than one, the parent has a bug. Identify it with:
ps aux | grep 'Z'
Then use kill -SIGCHLD on the parent, or if that doesn't work, kill the parent.
Filter by username or command
To see only processes for user www-data:
ps -U www-data u
Or search for a specific process without grep:
pgrep -a nginx # PID plus command
pkill -f "php.*artisan" # kill by pattern
We use pgrep and pkill in monitoring scripts because they're cleaner and avoid false positives from grep itself.
Child processes and tree hierarchy
A process may spawn many children. To see relationships:
ps auxf
Or the full tree:
pstree -p
When a parent dies without reaping children, they become orphans and are adopted by init (PID 1). If you see a process with PPID 1 that shouldn't be there, something went wrong.
What to do now
- Open a terminal and run
ps aux --sort=-%memto see processes consuming the most RAM. - Check for zombies:
ps aux | grep -w Z - Save the output to a file for future comparison:
ps aux > /tmp/process_snapshot.txt
Which signal to send with kill? SIGTERM vs SIGKILL and clean process termination
kill doesn't kill: it sends signals. The difference between a process that exits cleanly and one that leaves temporary files or open sockets lies in the chosen signal.
Sponsored Protocol
Signals you need to know
| Signal | Number | Effect |
|---|---|---|
| SIGTERM | 15 | Polite termination request. Process can clean up. |
| SIGKILL | 9 | Immediate forced kill. Process cannot ignore it. |
| SIGHUP | 1 | Reload configurations (many daemons support it). |
| SIGINT | 2 | Keyboard interrupt (Ctrl+C). |
| SIGSTOP | 19 | Stops the process (cannot be terminated). |
| SIGCONT | 18 | Resumes a stopped process. |
Correct procedure to stop a process
- First try SIGTERM:
kill -15 PID - If after 5 seconds it hasn't responded, SIGKILL:
kill -9 PID - Never use SIGKILL as first option: you risk data corruption.
In automated scripts, we always check if the process exists before killing:
PID=$(pgrep -f "my-long-job")
if [ -n "$PID" ]; then
kill -15 $PID
sleep 5
if kill -0 $PID 2>/dev/null; then
kill -9 $PID
fi
fi
kill -0 doesn't kill, but returns 0 if the process exists. Handy for testing.
Sponsored Protocol
killall and pkill: caution with patterns
killall kills by exact name, pkill by pattern. We prefer pkill -f with caution: it also kills processes whose command contains the string. For example pkill -f php could stop all PHP processes, not just the intended ones.
What to do now
- Find a running process (e.g.,
sleep 9999 &) and testkill -15thenkill -9. - Practice with
kill -0to check if a process is alive. - Read
man 7 signalfor the full list.
How to run a process in the background with nohup, bg, fg, and jobs?
You have a script that must run for hours, but you don't want to keep the terminal open. Or you launched a long command and forgot to put it in the background. Let's look at the solutions.
Run a process in the background directly
./my_script.sh &
The shell returns control immediately. The process runs in the background, but if you close the terminal it receives SIGHUP and dies. To prevent that:
nohup ./my_script.sh &
nohup ignores SIGHUP and redirects output to nohup.out unless otherwise specified.
Bring a process to the background after launching it
You launched ./long_job and now you're stuck? Press Ctrl+Z to suspend it, then:
Sponsored Protocol
bg # restarts it in the background
To bring it back to the foreground:
fg %1
The number after % is the job ID (you see it with jobs).
Jobs: manage multiple background jobs
jobs -l # also shows PIDs
[1]+ Running nohup ./script1.sh &
[2]- Stopped ./script2.sh
The + indicates the current job (the one affected by fg and bg). You can do fg %2 to bring the second one to the foreground.
Disown: detach a job from the terminal
If a job is already in the background and you want it to survive terminal closure, use disown:
./long_job &
disown %1
From that moment, the process becomes an orphan and no longer receives SIGHUP. Alternative: nohup at launch.
Robust alternatives: screen and tmux
nohup and disown are lightweight, but if you need to reconnect to an interactive process (e.g., editor, debugger), multiplexers are the answer:
screen -S myjob
./long_job
# detach with Ctrl+A D
# reattach: screen -r myjob
We use tmux on production servers because it allows multiple sessions and persistence even after a shell crash.
Sponsored Protocol
What to do now
- Run
sleep 300 &thenjobsanddisown %1. Close the terminal, reopen it, and verify the process is still running withps aux | grep sleep. - Install screen or tmux (
apt install tmux) and create a persistent session. - If you're a developer, use
nohupfor long deployment scripts: saves you from leaving the terminal open.
What to do now — In summary
- Learn to read ps:
ps aux --sort=-%cpuis your daily dashboard. - Use the right signals: SIGTERM first, SIGKILL only as last resort.
- Background jobs without worries:
nohup command &ordisownfor processes that must survive. - Explore tmux/screen: when an interactive process must stay alive, there's no alternative.
- Automate monitoring: write a script that saves
ps auxevery hour and checks for zombies (we do it with cron and a Telegram alert).
Process management is the difference between a server that crashes and one that runs for years without reboots. We at Meteora Web have dedicated an entire guide to shell scripting and Linux automation, of which this deep dive is a part. If your server still has zombie processes around, you already have your first step.