Skip to main content
Blog|
How-to guides

How to list users in Linux

|
Mar 30, 2026|9 min read
HOW-TO GUIDESHow to list users in LinuxHOSTNEYhostney.comMarch 30, 2026

Linux stores user accounts in /etc/passwd . Every user on the system, whether a human who logs in via SSH or a system account that runs a service, has an entry in this file. Listing users means reading this file and filtering it to find what you need. There are several ways to do this depending on whether you want all users, only human users, currently logged-in users, or users with specific privileges.

This guide covers each method with practical examples you can run on any Linux server.

Listing all users from /etc/passwd#

The most direct way to see every user account on the system:

cat /etc/passwd

Each line represents one user. The format is:

username:password:UID:GID:comment:home_directory:shell

For example:

root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
john:x:1001:1001:John Smith:/home/john:/bin/bash

The fields that matter most:

  • username (field 1) – the account name
  • UID (field 3) – the numeric user ID. Root is always 0. System accounts are typically below 1000. Human users start at 1000 on most distributions.
  • home_directory (field 6) – where the user’s files live
  • shell (field 7) – the shell assigned to the user.  /bin/bash  or  /bin/zsh  means the user can log in interactively.  /usr/sbin/nologin  or  /bin/false  means the account cannot log in.

The x in the password field means the actual password hash is stored in /etc/shadow , which is only readable by root.

Extract just the usernames

cut -d: -f1 /etc/passwd

The -d: flag sets the delimiter to colon. The -f1 flag extracts the first field (username). This gives you a clean list of every username on the system, one per line.

Extract usernames with UIDs

awk -F: '{print $1, $3}' /etc/passwd

Output:

root 0
daemon 1
bin 2
www-data 33
john 1001
jane 1002

This is useful for quickly seeing which accounts are system accounts (UID below 1000) and which are human users (UID 1000 and above).

Sort by UID

sort -t: -k3 -n /etc/passwd

This sorts the passwd file by the third field (UID) numerically. System accounts appear first, followed by human users in the order they were created.

Using getent passwd#

getent queries the system’s name service databases, which includes /etc/passwd but also LDAP, NIS, and other directory services if configured. On a server that authenticates against Active Directory or LDAP, cat /etc/passwd only shows local accounts. getent passwd shows all accounts the system knows about.

getent passwd

The output format is identical to /etc/passwd . If your server only uses local authentication (no LDAP, no AD), getent passwd and cat /etc/passwd produce the same results.

Look up a specific user

getent passwd john

This returns the passwd entry for john if the account exists, or nothing if it does not. This is a quick way to check whether a user account exists on the system.

Listing only human users#

A typical Linux server has dozens of system accounts (daemon, nobody, www-data, mysql, postfix, etc.) and only a few human users. Filtering out system accounts makes the user list more useful.

Filter by UID range

On most Linux distributions (RHEL, CentOS, Rocky Linux, Ubuntu, Debian), human users have UIDs starting at 1000. System accounts have UIDs below 1000.

awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd

The $3 >= 1000 condition filters for UIDs at or above 1000. The $3 < 65534 condition excludes the nobody account (which has UID 65534 on most systems).

On older RHEL/CentOS systems, human UIDs started at 500 instead of 1000. Check your system’s /etc/login.defs for the UID_MIN value:

grep UID_MIN /etc/login.defs

Filter by shell

Human users typically have an interactive shell ( /bin/bash , /bin/zsh , /bin/sh ). System accounts have /usr/sbin/nologin or /bin/false . Filtering by shell is another way to find human users:

grep -E '/bin/(bash|zsh|sh)$' /etc/passwd | cut -d: -f1

This finds all accounts with an interactive shell. It is not perfect since some system accounts may have a real shell assigned, but it covers the common case.

Filter by home directory

Human users typically have home directories under /home/ . System accounts have home directories in other locations ( /var/www , /var/lib/mysql , /root ).

awk -F: '$6 ~ /^\/home/ {print $1}' /etc/passwd

This lists users whose home directory starts with /home/ .

Using compgen

compgen -u

This is a Bash built-in that lists all usernames known to the system. The output is a plain list of usernames, one per line. It queries the same sources as getent passwd but only returns the username, not the full passwd entry.

Combining filters

You can combine UID and shell filters for a more precise list of actual human users who can log in:

awk -F: '$3 >= 1000 && $3 < 65534 && $7 !~ /nologin|false/ {print $1, $3, $7}' /etc/passwd

This shows only users with UID 1000+ who have an interactive shell. On a well-configured server, this should match exactly the people who have SSH access to the machine.

Checking user account details#

Full details for a specific user

id john
uid=1001(john) gid=1001(john) groups=1001(john),27(sudo),33(www-data)

Check when a password was last changed

sudo chage -l john

Output:

Last password change                    : Mar 15, 2026
Password expires                        : never
Password inactive                       : never
Account expires                         : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

This is useful for security audits. Accounts with passwords that have not been changed in years, or accounts set to never expire, may need attention.

Check if an account is locked

sudo passwd -S john

Output:

john P 03/15/2026 0 99999 7 -1

The second field indicates the account status: P means the password is set (account is active), L means the account is locked, and NP means no password is set.

Scripting user lists#

Export human users to a file

awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd > /tmp/user-list.txt

Compare users across two servers

If you manage multiple servers and want to verify that user accounts are consistent:

# On server A
awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd | sort > /tmp/users-a.txt

# On server B (run via SSH)
ssh user@server-b "awk -F: '\$3 >= 1000 && \$3 < 65534 {print \$1}' /etc/passwd" | sort > /tmp/users-b.txt

# Compare
diff /tmp/users-a.txt /tmp/users-b.txt

Lines starting with < exist only on server A. Lines starting with > exist only on server B. If both servers should have the same users, any differences need investigation.

Find users who have never logged in

for user in $(awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd); do
    if ! last "$user" | grep -q "pts\|tty"; then
        echo "$user has never logged in"
    fi
done

Accounts that exist but have never been used may be stale accounts from former employees or test accounts that were never cleaned up. These are a security risk because an attacker who discovers the credentials can use them without raising suspicion.

Counting users#

Total accounts

wc -l /etc/passwd

Or more precisely, counting only non-empty lines:

getent passwd | wc -l

Only human users

awk -F: '$3 >= 1000 && $3 < 65534' /etc/passwd | wc -l

On a typical web server, you might have 30-50 total accounts but only 2-5 human users.

Listing currently logged-in users#

These commands show who is connected to the server right now, not who has an account.

who

who

Output:

john     pts/0        2026-03-30 09:15 (10.0.1.50)
jane     pts/1        2026-03-30 10:22 (10.0.1.51)

This shows each logged-in user, their terminal, when they logged in, and where they connected from. Each line is one active session. A user with two SSH sessions open appears twice.

w

w

Output:

 10:45:23 up 42 days,  3:15,  2 users,  load average: 0.12, 0.08, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
john     pts/0    10.0.1.50        09:15    0.00s  0.05s  0.00s w
jane     pts/1    10.0.1.51        10:22    23:10  0.02s  0.02s vim config.php

w shows everything who shows plus the system uptime, load average, idle time for each session, and what command each user is currently running. This is more useful than who for checking whether someone is actively working or has an idle session.

users

users

Output:

john jane

The simplest form. Just the usernames of logged-in users, space-separated on one line. No details about terminals or login times.

Listing recent logins#

last

last

This reads /var/log/wtmp and shows a history of logins and logouts:

john     pts/0        10.0.1.50    Mon Mar 30 09:15   still logged in
jane     pts/1        10.0.1.51    Mon Mar 30 08:00 - 09:30  (01:30)
john     pts/0        10.0.1.50    Sun Mar 29 14:22 - 17:45  (03:23)
reboot   system boot  5.14.0-362   Sat Feb 15 07:30   still running

The reboot entries show when the system was restarted. The time in parentheses shows session duration.

Filter by user

last john

Shows only login history for john .

Failed login attempts

lastb

This reads /var/log/btmp and shows failed login attempts. Requires root. Useful for checking whether someone is trying to brute-force SSH access to the server. If you see hundreds of failed attempts from various IPs, that is normal internet background noise. Fail2ban handles this automatically by banning IPs after repeated failures.

sudo lastb | head -20

Listing users with sudo access#

Knowing which users can run commands as root is important for security auditing.

Check the sudoers file

sudo cat /etc/sudoers

This shows the main sudoers configuration. Look for lines like:

root    ALL=(ALL:ALL) ALL
%sudo   ALL=(ALL:ALL) ALL
%wheel  ALL=(ALL:ALL) ALL

The %sudo and %wheel lines mean any user in the sudo or wheel group has full sudo access. Which group is used depends on the distribution: Ubuntu uses sudo , RHEL/Rocky Linux uses wheel .

List members of the sudo/wheel group

# Ubuntu/Debian
getent group sudo

# RHEL/Rocky Linux/CentOS
getent group wheel

Output:

wheel:x:10:john,jane

This shows that john and jane are in the wheel group and can use sudo .

Check sudoers.d directory

Additional sudo rules can be added in /etc/sudoers.d/ :

sudo ls -la /etc/sudoers.d/

Each file in this directory may grant sudo access to specific users or groups. Check each one to get the complete picture of who has elevated privileges.

On Hostney, SSH access and user permissions are managed through the control panel. Each hosting account has its own isolated environment, so user management is scoped to the account level rather than the server level. For managing database users specifically, see How to show and manage MySQL users.

Listing users in a specific group#

See all groups and their members

cat /etc/group

The format is groupname:password:GID:members . The members field is a comma-separated list of usernames.

List members of a specific group

getent group www-data

Output:

www-data:x:33:john,deploy

List all groups a user belongs to

groups john

Output:

john : john sudo www-data

Or with numeric GIDs:

id john

Output:

uid=1001(john) gid=1001(john) groups=1001(john),27(sudo),33(www-data)

The id command is the most detailed. It shows the user’s UID, primary GID, and all supplementary groups with both names and numeric IDs. This is useful for verifying file permission issues, since file access is determined by the user’s UID and group memberships.

Quick reference#

# All usernames
cut -d: -f1 /etc/passwd

# All users (including LDAP/AD)
getent passwd | cut -d: -f1

# Human users only (UID >= 1000)
awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd

# Check if a user exists
getent passwd username

# Currently logged-in users
who
w

# Login history
last
last username

# Failed login attempts
sudo lastb

# Users with sudo access (Ubuntu)
getent group sudo

# Users with sudo access (RHEL/Rocky)
getent group wheel

# Groups a user belongs to
id username

# Count human users
awk -F: '$3 >= 1000 && $3 < 65534' /etc/passwd | wc -l

Related articles