Linux Process Management
Find, watch and stop processes, ps and top, SIGTERM before SIGKILL, zombie states, load average, and which port a process owns.
What Is a Process?
A process is a running instance of a program. When you open a shell, start a web server, or run a script, Linux creates processes to do that work.
Process management is a core Linux skill because troubleshooting often comes down to answering questions like:
- what is running?
- who started it?
- how much CPU or memory is it using?
- is it stuck?
- how can I stop it safely?
Listing Processes with ps
The ps command shows process snapshots.
ps
ps aux
ps -ef
Commonly used forms:
ps auxshows a broad list with CPU, memory, and command infops -efshows parent-child relationships and full commands in a format many admins like
Example:
ps aux | grep nginx
This helps you see running Nginx processes.
Watching Processes Live with top and htop
top shows a live updating view of system activity.
top
You can inspect CPU usage, memory consumption, load, and the busiest processes.
htop provides a friendlier interactive view if installed.
htop
Many servers do not include htop by default, so you should know top first.
Tip:
topis usually available everywhere, which makes it a dependable first troubleshooting tool.
Stopping Processes with kill
Every process has a PID or process ID. Use kill to send signals to it.
kill 1234
kill -15 1234
kill -9 1234
Common signals:
15orSIGTERM: polite request to stop9orSIGKILL: forceful termination
Prefer SIGTERM first so the process has a chance to clean up.
Note:
SIGKILLcannot be ignored, but it also does not let the process shut down gracefully.
Process Priority with nice and renice
Linux lets you influence scheduling priority with nice values. Lower nice values mean higher priority; higher nice values mean lower priority.
Start a command with a custom nice value:
nice -n 10 backup-script.sh
Change an existing process:
renice 5 -p 1234
This is useful when you want background jobs to be less disruptive to interactive or production workloads.
Jobs, Backgrounding, and Foreground Control
In a shell session, you can manage jobs directly.
Start a process in the background:
long-running-command &
List shell jobs:
jobs
Move a stopped job to the background:
bg %1
Bring a job to the foreground:
fg %1
This is useful during interactive work when you want to keep a task running without blocking your terminal.
Keeping Processes Alive with nohup
Normally, a process tied to your shell may stop when you disconnect. nohup helps keep it alive.
nohup ./sync-data.sh > sync.log 2>&1 &
This is handy for long-running tasks over SSH.
nohup ignores the hangup signal and, combined with &, lets the command continue in the background.
Process States
Linux processes can exist in different states. You may see letters like these in process listings:
R= running or runnableS= sleepingD= uninterruptible sleep, often waiting on I/OT= stoppedZ= zombie
A zombie process has finished execution but still has an entry because its parent has not collected its exit status yet.
A Practical Troubleshooting Example
Suppose an app is slow and users report timeouts.
A simple investigation could be:
top
ps aux | grep myapp
ps -ef | grep myapp
If one backup process is using too much CPU, you might lower its priority:
renice 15 -p 2481
If a worker is frozen and not responding to normal shutdown logic, you might send SIGTERM, then escalate if required:
kill 2481
kill -9 2481
Best Practices
- inspect before killing
- prefer graceful signals first
- use
topto understand the system before acting - background carefully and know which jobs belong to your shell
- use
nohupwhen disconnects would otherwise stop important tasks
Test Your Understanding
Exercise 1: Choosing the first stop signal
Question: When a process is misbehaving, which signal should you normally try before using SIGKILL?
Exercise 1: Choosing the first stop signal
Select the normal graceful signal for asking a process to exit.
Exercise 2: Tracking background jobs
Question: What does the jobs command show?
Exercise 2: Tracking background jobs
Identify what scope of work the jobs command reports.
Exercise 3: Surviving shell disconnects
Scenario: You launch a long sync over SSH and do not want it to die when your terminal closes.
Question: Why is nohup ./sync-data.sh > sync.log 2>&1 & useful here?
Exercise 3: Surviving shell disconnects
Choose what nohup plus backgrounding accomplishes for a long-running command.
Key takeaways
ps auxfor a snapshot,toporhtopto watch. Both answer different questions.killsendsSIGTERM(15) and asks politely;kill -9sendsSIGKILLand gives no chance to clean up.- Always try
SIGTERMfirst.-9skips flushing buffers and releasing locks. - A zombie process is already dead: it is an unreaped exit status, and the fix is the parent, not the zombie.
- A
Dstate process cannot be killed at all; it is blocked in the kernel, usually on I/O. nohuporsetsidoutlive the shell; a plain background job dies with your session.- Find the process on a port with
ss -tlnp, not by guessing at names.
Frequently Asked Questions
What is the difference between kill and kill -9?
Plain kill <pid> sends SIGTERM, a request to shut down that the process can catch, so it can finish writing a file, close connections and release locks. kill -9 sends SIGKILL, which the kernel enforces and the process cannot catch or ignore, so it stops mid-operation with no cleanup. That makes -9 a last resort rather than a default: reaching for it first is how you get corrupt files and stale lock files. Try SIGTERM, wait a few seconds, then escalate.
How do I find which process is using a port?
sudo ss -tlnp | grep :8080 lists listening sockets with the owning process and PID, and is the modern replacement for netstat -tlnp. sudo lsof -i :8080 gives the same answer with more detail about open files. The sudo matters, without it you see the ports but not which process owns them, because that information belongs to other users. Once you have the PID, ps -p <pid> -o pid,user,cmd shows the full command line.
What is a zombie process and how do I kill it?
A zombie has already terminated; what remains is an entry in the process table holding its exit status, waiting for its parent to read it with wait(). You cannot kill it, because there is nothing running. Signals to a zombie do nothing. The fix is the parent: if it is buggy and not reaping children, restart it, at which point the zombies are re-parented to init and cleaned up immediately. A handful of zombies is harmless; thousands means a parent process with a real bug.
Why can't I kill a process even with kill -9?
It is in uninterruptible sleep, shown as state D in ps. The process is blocked inside a kernel call, typically waiting on disk or a hung NFS mount, and signals are not delivered until that call returns. SIGKILL is queued rather than ignored, and takes effect the moment the I/O completes or times out. Fix the underlying cause: check dmesg for storage errors and unmount or remount the stuck filesystem. A reboot is sometimes the only route out.
What is the difference between nohup, disown and screen or tmux?
nohup command & starts a process immune to SIGHUP, so it survives your shell exiting, with output redirected to nohup.out. disown does the same for a job you have already backgrounded. screen and tmux go further by giving the process a persistent terminal you can detach from and reattach to later, which is what you want for anything interactive or long enough that you will need to check on it. For a service that must survive reboots, none of these is right. Write a systemd unit.
What do load averages actually mean?
The three numbers from uptime are the average number of processes runnable or waiting on I/O over the last 1, 5 and 15 minutes. They must be read against your core count: a load of 4.0 saturates a 4-core machine and is comfortable on 16. The trend across the three matters more than any single figure. A first number well above the third means load is climbing. Note that on Linux the figure includes processes blocked on disk, so high load with low CPU usage usually points at I/O rather than compute.