Linux Process Management — ps, kill, signal, nohup, and Background Jobs for Servers That Never Stall
> cd .. / HUB_EDITORIALE
Sistemi Operativi & Sicurezza

Linux Process Management — ps, kill, signal, nohup, and Background Jobs for Servers That Never Stall

[2026-07-24] Author: Ing. Calogero Bono
> share
Zenithby Meteora Web The operating system for your business. Social, clients, bookings and invoices in one platform. Gyms, barbers, professionals. Discover Zenith Free demo · no card

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=-%mem to 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

SignalNumberEffect
SIGTERM15Polite termination request. Process can clean up.
SIGKILL9Immediate forced kill. Process cannot ignore it.
SIGHUP1Reload configurations (many daemons support it).
SIGINT2Keyboard interrupt (Ctrl+C).
SIGSTOP19Stops the process (cannot be terminated).
SIGCONT18Resumes a stopped process.

Correct procedure to stop a process

  1. First try SIGTERM: kill -15 PID
  2. If after 5 seconds it hasn't responded, SIGKILL: kill -9 PID
  3. 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 test kill -15 then kill -9.
  • Practice with kill -0 to check if a process is alive.
  • Read man 7 signal for 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 & then jobs and disown %1. Close the terminal, reopen it, and verify the process is still running with ps aux | grep sleep.
  • Install screen or tmux (apt install tmux) and create a persistent session.
  • If you're a developer, use nohup for long deployment scripts: saves you from leaving the terminal open.

What to do now — In summary

  1. Learn to read ps: ps aux --sort=-%cpu is your daily dashboard.
  2. Use the right signals: SIGTERM first, SIGKILL only as last resort.
  3. Background jobs without worries: nohup command & or disown for processes that must survive.
  4. Explore tmux/screen: when an interactive process must stay alive, there's no alternative.
  5. Automate monitoring: write a script that saves ps aux every 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.

> share
Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.

> MW_JOURNAL

> READ_ALL()