Linux ps Command Cheat Sheet: 41 Examples for Spotting Suspicious Processes
Last verified: October 13, 2026 (commands tested on procps-ng 4.0.4)
Picture this: it's 3 a.m., and your monitoring flags a production Linux server running hot. CPU is pinned, nobody deployed anything, and the only lead is a process with a boring, believable name. Before you reach for a full endpoint detection and response console, you open a terminal and type a command that has shipped with Linux for decades: ps.
Most people know ps aux and stop there. But in real incident response, the difference between a five-minute triage and a two-hour hunt is often knowing which columns to ask for, how to sort, and how to read a process tree. This guide walks through 41 practical ps examples, grouped by what you're actually trying to do, with notes on what a defender should look for in the output.
Table of Contents
- Why ps Still Matters for SOC Analysts
- Basic Process Listings (Commands 1-6)
- Custom Columns and Sorting (Commands 7-15)
- Filtering by PID, User, Command, and Terminal (Commands 16-21)
- Process States and Parent-Child Trees (Commands 22-27)
- Threads, Counting, and Executable Paths (Commands 28-33)
- Threat Hunting with ps (Commands 34-38)
- Snapshots, Help, and Version (Commands 39-41)
- Detection and Prevention Tips
- Expert Tips
- FAQ
- Conclusion
Why ps Still Matters for SOC Analysts
ps reads process information from the /proc filesystem and prints a snapshot of what is running at that moment. It is installed almost everywhere, needs no agent, and works over a bare SSH session. That matters when you land on a minimal container or a locked-down server where nothing else is installed.
Two things to remember before the commands. First, ps is a snapshot, not a live view. Second, the %cpu column is the process's CPU time divided by how long it has been running, so it is a lifetime average rather than a current reading. A process that just started burning CPU may look quiet, and an old, finished burst may still look heavy. For live behavior, pair ps with top or the watch approach shown in command 35.
Basic Process Listings (Commands 1-6)
# 1. Processes associated with the current terminal
ps
# 2. Full-format listing (UID, PID, PPID, start time, command)
ps -f
# 3. All processes on the system
ps -e
# 4. Same as -e
ps -A
# 5. BSD-style listing with user, CPU, memory, state, command
ps aux
# 6. Processes in a hierarchy
ps -ejH
When to use them: Plain ps only shows your current terminal session, which is rarely what you want during an investigation. Start with ps aux or ps -ef for the full picture. Commands 3 and 4 are interchangeable. Command 6 gives a first look at which process spawned which.
Expected output: A header row followed by one line per process. In ps aux, the STAT column shows the state and COMMAND shows the launch string.
Custom Columns and Sorting for Linux Process Monitoring (Commands 7-15)
# 7. Search for Apache processes (the [a] trick avoids matching grep itself)
ps aux | grep '[a]pache'
# 8. PID and command name
ps -e -o pid,comm
# 9. PID, PPID, user, command
ps -eo pid,ppid,user,comm
# 10. Full command lines
ps -eo pid,user,args
# 11. CPU and memory percentages
ps -eo pid,comm,%cpu,%mem
# 12. Sort by CPU, highest first
ps -eo pid,comm,%cpu --sort=-%cpu
# 13. Sort by memory, highest first
ps -eo pid,comm,%mem --sort=-%mem
# 14. Top 10 CPU consumers (header + 10 rows)
ps -eo pid,comm,%cpu --sort=-%cpu | head -n 11
# 15. Top 10 memory consumers
ps -eo pid,comm,%mem --sort=-%mem | head -n 11
The -o flag is where ps becomes a real investigation tool. Instead of accepting the default columns, you choose exactly what you need. The distinction between comm and args is important for defenders. comm is just the executable name (truncated to 15 characters), while args shows the full command line with its arguments. Arguments are where the interesting details usually live: a remote address, a script path, or a suspicious flag.
The sort syntax --sort=-%cpu uses a minus sign for descending order. Commands 14 and 15 pipe through head -n 11 because the first line is the header, leaving ten process rows.
Filtering by PID, User, Command, and Terminal (Commands 16-21)
# 16. Inspect one process
ps -p 1234 -f
# 17. Inspect several PIDs
ps -p 1234,5678 -f
# 18. Current user's processes
ps -u "$USER" -f
# 19. A specific service account
ps -u www-data -f
# 20. Select by command name
ps -C nginx -f
# 21. Select by terminal
ps -t pts/0 -f
Replace 1234 and 5678 with real PIDs. Command 19 is a favorite for web servers: a service account like www-data should run your web stack and not much else. If you see a shell or an interpreter running under that account, treat it as a lead worth investigating. Note that -u matches the effective user, which is usually what you want.
Process States and Parent-Child Trees (Commands 22-27)
# 22. Show process state
ps -eo pid,stat,comm
# 23. Find zombie processes
ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/'
# 24. Parent-child relationships
ps -eo pid,ppid,comm --forest
# 25. Full-format process tree
ps -ef --forest
# 26. Elapsed runtime
ps -eo pid,etime,comm
# 27. Exact start time
ps -eo pid,lstart,comm
The first letter of the STAT column tells you the state:
| Code | Meaning |
| R | Running or runnable |
| S | Interruptible sleep (waiting for an event) |
| D | Uninterruptible sleep (usually I/O) |
| T | Stopped |
| Z | Zombie (finished, not yet reaped by its parent) |
A zombie is not a running threat. It has already exited and only holds a process table entry. A few are normal, but a growing pile usually means a buggy or hung parent process, so command 23 prints the PPID so you know which parent to examine.
The tree views (commands 24 and 25) are the heart of triage. A web server spawning a shell, or a document-handling service launching an interpreter, is a classic pattern worth escalating. Command 26 shows elapsed time as [[dd-]hh:]mm:ss, and command 27 gives the precise start timestamp, which you can line up with log entries and alert times.
Threads, Counting, and Executable Paths (Commands 28-33)
# 28. Threads, including LWP IDs
ps -eLf
# 29. Count all processes
ps -e --no-headers | wc -l
# 30. Count current user's processes
ps -u "$USER" --no-headers | wc -l
# 31. Executable path plus arguments (exe needs a recent procps-ng)
ps -eo pid,exe,args
# 32. SSH-related processes
ps -eo pid,user,args | grep '[s]shd'
# 33. Python processes
ps -eo pid,user,args | grep '[p]ython'
Counting processes (29 and 30) is a cheap baseline. If a host normally runs a few hundred processes and suddenly shows thousands, something is spawning aggressively.
Command 31 deserves a caution: the exe specifier works on current procps-ng releases (I confirmed it on 4.0.4) but older versions may return an "unknown format specifier" error. Where it works, it is valuable because a process can rewrite its own displayed command line, while the executable path is harder to disguise. Also expect a - for processes you lack permission to inspect, and for kernel threads.
Threat Hunting with ps (Commands 34-38)
# 34. High-CPU processes with ownership, start time, and arguments
ps -eo pid,ppid,user,%cpu,%mem,lstart,args --sort=-%cpu | head -n 15
# 35. Refresh the top-CPU list every 2 seconds
watch -n 2 'ps -eo pid,comm,%cpu,%mem --sort=-%cpu | head -n 11'
# 36. Running or runnable processes
ps -eo pid,stat,comm | awk '$2 ~ /^R/'
# 37. Processes with no controlling terminal
ps -eo pid,tty,stat,comm | awk '$2 == "?"'
# 38. SELinux security contexts (where supported)
ps -eZ
Command 34 is my default first move on a suspicious host. It combines who owns the process, who its parent is, when it started, and exactly what it was launched with, all sorted by CPU. Command 35 turns that into a rolling view for catching short bursts.
Command 37 lists processes without a terminal. Most legitimate daemons fall in this group, so it is noisy by itself. It becomes useful when you compare against a known-good baseline from a clean host of the same role. Command 38 shows SELinux contexts, which helps you confirm a process runs under the confinement you expect.
Snapshots, Help, and Version (Commands 39-41)
# 39. Save a point-in-time listing
ps aux > processes-report.txt
# 40. Extended help
ps --help all
# 41. Show the installed version
ps --version
Saving a snapshot (39) is a good habit at the start of an investigation, before anything is killed or restarted. One warning: command lines can contain passwords, tokens, or API keys passed as arguments. Treat the saved file as sensitive, restrict its permissions, and avoid pasting it into tickets or chat unredacted. Command 40 output varies by procps version, and command 41 tells you which one you have, which explains differences like the exe specifier noted earlier.
Detection and Prevention Tips
Here is what to look for when reading ps output during incident response:
- Odd parent-child chains: a web server, database, or document service spawning an interactive shell or interpreter.
- Unusual launch locations: arguments or executables pointing at
/tmp,/dev/shm, or other world-writable paths. - Name mismatches: a familiar-looking
commthat doesn't match the executable path or arguments. - Unexpected owners: service accounts running things outside their normal role.
- Timing: start times (command 27) that line up with a suspicious login or alert.
To verify a suspect process further, these read-only checks complement ps (replace 1234 with the PID):
ls -l /proc/1234/exe
cat /proc/1234/cmdline | tr '\0' ' '
If the exe link shows (deleted), the binary was removed from disk after launch, which is worth escalating. Do not rely on ps alone: on a compromised host, tools can be replaced or hidden, so corroborate with an EDR platform, auditd logs, and centralized logging. For prevention, run services as least-privileged accounts, restrict execution from temporary directories where feasible (for example with mount options like noexec), and baseline normal process trees per server role. No single control guarantees protection, but layered visibility shortens detection time.
Expert Tips
- Build an alias: save command 34 as a shell alias so your first triage step is one word.
- Know the lifetime-average trap: use
topor command 35 when you need current CPU behavior. - Prefer
argsovercommin investigations, since arguments carry the evidence. - Baseline first: a process list only means something compared against what is normal for that host.
- Snapshot before you act: capture command 39 output before terminating anything.
Related Cybersecurity Topics You Should Explore
- Linux ps Command Cheat Sheet: 41 Examples SOC Analysts Use
- Linux findmnt Command: 43 Examples for Security Audits
- Linux tune2fs Cheat Sheet: 41 Commands, 4 Costly Mistakes
- Linux blkid Command: 41 Examples Every SOC Analyst Should Know
- Linux fsck Command Guide: Fix Disk Errors Without Data Loss
- Linux mkfs Command Cheat Sheet: Format Disks Safely (2026)
- Linux parted Command Cheat Sheet: Partition Disks Safely
- Linux fdisk Command Cheat Sheet: Partition Disks Safely (2026)
FAQ
What is the difference between ps aux and ps -ef?
Both list all processes. ps aux uses BSD-style syntax and shows CPU, memory, and state columns. ps -ef uses UNIX-style syntax and shows UID, PID, PPID, and start time. -ef is handier when you care about parent relationships.
Why does my grep command show up in ps results?
The grep process's own command line contains the search term. Writing grep '[a]pache' avoids this, because the pattern matches "apache" but the grep command line contains "[a]pache".
Can I kill a zombie process?
Not directly, because it has already exited. The parent must reap it. Use the PPID from command 23 to investigate and, if appropriate, restart the parent service.
Is ps enough to detect malware?
No. It is a quick triage tool, not a detection system. Attackers can alter displayed names and arguments, so combine it with EDR, auditd, and log review.
Why is %CPU in ps different from top?
ps reports CPU time over the process's whole lifetime, while top shows recent usage between refreshes.
Do these commands work on macOS?
Many basics like ps aux do, but several options here (such as --forest and --sort) are specific to Linux procps-ng and will not work the same way.
Conclusion
The ps command won't replace a modern security stack, but it is often the fastest way to ask a server, "what are you actually running?" Learn the custom column flags, read process trees instead of flat lists, and always compare against a baseline. Do that, and a vague 3 a.m. alert becomes a focused, defensible investigation. Bookmark this cheat sheet and keep command 34 handy.
Analysis based on SOC monitoring experience and public Linux documentation review.
