To list all users on Linux, run getent passwd | cut -d: -f1. It prints every account the system knows, one name per line. Most of them are system accounts that services run under. The human accounts are the ones with a user ID (UID) of 1000 or higher, and awk filters those out of /etc/passwd:
# every account
getent passwd | cut -d: -f1
# only accounts created for people (UID 1000 and up, without "nobody")
awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd
# groups, and the groups of one user
getent group | cut -d: -f1
id alice
# who is logged in right now
whoThese work the same on Ubuntu, Debian, Rocky Linux and Alma. The sections below explain what the fields mean, how to see who can actually log in, who has sudo, who logged in recently, and how to check a server for accounts that should not be there.
What do the seven fields in /etc/passwd mean?
Each line of /etc/passwd is one account, with seven fields separated by colons:
alice:x:1000:1000:Alice Example,,,:/home/alice:/bin/bash- alice — the login name.
- x — the password field.
xmeans the password hash lives in/etc/shadow, which only root can read. The passwd file itself is readable by everyone, and has been for decades. - 1000 — the UID, the number the kernel actually uses. UID 0 is root, whatever the name says.
- 1000 — the GID of the primary group.
- Alice Example,,, — the comment field (GECOS): a full name and optional contact details.
- /home/alice — the home directory.
- /bin/bash — the login shell.
/usr/sbin/nologinor/bin/falsemeans the account cannot get a shell.
getent passwd reads the same data, plus accounts from LDAP or Active Directory if the server is joined to one. cat /etc/passwd shows only local accounts. On a stand-alone VPS the two print the same list.
Which accounts are system accounts and which are people?
The UID tells them apart. Debian, Ubuntu, Rocky and Alma all reserve the low numbers for the system and start human accounts at 1000:
- 0 — root.
- 1–999 — system accounts:
daemon,www-data(ornginxandapacheon Rocky),mysql,sshdand whatever packages add. Services run under them; nobody logs in as them. - 1000 and up — accounts created with
adduseroruseraddfor people. - 65534 —
nobody, a placeholder with no rights, which is why the filter above stops below it.
The boundaries are set in /etc/login.defs as UID_MIN and UID_MAX. If someone changed them, read the value instead of assuming 1000:
awk -F: -v min="$(awk '/^UID_MIN/ {print $2}' /etc/login.defs)" \
'$3>=min && $3<65534 {print $1, $3, $6}' /etc/passwdWhich users can actually log in?
An account can open a shell if its shell is a real one, not nologin or false. This lists those accounts with their shell:
getent passwd | awk -F: '$7 !~ /(nologin|false)$/ {print $1, $7}'On Debian and Ubuntu, sync shows up with /bin/sync as its shell. That is normal: the “shell” only flushes the disks and exits. Everything else on the list deserves a second look.
The shell is only half the picture. Whether someone can log in with a password depends on the password status, and SSH keys bypass the password entirely:
sudo passwd -S -a # P = usable password, L = locked, NP = no password
sudo passwd -S alice # one account; works on Rocky and Alma tooA locked password (L) stops password logins. It does not necessarily stop a login with an SSH key, so check the keys as well, as described below.
How do I list groups and their members?
getent group # every group: name:x:GID:members
getent group sudo # one group and its members
id alice # alice's UID, primary group and all other groups
groups alice # just the group names
# only groups that list members
getent group | awk -F: '$4 != "" {print $1": "$4}'One detail catches people out. The member list in /etc/group only contains users who were added to a group. A user’s primary group, the GID in /etc/passwd, is not repeated there. So getent group alice usually shows no members even though alice is in it. id alice always shows the full set, primary group included.
Who has sudo rights on this server?
On Debian and Ubuntu, sudo rights normally come from membership in the sudo group; on Rocky and Alma it is the wheel group. Rules can also be written directly into /etc/sudoers or a file in /etc/sudoers.d/, so check both:
getent group sudo # Debian, Ubuntu
getent group wheel # Rocky, Alma
sudo grep -rE '^[^#[:space:]]' /etc/sudoers /etc/sudoers.d/ # every active rule
sudo -l -U alice # what alice may run, as sudo sees itA line such as %sudo ALL=(ALL:ALL) ALL gives the whole group full rights; a line that starts with a user name gives rights to that user alone, and NOPASSWD means without asking for a password. Defaults lines are settings, not rights, and the root ALL=(ALL:ALL) ALL line is part of the stock file. To give an account sudo rights properly, see creating a sudo user. If the server does not even have the command, start with sudo: command not found.
Who is logged in right now?
who # who is logged in, on which terminal, from which IP
w # the same plus idle time and what each session is running
users # just the names, on one line
loginctl list-sessions # systemd's view, including sessions without a terminalA remote session shows the client’s IP address in brackets in who, or in the FROM column of w. If you see an address you do not recognise, note it before you do anything else.
Who logged in recently?
last -n 20 # the last 20 logins, with source IP and duration
last alice # one user's logins
last reboot # when the server restarted
sudo lastb -n 20 # failed login attempts (root only)
lastlog # each account's most recent login
lastlog -u alicelast reads /var/log/wtmp, lastb reads /var/log/btmp and lastlog reads /var/log/lastlog. In the lastlog output, “**Never logged in**” next to a system account is what you want to see.
# the unit is called ssh on Debian and Ubuntu, sshd on Rocky and Alma
sudo journalctl -u ssh -u sshd --since "7 days ago" | grep -E 'Accepted|Failed password|Invalid user'Accepted publickey for alice from 198.51.100.7 is a successful key login. Hundreds of Invalid user lines from addresses you do not know are bots guessing, which every server on the internet sees; they matter only if one of them is followed by an Accepted.
Which accounts can log in with an SSH key?
Every key in an account’s ~/.ssh/authorized_keys is a way in that no password change closes. This lists the keys of every account, root included, with the comment at the end of each key line, which is often the owner’s name or machine:
sudo sh -c 'getent passwd | while IFS=: read -r user _ _ _ _ home _; do
for f in "$home/.ssh/authorized_keys" "$home/.ssh/authorized_keys2"; do
[ -f "$f" ] && echo "== $user: $f" && cat "$f"
done
done'
# where sshd actually looks (it can be configured elsewhere)
sudo sshd -T | grep -i authorizedkeysfileAny key you cannot attribute to a person or a deployment tool should go. How to run SSH on keys only, and limit who may log in at all, is in securing SSH access.
How do I spot an account that should not be there?
After a break-in, attackers like to leave a way back: a new account, a second account with UID 0, or a key added to root. These checks take a minute:
# any account with UID 0 other than root is a backdoor
awk -F: '$3==0 {print $1}' /etc/passwd
# accounts with an empty password field
sudo awk -F: '$2=="" {print $1}' /etc/shadow
# human accounts and their shells
awk -F: '$3>=1000 && $3<65534 {print $1, $7}' /etc/passwd
# when the account files last changed
ls -l --time-style=long-iso /etc/passwd /etc/shadow /etc/group /etc/sudoers
# accounts created or changed recently, if the journal goes back far enough
sudo journalctl -t useradd -t usermod -t groupadd --since "30 days ago"What counts as unexpected depends on what the server started with, so save the list on a new server (getent passwd > ~/accounts-day1.txt) and compare it later with diff. Any human account you did not create yourself is worth a closer look. An unknown account often comes together with a process you do not recognise eating the CPU; the cryptominer section of our high-CPU guide shows what to look for and why rebuilding beats cleaning up.
Is there a shorter way in bash?
Yes. compgen is a bash built-in that completes names, and it can list users and groups directly. It is handy for a quick look, but it only prints names, and it does not exist in sh or zsh:
compgen -u # all users
compgen -g # all groups
getent passwd | wc -l # how many accounts there areHow do I list users on Windows Server?
Windows keeps local accounts in its own database, and the equivalents are short:
net user # all local accounts
net user alice # details, last logon, group memberships
net localgroup administrators # who has admin rights
net localgroup "Remote Desktop Users" # who may log in over RDP
quser # who is logged in right nowGet-LocalUser | Format-Table Name, Enabled, LastLogon
Get-LocalGroupMember -Group AdministratorsIf you are cleaning up after a suspicious login, look at the enabled accounts in Administrators and Remote Desktop Users first; those are the ones that can get a desktop on the server.
Every command on this page works on any Linux VPS where you have root, from a throwaway test box to a Standard KVM plan you run for years.
Frequently asked
How do I count the users on a Linux server?
'getent passwd | wc -l' counts every account, including the dozens of system accounts that services run under. To count only the accounts created for people, count UIDs from 1000 upwards: awk -F: '$3>=1000 && $3<65534' /etc/passwd | wc -l. The 1000 boundary is UID_MIN in /etc/login.defs.
Should I use getent passwd or cat /etc/passwd?
Use getent passwd. It returns the local accounts from /etc/passwd plus any from LDAP, FreeIPA or Active Directory if the server is joined to a directory, exactly as the system resolves them. cat /etc/passwd shows only local accounts. On a stand-alone VPS both print the same list.
How do I see when a user last logged in?
'lastlog -u alice' shows one account's most recent login, and 'last alice' lists that user's login history with source IP addresses and session lengths. Some newer releases, Debian 13 among them, replace these commands with lastlog2 and the wtmpdb package; if they are missing, install those or search the SSH log with 'journalctl -u ssh' (the unit is sshd on Rocky and Alma).
How do I list users on Windows Server?
'net user' lists all local accounts, and 'net user alice' shows one account's details, including its last logon and groups. In PowerShell, Get-LocalUser does the same. 'net localgroup administrators' and 'net localgroup "Remote Desktop Users"' show who has admin rights and who may log in over RDP, and 'quser' shows who is logged in right now.