Skip to main content

Linux Processes and Services

·1260 words·6 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.
linux-beginner - This article is part of a series.
Part 4: This Article

What is a Process?
#

Every running program on a Linux system is a process. When you type a command, the shell creates a new process to execute it. Each process has:

  • PID — a unique process ID
  • PPID — the parent process ID (the process that started it)
  • Owner — the user who launched it
  • State — running, sleeping, stopped, or zombie
# Every process traces back to PID 1 (systemd/init)
ps -ef | head -5

Viewing Processes
#

ps — Snapshot of Processes
#

# Your processes in the current terminal
ps

# All processes on the system (full format)
ps -ef

# All processes (BSD style, with resource usage)
ps aux

# Filter by name
ps aux | grep nginx

# Show process tree
ps -ef --forest

Reading ps aux output:

USER   PID %CPU %MEM    VSZ   RSS TTY  STAT START  TIME COMMAND
mike  1234  0.5  1.2 123456 12345 pts/0 S  10:30  0:02 vim file.txt
ColumnMeaning
USEROwner
PIDProcess ID
%CPUCPU usage percentage
%MEMMemory usage percentage
VSZVirtual memory size (KB)
RSSResident memory (actually in RAM, KB)
TTYTerminal associated with the process
STATProcess state
STARTStart time
TIMETotal CPU time consumed
COMMANDCommand that started the process

Process states
#

StateMeaning
RRunning
SSleeping (waiting for input/event)
DUninterruptible sleep (usually I/O)
TStopped (suspended)
ZZombie (finished but not cleaned up by parent)

top — Real-Time Process Monitor
#

top

Key commands within top:

KeyAction
qQuit
kKill a process (prompts for PID)
MSort by memory usage
PSort by CPU usage
1Show per-CPU usage
uFilter by user
cToggle full command path

htop — Better Interactive Monitor
#

htop

htop is a more user-friendly alternative to top with color, mouse support, and easier navigation. Install it with your package manager if it’s not available.

pgrep — Find Processes by Name
#

# Get PID of nginx processes
pgrep nginx

# With full command shown
pgrep -a nginx

# By user
pgrep -u mike

Signals and Killing Processes
#

Signals are how you communicate with processes. The most common:

SignalNumberMeaning
SIGHUP1Hangup — often used to reload configuration
SIGINT2Interrupt (same as Ctrl-c)
SIGKILL9Force kill — cannot be caught or ignored
SIGTERM15Graceful termination (default)
SIGSTOP19Pause the process
SIGCONT18Resume a paused process

Sending signals
#

# Graceful stop (default SIGTERM)
kill 1234

# Force kill
kill -9 1234

# Reload configuration
kill -HUP 1234

# Kill by name
killall nginx

# Kill by name (with signal)
pkill -HUP nginx

# Kill all processes by a user
pkill -u baduser

When to use SIGKILL vs SIGTERM
#

Always try SIGTERM (plain kill) first — it lets the process clean up (close files, finish writes, release locks). Only use kill -9 if the process doesn’t respond to SIGTERM, because SIGKILL gives the process no chance to clean up.

Job Control
#

Jobs are processes started from your shell. You can suspend, resume, and move them between foreground and background.

Running in the background
#

# Start a command in the background
long-running-command &

# Check background jobs
jobs

# Bring a background job to the foreground
fg %1

# Send the current foreground job to the background
# First: Ctrl-z (suspends it)
# Then:
bg %1

Practical job control
#

# Start a download in the background
wget https://example.com/bigfile.tar.gz &

# Suspend a running editor (Ctrl-z), do something else, then resume
vim file.txt
# Press Ctrl-z
fg

nohup — Survive Logout
#

Normally, background jobs die when you close the terminal. nohup prevents that:

nohup long-running-script.sh &

Output goes to nohup.out. For more control, use tmux or screen.

Process Priority and niceness
#

Every process has a nice value from -20 (highest priority) to 19 (lowest priority). Default is 0.

# Start a process with low priority
nice -n 10 heavy-computation

# Change priority of a running process
renice 10 -p 1234

# Only root can increase priority (lower nice value)
sudo renice -5 -p 1234

Systemd and Services
#

Most modern Linux distributions use systemd to manage services (background daemons). Services are defined in unit files and managed with systemctl.

Viewing service status
#

# Check if a service is running
systemctl status nginx

# Is it active? (returns 0 or 1)
systemctl is-active nginx

# Is it enabled to start at boot?
systemctl is-enabled nginx

# List all running services
systemctl list-units --type=service --state=running

# List all services (including inactive)
systemctl list-units --type=service --all

Controlling services
#

# Start a service
sudo systemctl start nginx

# Stop a service
sudo systemctl stop nginx

# Restart (stop + start)
sudo systemctl restart nginx

# Reload config without stopping
sudo systemctl reload nginx

# Enable at boot
sudo systemctl enable nginx

# Disable at boot
sudo systemctl disable nginx

# Enable and start in one command
sudo systemctl enable --now nginx

Viewing logs with journalctl
#

Systemd captures output from all services in a structured journal:

# Logs for a specific service
journalctl -u nginx

# Follow logs in real time (like tail -f)
journalctl -u nginx -f

# Logs since last boot
journalctl -b

# Logs since a specific time
journalctl --since "1 hour ago"
journalctl --since "2026-06-09 10:00:00"

# Only errors and above
journalctl -u nginx -p err

# Kernel messages
journalctl -k

Unit file basics
#

Unit files live in /etc/systemd/system/ (custom) or /usr/lib/systemd/system/ (package-provided).

A simple service unit:

[Unit]
Description=My Application
After=network.target

[Service]
Type=simple
User=myapp
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.toml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
# After creating or modifying a unit file
sudo systemctl daemon-reload

# Then start it
sudo systemctl start myapp

Common unit file options
#

OptionMeaning
After=Start after these units
Type=simpleProcess stays in foreground
Type=forkingProcess forks (traditional daemons)
Restart=on-failureRestart if it exits with an error
Restart=alwaysRestart no matter what
RestartSec=5Wait 5 seconds before restarting
User=Run as this user
Environment=Set environment variables
WorkingDirectory=Set working directory

Resource Monitoring
#

Memory usage
#

# System memory overview
free -h

# Detailed per-process memory
ps aux --sort=-%mem | head -10

CPU usage
#

# Per-CPU stats
mpstat

# Top CPU consumers
ps aux --sort=-%cpu | head -10

Disk I/O
#

# Real-time I/O stats
iostat -x 1

# Per-process I/O
iotop

Combined: top/htop shows CPU, memory, and process info in one view.
#

The /proc Filesystem
#

Every running process has a directory in /proc:

# Info about process 1234
ls /proc/1234/

# Command that started the process
cat /proc/1234/cmdline | tr '\0' ' '

# Environment variables
cat /proc/1234/environ | tr '\0' '\n'

# File descriptors (open files)
ls -l /proc/1234/fd/

# Memory maps
cat /proc/1234/maps

System-wide information:

cat /proc/cpuinfo      # CPU details
cat /proc/meminfo      # Memory details
cat /proc/uptime       # System uptime
cat /proc/loadavg      # Load averages

Best Practices
#

  • Use SIGTERM before SIGKILL — always give processes a chance to clean up
  • Use systemctl to manage services, not manual kill commands — systemd handles restarts and dependencies
  • Check journalctl -u servicename first when a service misbehaves — the answer is usually in the logs
  • Use nice for CPU-heavy batch jobs so they don’t starve interactive processes
  • Monitor zombie processes (ps aux | grep Z) — they indicate a parent process isn’t handling child termination
  • Use htop for interactive investigation and ps aux for scriptable output
  • Enable Restart=on-failure in unit files for services that should stay running
  • Avoid nohup for production workloads — write a proper systemd unit file instead
linux-beginner - This article is part of a series.
Part 4: This Article