Updated: 18 October 2026 · Applies to: procps-ng 4.0.4 (ps, watch) and psmisc 23.6 (pstree) on AlmaLinux 10.2, tested; Ubuntu 26.04 and Debian 13 ship the same procps-ng 4.0.4
ps ("process status") prints a snapshot of the processes running on a Linux or Unix system. ps -ef or ps aux lists them all; the options below filter that list by user, group, PID, terminal or name, show threads and process trees, choose and sort the columns, and show SELinux labels. For the basics (reading ps aux, top and htop) see How to List and Find Running Processes in Linux; to turn a PID into a name or back, see Get a Process Name From a PID in Linux.
ps -fu alice # processes of user alice ps -fG web # processes of group web ps -fp 97,89 # chosen PIDs ps -f --ppid 89 # children of PID 89 ps -C sleep # by command name ps -ft pts/0 # on one terminal ps -ef --forest # as a tree ps -fL -p 97 # threads of PID 97 ps -eo pid,user,etime,args --sort=-rss # your own columns, sorted ps -eZ # SELinux context watch -n 2 'ps -eo pid,%cpu,args --sort=-%cpu | head' # live view
Three option styles. According to the ps manual, ps accepts Unix options (grouped, with a dash: ps -ef), BSD options (grouped, without a dash: ps aux) and GNU long options (two dashes: --sort). That is why both ps -ef and ps aux work.
The output below is a lab example from an AlmaLinux 10.2 test container with systemd as process 1, user alice (UID 1000) and user deploy (UID 1001, member of group web). A real server lists many more processes.
1. Processes of one user
$ ps -fu 1001 UID PID PPID C STIME TTY TIME CMD deploy 97 90 0 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py deploy 100 88 0 09:34 ? 00:00:00 sleep 1002
A user name works too (ps -fu deploy). -u selects by effective user, -U by real user. They differ for setuid programs. Here alice started a setuid copy of sleep, which runs with root rights:
$ ps -o pid,ruser,euser,comm -U alice
PID RUSER EUSER COMMAND
103 alice root suidsleep
104 alice alice sleep
$ ps -o pid,ruser,euser,comm -u alice
PID RUSER EUSER COMMAND
104 alice alice sleep
According to the ps manual, selection options add up, so ps -U root -u root lists every process whose real or effective user is root.
2. Processes of one group
$ ps -o pid,user,rgroup,egroup,comm -G web
PID USER RGROUP EGROUP COMMAND
100 deploy web web sleep
-G selects by real group. -g selects by session or effective group name; ps -fg web found the same process. ps -eo pid,user,group,comm --sort=user lists every process with its user and group.
3. By PID, parent PID or name
$ ps -fp 97,89
UID PID PPID C STIME TTY TIME CMD
root 89 1 0 09:34 ? 00:00:00 bash -c sleep 1003 & sleep 1004 & wait
deploy 97 90 0 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py
$ ps -f --ppid 89
UID PID PPID C STIME TTY TIME CMD
root 98 89 0 09:34 ? 00:00:00 sleep 1003
root 99 89 0 09:34 ? 00:00:00 sleep 1004
$ ps -C sleep,python3 -o pid,user,etime,args | head -4
PID USER ELAPSED COMMAND
91 root 00:06 sleep 1005
94 root 00:06 sleep 900
96 root 00:06 [sleep] <defunct>
-C matches the exact program name. ps -C sleep -o pid= prints only the PIDs, one per line, which is handy in scripts. ps -p PID returns exit code 1 when the process does not exist (tested with a PID that was not in use).
4. By terminal
$ ps -o pid,tty,stat,args -t pts/0
PID TT STAT COMMAND
102 pts/0 Ss+ sleep 1006
Run tty to see the name of your own terminal. A ? in the TTY column means the process has no terminal, which is normal for services.
5. Process tree
$ ps -ef --forest UID PID PPID C STIME TTY TIME CMD root 1 0 0 09:33 ? 00:00:00 /sbin/init root 12 1 0 09:33 ? 00:00:00 /usr/lib/systemd/systemd-journald root 89 1 0 09:34 ? 00:00:00 bash -c sleep 1003 & sleep 1004 & wait root 98 89 0 09:34 ? 00:00:00 \_ sleep 1003 root 99 89 0 09:34 ? 00:00:00 \_ sleep 1004 root 90 1 0 09:34 ? 00:00:00 runuser -u deploy -- python3 /usr/local/bin/worker.py deploy 97 90 0 09:34 ? 00:00:00 \_ python3 /usr/local/bin/worker.py (shortened)
ps axjf is the BSD-style tree with process group and session IDs. pstree -p (package psmisc) draws a compact tree, for the whole system or from one PID, and shows threads in curly brackets:
$ pstree -p 89
bash(89)-+-sleep(98)
`-sleep(99)
$ pstree -p
systemd(1)-+-bash(89)-+-sleep(98)
| `-sleep(99)
(shortened)
|-runuser(90)---python3(97)-+-{python3}(105)
| |-{python3}(106)
| `-{python3}(107)
6. Threads
$ ps -fL -p 97 UID PID PPID LWP C NLWP STIME TTY TIME CMD deploy 97 90 97 0 4 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py deploy 97 90 105 0 4 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py deploy 97 90 106 0 4 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py deploy 97 90 107 0 4 09:34 ? 00:00:00 python3 /usr/local/bin/worker.py
LWP is the thread ID and NLWP the number of threads. ps -T -p 97 shows the same with an SPID column, and ps -o pid,nlwp,args -p 97 just the count. ps -eLf --no-headers | wc -l counts all threads on the system (29 in our container).
7. Choose your own columns with -o
$ ps -o pid,etime=RUNNING_FOR,args -p 97
PID RUNNING_FOR COMMAND
97 00:06 python3 /usr/local/bin/worker.py
$ ps -p 97 -o pid,lstart,etime
PID STARTED ELAPSED
97 Mon Oct 12 09:34:46 2026 00:06
A name after = renames the header; a bare = removes it. Useful columns: pid, ppid, user, group, stat, %cpu, %mem, rss (physical memory in kilobytes), etime (running time), lstart (start time), nlwp, tty, comm (name) and args (full command). ps L lists every column name (190 lines on procps-ng 4.0.4). More on running time in How to Check Execution Time of a Process in Linux.
8. Sort the output
$ ps -eo pid,ppid,user,etime,%cpu,%mem,rss,args --sort=-rss | head -3
PID PPID USER ELAPSED %CPU %MEM RSS COMMAND
1 0 root 00:59 0.1 0.2 11520 /sbin/init
97 90 deploy 00:06 0.1 0.2 9088 python3 /usr/local/bin/worker.py
A minus sign sorts from high to low; several keys are separated by commas, for example --sort=-%cpu,-%mem. --sort=etime puts the newest processes first. For finding heavy processes, see Find Top Running Processes by Highest Memory and CPU Usage in Linux.
9. Process states and zombies
$ ps -e -o stat= | cut -c1 | sort | uniq -c
1 R
26 S
1 Z
$ ps -eo pid,ppid,stat,args | awk '$3 ~ /^Z/'
96 91 Z [sleep] <defunct>
According to the ps manual, R is running or runnable, S sleeping, D uninterruptible sleep (usually disk or network I/O), T stopped and Z a zombie: a process that has ended but has not been reaped by its parent. A zombie goes away when its parent reaps it or exits, so look at the parent (PPID 91 here). Extra letters: s session leader, l multi-threaded, + foreground, < high and N low priority. Processes that stay in D are waiting for I/O, for example a slow disk or network file system.
10. SELinux context
ps -eZ (also -M or --context) adds a LABEL column, and ps -eo label,pid,comm shows it with your own columns. According to Red Hat's SELinux guide, the Apache web server runs as system_u:system_r:httpd_t:s0; the third field (httpd_t) is the domain SELinux uses to confine it. Inside our test container, where SELinux is not visible, every process showed only kernel, so run this on the host itself. More in Understanding SELinux File Labelling and SELinux Context.
11. The status of one process
The kernel keeps a readable status file for every process:
$ grep -E '^(Name|State|Pid|PPid|Uid|Threads|VmRSS)' /proc/97/status Name: python3 State: S (sleeping) Pid: 97 PPid: 90 Uid: 1001 1001 1001 1001 VmRSS: 9088 kB Threads: 4
According to the kernel documentation, the four Uid values are the real, effective, saved set and file system user IDs; for alice's setuid process they were 1000 0 0 0. For the status of a service rather than a process, use systemctl status nginx; see How to List Services and Check Their Status with systemctl.
12. Monitor processes in real time
ps shows a snapshot. To repeat it, wrap it in watch; press Ctrl+C to stop:
watch -n 2 'ps -eo pid,user,%cpu,%mem,args --sort=-%cpu | head -15'
According to the watch manual, the default interval is 2 seconds and -d highlights what changed between updates. For an interactive view, use top or htop.
List processes in Bash
jobs -llists the background jobs of your current shell with their PIDs, for example[1]- 168 Running sleep 100 &.ps -ef | grep sleepalso matches the grep command itself. Useps -ef | grep [s]leeporpgrep -a sleep, which prints PID and command line.- In scripts, prefer
ps -C name -o pid=orpgrepover parsing the full listing.
To stop a process you found, see How to Find and Kill Running Processes in Linux.
Official documentation: ps manual (procps-ng).