Skip to content
Go back

procs vs ps: Modern Process Listing

By SumGuy 10 min read
procs vs ps: Modern Process Listing
Contents

Your ps Output Looks Like an Eye Chart

You type ps aux and get a wall of numbers that all look the same. PID, PPID, RSS, VSZ, columns jammed together, no color, everything the same weight. You squint, scroll up, pipe it to grep, pipe that to awk, squint again.

It’s 2 AM and you’re trying to figure out which process is eating your RAM. ps aux | sort -k 4 -rn | head -20 gets the job done, but “gets the job done” is doing a lot of heavy lifting there. You’re basically writing a shell script just to read your own process table.

procs is what ps would look like if it had been written after humans stopped punching cards. It’s a Rust CLI tool that gives you colored columns, a process tree, Docker container awareness, pager support, and search, without needing a five-step pipeline. Let’s talk about where it fits, where ps still wins, and whether you actually need it.

What procs Is

procs (version 0.14.x as of mid-2026) is a ps replacement written in Rust by dalance. It outputs a table of processes with:

It doesn’t replace every ps use case, if you’re scripting, parsing, or need POSIX compliance, stick with ps. But for interactive use, procs is genuinely better in almost every way.

Installing It

Terminal window
# Arch / CachyOS
pacman -S procs
# Debian/Ubuntu
apt install procs
# macOS
brew install procs
# Cargo (if you want latest)
cargo install procs

Confirm it’s working:

Terminal window
procs --version
# procs 0.14.12

Zero config required out of the box. Just run procs and you get a formatted table with color.

Default Output vs ps aux

Here’s what you get by default, side by side.

With ps aux you see something like:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 169804 13256 ? Ss May15 0:06 /sbin/init
kingpin 4872 1.2 0.8 1234560 68432 pts/0 Sl+ 10:34 0:22 nvim .

All the same visual weight, no way to quickly spot the memory hog at a glance.

With procs you get human-readable memory units (68M instead of 68432), color-coded CPU%, the command truncated intelligently, and the full row is scannable in about half a second. The columns procs shows by default:

ColumnWhat it is
PIDProcess ID
UserOwner
CPUCPU% (color-coded, red when high)
MEMRSS in human units (K/M/G)
VmRSSPhysical RAM in use
CommandFull command with args

Not every ps column is here by default, but everything you actually look at during normal triage is.

Filtering by Name

This is where procs starts pulling ahead for daily use.

Terminal window
# Show only processes matching "nginx"
procs nginx
# Search matches across columns, so a username works too
procs kingpin
# Show a specific PID
procs 4872

No pipes needed. No grep -v grep to filter out your own grep. The search is applied across the whole row, pid, user, command, everything, so procs docker shows Docker daemon processes and any process that happens to mention docker in its command line.

With ps:

Terminal window
ps aux | grep '[n]ginx'

The [n]ginx trick to avoid matching the grep itself is a rite of passage. procs nginx just works.

The Process Tree

pstree is installed on most distros but it’s ugly and hard to read at scale. procs --tree does the same thing with the same formatted columns:

Terminal window
procs --tree

You’ll see the init/systemd at the top, then children indented underneath, with the same color-coded CPU/memory columns on each row. If you’re debugging a process that’s spawning children you didn’t expect, this view makes it obvious in two seconds.

Terminal window
# Tree filtered to just docker-related processes
procs --tree docker

This is genuinely useful when you have a compose stack running and want to see which containerd shim owns which container.

Docker Container Names

If you’re running Docker on the same machine, procs will show the container name next to processes that live inside one. The column is called Docker and it appears automatically when Docker is detected.

Terminal window
procs --sortd Docker

You get something like:

PID User CPU MEM Docker Command
8821 root 0.1 12M my-nginx-container nginx: master process
8834 33 0.0 6M my-nginx-container nginx: worker process
9102 1000 2.3 180M my-app-container node /app/server.js

No more cross-referencing docker ps output with PIDs manually. This one feature alone is worth the install if you run Docker heavily.

Watching Processes in Real Time

procs isn’t top or htop. It doesn’t update automatically by default. But you can do a basic watch:

Terminal window
# Refresh every 1 second (the --watch default)
procs --watch
# Watch with a custom interval in seconds
procs --watch-interval 2

Honestly, for real-time monitoring htop or btop is still better. procs --watch is fine for keeping an eye on one specific thing but it’s not trying to replace the interactive TUI experience. Use it for quick snapshots, not for sitting at a dashboard.

Configuring the Columns

procs reads from ~/.config/procs/config.toml. If the file doesn’t exist it uses defaults, so you only need to create it if you want to customize.

~/.config/procs/config.toml
[[columns]]
kind = "Pid"
style = "BrightYellow"
numeric_search = true
nonnumeric_search = false
[[columns]]
kind = "User"
style = "BrightGreen"
[[columns]]
kind = "CpuTime"
style = "BrightBlue"
[[columns]]
kind = "MemRss"
style = "BrightRed"
color_theme = "ByValue"
[[columns]]
kind = "Docker"
style = "BrightCyan"
[[columns]]
kind = "Command"
style = "White"

Available column kinds include: Pid, PPid, User, Group, CpuTime, MemRss, MemVsz, State, StartTime, Command, Docker, Tcp, Udp, ReadBytes, WriteBytes, and more. The full list is in the project docs.

One useful addition is TCP/UDP ports:

~/.config/procs/config.toml
[[columns]]
kind = "Tcp"
style = "BrightCyan"
[[columns]]
kind = "Udp"
style = "BrightCyan"

Now procs shows which ports each process is listening on, in the same table. You can skip ss -tlnp for quick checks.

Sorting Output

Terminal window
# Sort by memory descending (find the RAM hog)
procs --sortd MemRss
# Sort by CPU descending
procs --sortd CpuTime
# Sort by PID ascending
procs --sorta Pid

procs splits sort direction into two flags: --sortd for descending, --sorta for ascending. The keyword after it is matched partially and case-insensitively against the column name, so --sortd rss works just as well as --sortd MemRss. The default sort is by PID ascending, which is fine for browsing but not for triage. procs --sortd MemRss is what you actually want at 2 AM when something’s eating 12GB of RAM and you don’t know what.

Where ps Still Wins

Here’s the honest part. procs is better for interactive use, but ps is better for a bunch of real-world scenarios.

Shell scripts. If you’re writing a script that parses process output, use ps. It’s POSIX, the output format is predictable, and awk/grep pipelines are reliable. procs output is formatted for humans, column widths change, color codes get injected, and parsing it programmatically is asking for trouble.

Terminal window
# Correct approach in a script: use ps, not procs
PID=$(ps -ef | awk '/nginx/ && !/awk/ {print $2; exit}')

Remote servers without procs installed. ps is always there. procs is not. If you’re SSH-ing into a production box and something’s on fire, you don’t have time to install Rust toolchains.

Specific ps flags with no procs equivalent. ps -p 1234 -o pid,ppid,cmd,lstart gives you the exact columns you need in a specific format. procs doesn’t have that level of per-invocation column control without editing the config file.

BSD systems. procs is primarily Linux. macOS works with Homebrew but you lose some features (Docker detection, some columns). BSD systems may not work at all.

Auditing and compliance contexts. Some tooling expects ps output in a specific format. Don’t try to be clever here.

Practical Aliases That Actually Help

Once you’ve got procs installed, a few aliases make it part of your muscle memory:

~/.zshrc or ~/.bashrc
# Quick memory triage
alias psmem='procs --sortd MemRss'
# Quick CPU triage
alias pscpu='procs --sortd CpuTime'
# Process tree
alias pstree='procs --tree'
# Find by name (same as procs <name>, just more explicit)
alias pg='procs'

The pstree alias replaces the system pstree command for interactive use. If you actually need the real pstree in a script, use the full path /usr/bin/pstree.

A Real Triage Example

You get paged. Something on your self-hosted box is chewing CPU. Here’s the procs workflow:

Terminal window
# Step 1: What's using the most CPU?
procs --sortd CpuTime

You see node /app/server.js sitting at 94% CPU in a container called my-app-container.

Terminal window
# Step 2: What's the tree look like around it?
procs --tree my-app

You see the node process spawned three worker children, all pegged.

Terminal window
# Step 3: Is it holding open ports?
procs --sortd CpuTime my-app

The TCP column shows it’s listening on 3000 and 9229 (that’s the debug port, it’s in debug mode, mystery solved).

Total time: 30 seconds. With ps aux | grep | sort | awk, you’re easily at 3-4 minutes of pipeline archaeology.

Shell Completions

Set these up once and forget about them:

Terminal window
# Zsh
procs --gen-completion-out zsh > ~/.zsh/completions/_procs
# Bash
procs --gen-completion-out bash > ~/.bash_completion.d/procs
# Fish
procs --gen-completion-out fish > ~/.config/fish/completions/procs.fish

Then procs --<tab> will autocomplete flags. Small thing, makes a difference.

Should You Bother?

If you’re the kind of person who already has eza, bat, fd, and ripgrep installed, yes, obviously. procs fits right into that toolbox and you’ll wonder why you ever squinted at raw ps output.

If you’re on a shared server, in a Docker container, writing scripts, or SSHing into random boxes, stick with ps. It’s portable, reliable, and always there.

The rule of thumb: use procs on machines you control, for interactive use. Use ps everywhere else and in any automation.

ps isn’t going away and you don’t need to unlearn it. But when you’re staring at your workstation at 11 PM trying to figure out why Firefox has spawned 47 child processes and one of them is mysteriously eating 4GB of RAM, procs --tree firefox is the tool you want in that moment.

Install it. Alias the common cases. Move on.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Carapace: Universal Shell Completions
Next Post
SOCKS5 Over SSH: Selective Routing Without a VPN

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts