w command displays information about currently logged-in users and what they are doing. It shows uptime, load averages, user sessions, login times, idle time, and current processes - providing a comprehensive snapshot of system activity.
Show comprehensive information about all current users:
w
Sample Output:
15:30:42 up 5 days, 3:25, 3 users, load average: 0.15, 0.20, 0.18 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT john pts/0 192.168.1.100 14:20 0.00s 0.12s 0.01s vim document.txt jane pts/1 192.168.1.101 15:15 5:00 0.05s 0.05s -bash root tty1 - 09:30 45:20 2.50s 0.01s top
Header Information:
Column Meanings:
Show only user information, omit the uptime header:
w -h
Sample Output:
john pts/0 192.168.1.100 14:20 0.00s 0.12s 0.01s vim document.txt jane pts/1 192.168.1.101 15:15 5:00 0.05s 0.05s -bash root tty1 - 09:30 45:20 2.50s 0.01s top
When to use:
Example script usage:
#!/bin/bash
# Count logged-in users
USER_COUNT=$(w -h | wc -l)
echo "Currently logged in: $USER_COUNT users"
# List usernames only
w -h | awk '{print $1}' | sort -u
Display information for a particular user:
w john
Sample Output:
15:30:42 up 5 days, 3:25, 3 users, load average: 0.15, 0.20, 0.18 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT john pts/0 192.168.1.100 14:20 0.00s 0.12s 0.01s vim document.txt john pts/2 192.168.1.100 15:00 2:15 0.08s 0.03s ssh server.com
Use cases:
Check for multiple sessions:
# Count user's sessions w -h john | wc -l # See all activities w -h john
Display abbreviated output without login time, JCPU, or PCPU:
w -s
Sample Output:
15:30:42 up 5 days, 3:25, 3 users, load average: 0.15, 0.20, 0.18 USER TTY FROM IDLE WHAT john pts/0 192.168.1.100 0.00s vim document.txt jane pts/1 192.168.1.101 5:00 -bash root tty1 - 45:20 top
Benefits:
Alternative short display:
# Even more compact - username and process only
w -h -s | awk '{print $1, $NF}'
Omit the hostname/IP information:
w -f
Sample Output:
15:30:42 up 5 days, 3:25, 3 users, load average: 0.15, 0.20, 0.18 USER TTY LOGIN@ IDLE JCPU PCPU WHAT john pts/0 14:20 0.00s 0.12s 0.01s vim document.txt jane pts/1 15:15 5:00 0.05s 0.05s -bash root tty1 09:30 45:20 2.50s 0.01s top
Use when:
Continuously watch user logins and activity:
watch -n 5 'w -h'
What it does: Updates every 5 seconds, showing current user activity. Press Ctrl+C to stop.
More sophisticated monitoring script:
#!/bin/bash
# user-monitor.sh - Monitor user logins with alerts
ALERT_EMAIL="admin@example.com"
PREVIOUS_USERS=""
while true; do
CURRENT_USERS=$(w -h | awk '{print $1}' | sort -u | tr '\n' ' ')
# Check for new logins
for user in $CURRENT_USERS; do
if ! echo "$PREVIOUS_USERS" | grep -q "$user"; then
echo "[$(date)] NEW LOGIN: $user"
# Get login details
w -h | grep "^$user" | while read line; do
echo " Details: $line"
done
# Optional: Send email alert
# echo "New login: $user" | mail -s "Login Alert" $ALERT_EMAIL
fi
done
# Check for logouts
for user in $PREVIOUS_USERS; do
if ! echo "$CURRENT_USERS" | grep -q "$user"; then
echo "[$(date)] LOGOUT: $user"
fi
done
PREVIOUS_USERS="$CURRENT_USERS"
sleep 10
done
Usage:
bash user-monitor.sh
Understand the differences between related commands:
whoami - Shows current user:
whoami # Output: john
who - Shows logged-in users (simple):
who # Output: # john pts/0 2026-01-25 14:20 (192.168.1.100) # jane pts/1 2026-01-25 15:15 (192.168.1.101)
w - Shows users and their activity (detailed):
w # Output: Full information including processes and CPU time
Comparison table:
| Command | Shows | Detail Level | Use Case |
|---|---|---|---|
whoami |
Current user | Minimal | Identify yourself |
who |
All logged-in users | Basic | See who's logged in |
w |
Users + activity | Comprehensive | Monitor system usage |
Monitor for unusual user activity patterns:
#!/bin/bash
# security-audit-w.sh - Detect suspicious user activity
REPORT="/tmp/security_audit_w_$(date +%Y%m%d).txt"
echo "User Activity Security Audit - $(date)" > $REPORT
echo "========================================" >> $REPORT
echo "" >> $REPORT
# 1. Check for users logged in from unexpected locations
echo "=== Remote Logins ===" >> $REPORT
w -h | grep -v "^root" | grep -v "\-$" | \
awk '{print $1, $3}' >> $REPORT || echo "None" >> $REPORT
echo "" >> $REPORT
# 2. Find idle sessions (potential security risk)
echo "=== Idle Sessions (>30 minutes) ===" >> $REPORT
w -h | awk '$5 ~ /[0-9]+:[0-9]+/ {
split($5, time, ":");
if (time[1] >= 30 || length($5) > 5) print $0
}' >> $REPORT || echo "None" >> $REPORT
echo "" >> $REPORT
# 3. Root logins (should be monitored)
echo "=== Root User Activity ===" >> $REPORT
w -h root >> $REPORT 2>/dev/null || echo "No root sessions" >> $REPORT
echo "" >> $REPORT
# 4. Multiple sessions from same user
echo "=== Users with Multiple Sessions ===" >> $REPORT
w -h | awk '{print $1}' | sort | uniq -c | awk '$1>1 {print $0}' \
>> $REPORT || echo "None" >> $REPORT
echo "" >> $REPORT
# 5. Unusual processes
echo "=== Potentially Suspicious Processes ===" >> $REPORT
w -h | grep -E "(nc|netcat|ncat|/bin/sh|/bin/bash)" | \
grep -v "^root" >> $REPORT || echo "None" >> $REPORT
echo "" >> $REPORT
# 6. After-hours logins (assuming 9-5 workday)
HOUR=$(date +%H)
if [ $HOUR -lt 9 ] || [ $HOUR -gt 17 ]; then
echo "=== After-Hours Activity (Current time: $HOUR:00) ===" >> $REPORT
w -h >> $REPORT
echo "" >> $REPORT
fi
echo "Audit complete: $REPORT"
cat $REPORT
Run regularly:
# Add to crontab to run every hour 0 * * * * /path/to/security-audit-w.sh
Create detailed activity report for management or audit:
#!/bin/bash
# user-activity-report.sh - Generate comprehensive user activity report
REPORT_FILE="/tmp/user_activity_report_$(date +%Y%m%d_%H%M).txt"
generate_report() {
echo "======================================"
echo "USER ACTIVITY REPORT"
echo "======================================"
echo "Generated: $(date)"
echo "Hostname: $(hostname)"
echo ""
echo "SYSTEM STATUS"
echo "--------------------------------------"
w | head -1
echo ""
echo "CURRENTLY LOGGED IN USERS"
echo "--------------------------------------"
TOTAL_USERS=$(w -h | wc -l)
echo "Total Active Sessions: $TOTAL_USERS"
echo ""
echo "USER DETAILS"
echo "--------------------------------------"
w -h | while read line; do
USER=$(echo $line | awk '{print $1}')
TTY=$(echo $line | awk '{print $2}')
FROM=$(echo $line | awk '{print $3}')
LOGIN=$(echo $line | awk '{print $4}')
IDLE=$(echo $line | awk '{print $5}')
WHAT=$(echo $line | awk '{for(i=8;i<=NF;i++) printf $i" "; print ""}')
echo "User: $USER"
echo " Terminal: $TTY"
echo " From: $FROM"
echo " Logged in at: $LOGIN"
echo " Idle time: $IDLE"
echo " Current activity: $WHAT"
echo ""
done
echo "UNIQUE USERS"
echo "--------------------------------------"
w -h | awk '{print $1}' | sort -u | while read user; do
SESSIONS=$(w -h $user | wc -l)
echo "$user: $SESSIONS session(s)"
done
echo ""
echo "REMOTE CONNECTIONS"
echo "--------------------------------------"
w -h | grep -v "\-$" | awk '{print $3}' | sort -u | while read ip; do
if [ "$ip" != "-" ]; then
USERS=$(w -h | grep "$ip" | awk '{print $1}' | sort -u | tr '\n' ', ')
echo "From $ip: $USERS"
fi
done
echo ""
echo "ACTIVITY SUMMARY"
echo "--------------------------------------"
echo "Total unique users: $(w -h | awk '{print $1}' | sort -u | wc -l)"
echo "Remote connections: $(w -h | grep -v "\-$" | grep -v "^USER" | wc -l)"
echo "Local connections: $(w -h | grep "\-$" | wc -l)"
echo ""
echo "======================================"
echo "END OF REPORT"
echo "======================================"
}
# Generate report
generate_report | tee $REPORT_FILE
echo ""
echo "Report saved to: $REPORT_FILE"
Usage:
bash user-activity-report.sh
Create real-time monitoring dashboard:
#!/bin/bash
# user-dashboard.sh - Real-time user activity dashboard
# Colors for terminal
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_header() {
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}"
}
while true; do
clear
print_header "USER ACTIVITY DASHBOARD - $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# System info from w header
echo -e "${GREEN}SYSTEM STATUS:${NC}"
w | head -1
echo ""
# Active users count
ACTIVE=$(w -h | wc -l)
UNIQUE=$(w -h | awk '{print $1}' | sort -u | wc -l)
echo -e "${GREEN}ACTIVE SESSIONS:${NC} $ACTIVE ${GREEN}UNIQUE USERS:${NC} $UNIQUE"
echo ""
# User activity table
echo -e "${GREEN}CURRENT ACTIVITY:${NC}"
printf "%-12s %-10s %-18s %-8s %-s\n" "USER" "TERMINAL" "FROM" "IDLE" "COMMAND"
echo "----------------------------------------------------------------------"
w -h | while read line; do
USER=$(echo $line | awk '{print $1}')
TTY=$(echo $line | awk '{print $2}')
FROM=$(echo $line | awk '{print $3}')
IDLE=$(echo $line | awk '{print $5}')
WHAT=$(echo $line | awk '{for(i=8;<=NF;i++) printf $i" "; print ""}' | cut -c1-30)
# Highlight root in red
if [ "$USER" = "root" ]; then
echo -e "${RED}$(printf "%-12s %-10s %-18s %-8s %-s" $USER $TTY $FROM $IDLE "$WHAT")${NC}"
else
printf "%-12s %-10s %-18s %-8s %-s\n" $USER $TTY $FROM $IDLE "$WHAT"
fi
done
echo ""
# Idle session warnings
echo -e "${YELLOW}IDLE SESSIONS (>30 min):${NC}"
IDLE_COUNT=0
w -h | while read line; do
IDLE=$(echo $line | awk '{print $5}')
if echo "$IDLE" | grep -q ":"; then
MINS=$(echo $IDLE | cut -d: -f1)
if [ "$MINS" -ge 30 ]; then
USER=$(echo $line | awk '{print $1}')
echo " - $USER idle for $IDLE"
IDLE_COUNT=$((IDLE_COUNT + 1))
fi
fi
done
if [ $IDLE_COUNT -eq 0 ]; then
echo " None"
fi
echo ""
# Remote connections
echo -e "${GREEN}REMOTE CONNECTIONS:${NC}"
REMOTE=$(w -h | grep -v "\-$" | wc -l)
if [ $REMOTE -gt 0 ]; then
w -h | grep -v "\-$" | awk '{print " -", $1, "from", $3}'
else
echo " None"
fi
echo ""
echo "Refreshing in 5 seconds... (Press Ctrl+C to exit)"
sleep 5
done
Usage:
bash user-dashboard.sh
Features color-coded output, automatic refresh, and highlights important information like root sessions and idle users.
| Option | Description | Example |
|---|---|---|
-h |
Don't print header (uptime info) | w -h |
-s |
Short format (omit login time, JCPU, PCPU) | w -s |
-f |
Don't print FROM field | w -f |
-i |
Show IP address instead of hostname | w -i |
-o |
Old style output (blank IDLE less than 1 minute) | w -o |
-u |
Ignore username when computing CPU times | w -u |
user |
Show info for specific user only | w john |
| Format | Meaning | Example |
|---|---|---|
| 0.00s | Active (less than 1 second idle) | Currently typing/working |
| 5.00s | 5 seconds idle | Brief pause |
| 2:15 | 2 minutes 15 seconds idle | Temporarily away |
| 1:30m | 1 hour 30 minutes idle | Long absence |
| 2days | 2 days idle | Abandoned session |
| TTY | Type | Description |
|---|---|---|
| tty1-tty6 | Physical console | Local terminal (Alt+F1 through Alt+F6) |
| pts/0 | Pseudo-terminal | SSH session or terminal emulator |
| :0 | X display | Graphical desktop session |
Load average shows system load over 1, 5, and 15 minutes:
Rule of thumb: Load average should be less than number of CPU cores for responsive system.
# How many users logged in?
w -h | wc -l
# Is specific user logged in?
w john
# What is root doing?
w root
# Get just usernames
w -h | awk '{print $1}' | sort -u
# Check for remote logins w -h | grep -v "\-$" # Find idle sessions w -h | awk '$5 ~ /[0-9]+:[0-9]+/' # Monitor in real-time watch -n 2 w
# Before system maintenance w # See who's logged in # Send message to all users wall "System maintenance in 10 minutes" # Check load before starting heavy task w | head -1
| Task | Command |
|---|---|
| Show all users | w |
| Without header | w -h |
| Short format | w -s |
| Specific user | w john |
| Count users | w -h | wc -l |
| List usernames | w -h | awk '{print $1}' |
| Monitor continuously | watch w |
who - Simpler user listingwhoami - Show current userusers - List logged-in usernameslast - Login historyuptime - System uptime and load