真实用户UID通常≥1000且shell非nologin/false:getent passwd | awk -F: '$3>=1000 && $7!~/nologin|false$/{print $1}'

怎么用 getent 看到所有真实用户(不含系统账号)
Linux 里 /etc/passwd 有几百行,但大部分是 daemon、sys、www-data 这类服务账户,真要导出“人用的用户”,得筛 UID 范围。不同发行版默认策略不同:getent passwd 输出全量,但得自己过滤。
实操建议:
- 普通用户 UID 通常从
1000开始(Ubuntu/Debian),CentOS/RHEL 是1000起,但有些老系统用500;先查当前策略:grep -E '^UID_MIN' /etc/login.defs - 导出真实用户命令:
getent passwd | awk -F: '$3 >= 1000 && $3 —— 这里 <code>65534是避免包含nobody类特殊 UID - 别只看
/etc/passwd:如果用了 LDAP 或 SSSD,getent才能拉到网络用户;直接cat /etc/passwd会漏
cut 和 awk 提取用户名时字段数容易错
/etc/passwd 是冒号分隔,共 7 字段,但第 5 字段(GECOS)本身可能含逗号,不能靠 cut -d: -f1,5 直接提姓名——这会导致字段错位。用户名永远在第 1 字段,但“全名”或“描述”在第 5 字段,提取逻辑必须分开。
常见错误现象:
-
cut -d: -f1,5 /etc/passwd在 GECOS 含空格或逗号时,输出变成alice:John Doe,Admin,,,,后续脚本解析失败 - 想导出“用户名+全名”,误写成
awk -F: '{print $1, $5}',结果发现某些行第 5 字段为空,对齐混乱
正确做法:
- 只要用户名:
awk -F: '$3 >= 1000 {print $1}' /etc/passwd - 要用户名+清理后的全名(去逗号和多余空格):
awk -F: '$3 >= 1000 {gsub(/,.*/, "", $5); gsub(/^ +| +$/, "", $5); print $1, $5}' /etc/passwd
导出结果含重复或无效用户怎么办
运行 getent passwd 或解析 /etc/passwd 时,常遇到 nobody、systemd-network、dbus 这类 UID 合法但无登录能力的账号。它们不是“被禁用”,而是压根没设密码、shell 为 /usr/sbin/nologin 或 /bin/false。
判断是否可登录的关键参数是第 7 字段(shell)和第 2 字段(密码字段):
- 跳过 shell 为
/usr/sbin/nologin、/bin/false、/sbin/nologin的行:awk -F: '$3 >= 1000 && $7 !~ /(nologin|false)$/ {print $1}' - 第 2 字段为
*或!表示密码被锁,但用户仍可能用 SSH key 登录,不建议仅凭此过滤 - 注意:某些容器环境或最小化系统会把
root的 shell 改成/sbin/nologin,别一刀切排除root
导出 CSV 或用于脚本时换行/空格处理要小心
用户名本身可能含空格(虽然不推荐),更常见的是 GECOS 第 5 字段带空格甚至换行符(极少见但合法)。直接 echo 或重定向进 CSV,会导致 Excel 打开错行、while read 循环提前中断。
安全做法:
- 导出纯用户名列表(无空格风险):
getent passwd | awk -F: '$3 >= 1000 && $7 !~ /nologin|false$/ {print $1}' | sort -u > users.txt - 导出带引号的 CSV(兼容空格):
getent passwd | awk -F: '$3 >= 1000 && $7 !~ /nologin|false$/ {gsub(/"/, "\"\"", $5); print "\"" $1 "\",\"" $5 "\""}'—— 这里用了 Excel 风格双引号转义 - 脚本里读取时,别用
for u in $(cat users.txt),改用while IFS= read -r u,否则空格会让变量截断
真正麻烦的是跨系统迁移:Ubuntu 默认 UID_MIN=1000,Alpine 是 100,Arch 是 1000 但允许手动创建低 UID 用户。导出前不确认目标系统的策略,生成的清单可能在另一台机器上完全对不上。

















