ps, ss & netstat β Processes & Sockets#
ps β Process Status#
Syntax styles#
ps accepts both BSD (ps aux) and POSIX/Unix (ps -ef) style options β donβt mix them.
Most common invocations#
ps aux # all processes, user-friendly (BSD)
ps -ef # all processes, full format (POSIX)
ps -eF # POSIX + extra columns
ps -ely # POSIX + long format (no truncation)
ps axjf # BSD + forest (process tree)
ps -ejH # POSIX + hierarchical tree
Column reference (BSD aux)#
| Column | Meaning |
|---|---|
USER | Process owner |
PID | Process ID |
%CPU | CPU usage % |
%MEM | Memory usage % |
VSZ | Virtual memory size (KB) |
RSS | Resident (physical) memory (KB) |
TTY | Controlling terminal |
STAT | Process state |
START | Start time |
TIME | Cumulative CPU time |
COMMAND | Command + arguments |
Process states (STAT)#
| Code | Meaning |
|---|---|
R | Running or runnable |
S | Sleeping (interruptible) |
D | Uninterruptible sleep (I/O) |
T | Stopped (signal or debugger) |
Z | Zombie (finished, not reaped) |
< | High priority |
N | Low priority |
L | Locked pages in memory |
s | Session leader |
l | Multi-threaded |
+ | Foreground process group |
Filtering and searching#
ps aux | grep nginx # find by name
ps aux | grep -v grep | grep nginx # exclude grep itself
ps -C nginx # by command name (POSIX)
ps -p 1234 # by PID
ps -p 1234,5678 # multiple PIDs
ps -u alice # by user
ps --ppid 1234 # children of PID
# Find PID of a program
pgrep nginx # print matching PIDs
pgrep -l nginx # with process names
pgrep -a nginx # with full command
pgrep -u root nginx # by user + name
Custom output format#
ps -eo pid,ppid,user,%cpu,%mem,vsz,rss,stat,comm
ps -eo pid,user,comm --sort=-%cpu | head -15 # top CPU consumers
ps -eo pid,user,comm --sort=-%mem | head -15 # top memory consumers
ps -eo pid,etime,comm # elapsed time since start
ps -eo pid,lstart,comm # absolute start time
# All threads of a process
ps -T -p 1234
ps -eLf | grep 1234
Process tree#
ps axjf # ASCII art tree (BSD)
ps -ejH # indented tree (POSIX)
pstree # dedicated tool
pstree -p # with PIDs
pstree -u # with usernames
pstree -a # with arguments
Watch processes#
watch -n 1 'ps aux --sort=-%cpu | head -20'
ss β Socket Statistics (modern netstat)#
ss is the modern replacement for netstat β faster, more features, same basic concepts.
Common invocations#
ss -tuln # TCP+UDP listening sockets, numeric (most common)
ss -tulnp # + show process name/PID
ss -ta # all TCP connections
ss -ua # all UDP sockets
ss -x # UNIX domain sockets
ss -s # summary statistics
ss -i # TCP internal info (window, RTT)
Option flags#
| Flag | Meaning |
|---|---|
-t | TCP sockets |
-u | UDP sockets |
-x | UNIX domain sockets |
-l | Listening sockets only |
-a | All sockets (listening + connected) |
-n | Numeric (no DNS/service name resolution) |
-p | Show process (requires root for othersβ processes) |
-e | Extended info (UID, inode) |
-o | Show timer info |
-r | Resolve hostnames |
-4 | IPv4 only |
-6 | IPv6 only |
Filtering with expressions#
ss -tnp state established # established TCP
ss -tnp state time-wait # TIME-WAIT
ss -tnp state listening # listening
ss -tnp '( dport = :80 or sport = :80 )' # port 80
ss -tnp dst 10.0.0.1 # connections to host
ss -tnp src :22 # connections from port 22
ss -tnp dport :\> :1024 # dest port > 1024
TCP states#
ESTABLISHED, SYN-SENT, SYN-RECV, FIN-WAIT-1, FIN-WAIT-2, TIME-WAIT, CLOSE, CLOSE-WAIT, LAST-ACK, LISTEN, CLOSING
ss -t state established '( dport = :443 )' # HTTPS connections
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn # count by state
Whatβs listening on a port#
ss -tlnp | grep :8080
ss -tnlp sport = :443
sudo ss -tlnp | grep '"nginx"' # filter by process name
netstat β Legacy (still common)#
netstat is deprecated on Linux (replaced by ss) but still present on macOS, BSD, and older Linux systems.
netstat -tuln # TCP+UDP listening, numeric (like ss -tuln)
netstat -tunap # all TCP/UDP + process info
netstat -rn # routing table
netstat -i # interface statistics
netstat -s # summary by protocol
netstat -an # all connections, numeric
macOS / BSD netstat differences#
# macOS: -p specifies protocol, not process
netstat -anp tcp # macOS: all TCP (not process info)
netstat -anp udp # macOS: all UDP
# Get process info on macOS
sudo lsof -i :8080 # what's on port 8080
sudo lsof -i tcp # all TCP connections
lsof β List Open Files / Ports#
lsof -i # all network connections
lsof -i :8080 # what's using port 8080
lsof -i tcp # all TCP connections
lsof -i tcp:443 # port 443 specifically
lsof -i @192.168.1.1 # connections to/from IP
lsof -p 1234 # files opened by PID 1234
lsof -u alice # files opened by user
lsof -c nginx # files opened by nginx processes
lsof +D /var/log # files open in /var/log tree
Practical recipes#
# What process is listening on port 80?
sudo ss -tlnp | grep ':80 '
sudo lsof -i :80
# All established connections and their process
sudo ss -tnp state established
# Count connections per remote IP
ss -tn state established | awk '{print $5}' | cut -d: -f1 | \
sort | uniq -c | sort -rn | head -20
# Find zombie processes
ps aux | awk '$8=="Z" {print $2, $11}'
# Kill all processes matching name (safer than killall)
pgrep -x stale-worker | xargs kill -TERM
# Top 10 memory-hungry processes
ps aux --sort=-%mem | awk 'NR<=11 {printf "%-10s %5s %5s %s\n",$1,$3,$4,$11}'
# Watch connection count to port 443
watch -n 2 'ss -tn state established dst :443 | wc -l'
# Find processes with open network connections
sudo lsof -i -n -P | grep ESTABLISHED | awk '{print $1,$9}' | sort -u
[!TIP] On modern Linux, always prefer
ssovernetstat.ssreads directly from the kernelβs netlink socket (/proc/net/tcp) rather than walking/proc, making it significantly faster on systems with many connections.netstatmay not be installed by default.