Every running program is a process with an ID, resource usage, and a state — and knowing how to see what's running, tell what's misbehaving, and stop something safely is exactly what turns 'the server is stuck' from a mystery into a diagnosis.
3 min read
Every time a program runs — a script, a server, a background task — the operating system creates a process for it: a unique numeric PID (process ID), a defined amount of CPU and memory it's using, and a current state (running, sleeping, stopped). A single program can have multiple processes running simultaneously (opening the same app twice, or a server handling many requests via multiple worker processes).
ps (process status) lists currently running processes:
$ ps aux
USER PID %CPU %MEM COMMAND
alice 1234 0.5 2.1 python app.py
alice 1250 15.2 8.4 node server.jsaux here means: a (all users' processes), u (user-friendly detail
format), x (include processes not attached to a terminal). top (or the
more modern, friendlier htop) shows the same kind of information as a
continuously updating live view — genuinely useful for watching CPU and memory
usage change in real time while diagnosing a slow or overloaded system.
kill sends a signal to a process — not necessarily an instant,
forceful termination, despite the name:
$ kill 1234 # SIGTERM (default): ask the process to shut down gracefully
$ kill -9 1234 # SIGKILL: force-terminate immediately, no cleanup allowedSIGTERM (the default, plain kill) is a request — a well-behaved program
can catch it and shut down cleanly (closing open files, finishing an
in-progress database write, releasing locks) before actually exiting.
SIGKILL (kill -9) gives the process no chance to clean up at all — the
operating system terminates it immediately and unconditionally. The practical
rule: try plain kill first, and reach for kill -9 only when a process
genuinely isn't responding to the polite request, since skipping straight to
-9 can leave behind partial writes, locked files, or other cleanup that
never got to run.
A command runs in the foreground by default, occupying your terminal until
it finishes. Appending & runs it in the background, freeing the terminal
for other commands immediately:
$ python long_task.py & # runs in the background, terminal is free immediatelynohup ("no hangup") additionally protects a background process from being
killed automatically when the terminal session itself closes — genuinely
important when starting a long-running process over SSH and then
disconnecting, since without it, closing the SSH connection would kill the
process too:
$ nohup python long_task.py &A server that's "stuck" or unresponsive is a direct, practical use case for
everything in this lesson: ps aux | grep myapp finds the actual process,
top/htop reveals whether it's pegged at 100% CPU or consuming excessive
memory, and kill (or kill -9 if it's truly unresponsive) is how you
actually stop it — turning "something's wrong with the server" into a
specific, diagnosable, and fixable situation, directly applying the systematic
debugging discipline from the Software Engineering Fundamentals domain.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What's the practical difference between plain `kill` and `kill -9`?
2. Why does starting a long-running process over SSH with just `&` risk losing it when you disconnect?
3. What's the practical difference between `ps` and `top`/`htop`?
Linux & the Command Line