Skip to main content
Blog|
How-to guides

How to list running processes in Linux

|
Mar 30, 2026|9 min read
HOW-TO GUIDESHow to list running processesin LinuxHOSTNEYhostney.comMarch 30, 2026

Every program running on a Linux server is a process. Your web server, PHP-FPM, MySQL, SSH sessions, cron jobs, and the kernel itself all run as processes. Knowing how to list, filter, and manage processes is fundamental to server administration. When a site is slow, a server is overloaded, or a service is not responding, the first step is always checking what is running and how much resources it is consuming.

This guide covers the commands you need for listing processes, finding specific ones, checking resource usage, identifying what is using a port, and stopping processes that need to be stopped.

Listing all processes with ps#

ps aux

ps aux

This is the most commonly used form. It shows every process on the system with useful details:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 169612 13456 ?        Ss   Feb15   0:12 /usr/lib/systemd/systemd
root       512  0.0  0.0  16716  5892 ?        Ss   Feb15   0:03 /usr/sbin/sshd -D
www-data  1234  0.2  1.5 452312 124568 ?       S    09:15   0:45 php-fpm: pool www
mysql     1456  1.2  8.3 1842560 678432 ?      Sl   Feb15 142:30 /usr/sbin/mysqld
john      2345  0.0  0.0  21560  5320 pts/0    Ss   10:22   0:00 -bash

The columns:

  • USER – which user owns the process
  • PID – the process ID (used to send signals or kill the process)
  • %CPU – current CPU usage as a percentage
  • %MEM – current memory usage as a percentage of total RAM
  • VSZ – virtual memory size in KB (includes shared libraries, not very useful on its own)
  • RSS – resident set size in KB (actual physical memory the process is using)
  • STAT – process state (S=sleeping, R=running, Z=zombie, D=uninterruptible sleep, T=stopped)
  • START – when the process started
  • TIME – total CPU time consumed
  • COMMAND – the command that started the process

Filter with grep

ps aux outputs every process, which can be hundreds of lines. Pipe to grep to find what you need:

ps aux | grep nginx
root      1100  0.0  0.1  41456  8320 ?        Ss   Feb15   0:00 nginx: master process
www-data  1101  0.0  0.3  42112 24568 ?        S    Feb15   2:15 nginx: worker process
www-data  1102  0.0  0.3  42096 24312 ?        S    Feb15   2:12 nginx: worker process
john      3456  0.0  0.0  12144  1080 pts/0    S+   10:45   0:00 grep nginx

The last line is the grep command itself showing up in the process list. To exclude it:

ps aux | grep [n]ginx

The [n] trick makes the grep pattern different from the literal string “nginx,” so the grep process does not match itself.

List processes for a specific user

ps -u www-data

Shows only processes owned by www-data . Useful for checking how many PHP-FPM workers are running or what a specific user is doing on the server.

ps aux --sort=-%mem | head -20

Sorts by memory usage (descending) and shows the top 20. This is the fastest way to find what is consuming the most RAM.

ps aux --sort=-%cpu | head -20

Same but sorted by CPU usage. Useful when load is high and you need to identify the culprit.

Real-time monitoring with top#

top

top shows a live, updating view of processes sorted by CPU usage by default. It refreshes every 3 seconds.

top - 10:45:23 up 42 days,  3:15,  2 users,  load average: 0.42, 0.35, 0.28
Tasks: 142 total,   1 running, 140 sleeping,   0 stopped,   1 zombie
%Cpu(s):  5.2 us,  1.3 sy,  0.0 ni, 93.2 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7953.5 total,    512.3 free,   5124.8 used,   2316.4 buff/cache
MiB Swap:   2048.0 total,   1892.0 free,    156.0 used.   2548.7 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 1456 mysql     20   0 1842560 678432  32456 S   3.3   8.3 142:30.45 mysqld
 1234 www-data  20   0  452312 124568  12340 S   1.0   1.5   0:45.12 php-fpm

The header shows system-wide stats: uptime, load average, CPU breakdown, and memory usage.

Key commands while top is running:

  • M  – sort by memory usage
  • P  – sort by CPU usage (default)
  • k  – kill a process (prompts for PID)
  • u  – filter by user
  • c  – toggle full command path
  • 1  – show per-CPU core breakdown
  • q  – quit

The load average numbers (0.42, 0.35, 0.28) show the average number of processes waiting for CPU time over the last 1, 5, and 15 minutes. On a 4-core server, a load average of 4.0 means all cores are fully utilized. Above that means processes are waiting for CPU time. A load average consistently above the number of CPU cores indicates the server is overloaded.

The wa (I/O wait) percentage in the CPU line shows how much time the CPU spends waiting for disk I/O. A high wa value (above 10-20%) usually means disk is the bottleneck, not CPU. This is common on servers with slow disks or when MySQL is doing heavy table scans.

htop: a better top#

htop

htop is an improved version of top with color-coded output, visual CPU and memory bars, mouse support, and easier process management. It is not installed by default on most distributions but is available in the standard repositories:

# RHEL/Rocky Linux/CentOS
sudo dnf install htop

# Ubuntu/Debian
sudo apt install htop

htop shows the same information as top but in a more readable format. You can scroll through the process list, search with / , filter with \ , and kill processes with F9 . The tree view ( F5 ) shows parent-child relationships between processes, which is useful for understanding which PHP-FPM workers belong to which pool or which processes were spawned by cron.

Finding specific processes#

pgrep

pgrep nginx

Returns just the PIDs of processes matching “nginx”:

1100
1101
1102

With more detail:

pgrep -a nginx
1100 nginx: master process /usr/sbin/nginx -g daemon on;
1101 nginx: worker process
1102 nginx: worker process

The -a flag shows the full command line alongside the PID.

pgrep by user

pgrep -u www-data

Lists PIDs of all processes owned by www-data .

Count processes

pgrep -c php-fpm

Returns just the count. Useful in scripts to check how many PHP-FPM workers are active:

echo "PHP-FPM workers: $(pgrep -c php-fpm)"

Checking which process uses a port#

When a service will not start because the port is already in use, or when you need to identify what is listening on a specific port:

ss (modern replacement for netstat)

ss -tlnp
State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0       511     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=1100,fd=6))
LISTEN  0       511     0.0.0.0:443         0.0.0.0:*          users:(("nginx",pid=1100,fd=7))
LISTEN  0       128     127.0.0.1:3306      0.0.0.0:*          users:(("mysqld",pid=1456,fd=22))
LISTEN  0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=512,fd=3))

The flags: -t for TCP, -l for listening, -n for numeric (no DNS resolution), -p for process info.

This shows you exactly what is listening on each port. MySQL on 3306, Nginx on 80 and 443, SSH on 22. If you are troubleshooting a 521 error or SSH connection refused, this command tells you immediately whether the service is listening.

Filter by port

ss -tlnp | grep ':443'

Shows only what is listening on port 443.

lsof

sudo lsof -i :80

Shows all processes using port 80, including the process name, PID, user, and connection state. lsof requires root to see processes owned by other users.

sudo lsof -i :3306

Shows what is connected to MySQL. Useful for diagnosing too many connections issues.

Listing services with systemctl#

Modern Linux distributions use systemd to manage services. systemctl lists and controls them.

List all running services

systemctl list-units --type=service --state=running
UNIT                     LOAD   ACTIVE SUB     DESCRIPTION
crond.service            loaded active running Command Scheduler
mysqld.service           loaded active running MySQL Server
nginx.service            loaded active running The nginx HTTP and reverse proxy server
php-fpm.service          loaded active running The PHP FastCGI Process Manager
sshd.service             loaded active running OpenSSH server daemon

This shows only services that are currently running. It is a cleaner view than ps aux when you want to see which services are active.

List all services (including stopped)

systemctl list-units --type=service --all

Check a specific service

systemctl status nginx

This shows whether the service is running, its PID, memory usage, recent log entries, and how long it has been running. This is usually the first command to run when investigating a service issue.

List services that start on boot

systemctl list-unit-files --type=service --state=enabled

Shows which services are configured to start automatically when the server boots. If a service should be running but is not, check if it is enabled here. For restarting services and the server itself, see How to restart Linux: command line reference.

Killing processes#

kill by PID

kill 1234

Sends SIGTERM (signal 15) to process 1234, asking it to shut down gracefully. The process can catch this signal and clean up before exiting. Most well-behaved processes exit within a few seconds.

If the process does not respond to SIGTERM:

kill -9 1234

Sends SIGKILL (signal 9), which terminates the process immediately. The process cannot catch or ignore this signal. Use this only when SIGTERM does not work, because SIGKILL does not give the process a chance to clean up (close files, release locks, flush buffers).

Kill by name

pkill php-fpm

Sends SIGTERM to all processes matching “php-fpm.” Be careful with this because it matches partial names. pkill php would kill any process with “php” in its name.

Kill all processes by a user

pkill -u john

Sends SIGTERM to every process owned by john . This is the equivalent of logging the user out forcefully.

Kill a process using a specific port

sudo fuser -k 80/tcp

Kills whatever is listening on port 80. Useful when a port is stuck and you need to free it for another service.

Common troubleshooting scenarios#

Server is slow, what is using CPU?

ps aux --sort=-%cpu | head -10

Or open top and press P to sort by CPU. Look for processes with high %CPU that should not be there. Common culprits: a PHP process stuck in an infinite loop, a MySQL query doing a full table scan, or a backup process running during peak hours.

Server is running out of memory

ps aux --sort=-%mem | head -10

Or open top and press M to sort by memory. Check the RSS column for actual memory usage. MySQL and PHP-FPM are typically the largest memory consumers on a web server. If PHP-FPM workers are consuming too much memory individually, check for memory leaks in WordPress plugins.

A service is not running

systemctl status nginx

If the service is “inactive (dead)” or “failed,” check the logs:

journalctl -u nginx --no-pager -n 50

This shows the last 50 log entries for the service, which usually includes the error that caused it to stop.

Zombie processes

Zombie processes (state Z in ps output) are processes that have finished executing but their parent has not collected their exit status. A few zombies are normal and harmless. Hundreds of zombies indicate a bug in the parent process.

ps aux | grep ' Z '

Zombies cannot be killed with kill because they are already dead. The fix is to restart the parent process, which clears the zombie entries.

Running process checks over SSH#

You can run any of these commands on a remote server without opening an interactive session:

ssh user@server "ps aux --sort=-%cpu | head -10"
ssh user@server "systemctl status nginx"
ssh user@server "ss -tlnp"

This is useful for quick checks across multiple servers. See How to run commands over SSH for more patterns.

Quick reference#

# All processes
ps aux

# Sort by CPU usage
ps aux --sort=-%cpu | head -20

# Sort by memory usage
ps aux --sort=-%mem | head -20

# Filter by name
ps aux | grep [n]ginx

# Filter by user
ps -u www-data

# Real-time monitoring
top
htop

# Find PIDs by name
pgrep nginx
pgrep -a nginx    # with full command
pgrep -c php-fpm  # count only

# Check what is listening on ports
ss -tlnp
ss -tlnp | grep ':443'
sudo lsof -i :80

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

# Check a specific service
systemctl status nginx

# Kill by PID
kill PID        # graceful
kill -9 PID     # force

# Kill by name
pkill process-name

# Kill by port
sudo fuser -k 80/tcp