Answers:
人类用户的UID从1000开始,因此您可以使用该事实过滤掉非人类用户:
cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1
这会从中切出第一个(用户名)和第三个(UID)以冒号分隔的字段/etc/passwd
,然后过滤以冒号和四位数结尾的结果行,然后从中切出第一个(用户名)字段,为您提供一个列表UID在1000到9999之间的用户。
如果您的系统上有超过九千个用户,这将失败-但是有必要将结果限制为4位UID,以免被捕获nobody
(UID 65534)。
我个人喜欢只使用:
ls /home
不可否认,这不是用户列表,而是其主目录列表。当前系统上现有的人工用户将在中拥有主目录/home
,但是您可能还会看到被删除的过去用户的主目录。
这对我有用,也可能对您有用。例如,如果您要删除原来不存在的用户帐户(nonexistent-user
),然后运行命令
sudo deluser nonexistent-user
它只会告诉您该用户不存在。
/home
(未链接到/home
)的主目录似乎不太可能用户登录屏幕上,有时可以由人类用户完成)。一个相对较小的缺点是,lost+found
它将在具有单独/home
分区的系统上列出。
useradd --no-create-home username
?
useradd --no-create-home
-主目录可能已经存在或可能在此后不久创建-但该ls /home
方法在这些情况下效果很好。
尽管这似乎是一个明确的主意,但实际上,人类使用者的含义存在歧义。用户帐户是否仅由于专门用于人类用户的目的而被故意隐藏在登录屏幕上?ubuntu
实时CD上的用户(UID 999)如何?而且,Ubuntu中的来宾帐户是即时创建的,并在注销后销毁;他们是人类使用者吗?可以设计更多示例。
因此,给出多个非等效的答案是合适的。Saige Hamblin的运行解决方案ls /home
是人们的实际操作,除非您正在编写脚本,否则可能应该使用它。
ls /home
更稳健但是,也许您的用户已被删除,但其主目录仍存在于中/home
,并且您必须避免列出它们。或者,也许由于某些其他原因,您必须确保仅/home
列出与真实帐户相对应的条目。
在这种情况下,我建议通过这些名字都是在/home
以getent
(检索passwd
与这些名字用户的条目),然后分离并显示只是用户名字段(与grep
,sed
或awk
,按您的喜好)。这些中的任何一个都可以:
getent passwd $(ls /home) | grep -o '^[^:]*'
getent passwd $(ls /home) | sed 's/:.*//'
getent passwd $(ls /home) | awk -F: '{print $1}'
这应该很好用,因为您的用户帐户中不应包含空格或控制字符。不能,除非重新配置Ubuntu以允许它;如果这样做,您会遇到更大的问题。因此,解析ls
中常见的问题不适用。但是,即使在这里真的可以,但是如果您考虑用ls
美观或令人讨厌的习惯替换命令,您可能更喜欢:
getent passwd $(basename -a /home/*) | grep -o '^[^:]*'
getent passwd $(basename -a /home/*) | sed 's/:.*//'
getent passwd $(basename -a /home/*) | awk -F: '{print $1}'
这些也不包含空格或控制字符。我之所以提供它们,仅是因为$(ls /home)
即使正确也看起来还是错误的,从而以错误的方式擦拭了许多用户。在大多数情况下,确实有充分的理由要避免进行解析ls
,并且在这些情况下,解析的basename -a
坏处通常很少。但是,在这种情况下,由于实际上在用户名中可能出现什么字符的限制,它们都很好。
我getent
之所以使用它,主要是因为它接受用户名作为参数来限制其输出,还因为它比/etc/passwd
直接检查更通用,以防身份验证设施和密码数据库由网络服务提供。
这种方法的另一个好处ls /home
是,在具有单独/home
分区的系统上,lost+found
通常出现在的输出中ls /home
。
lost+found
只有在碰巧有一个用户(无论是人类还是不是)被称为时才会出现lost+found
。ls /home
很好- 您知道您没有人类用户lost+found
。这种方法(在上述任何一种变化中)很少会产生不令人满意的输出:
/home
,或根本不存在,则表明但并不意味着该帐户不应该代表人类用户。仅当中存在相同名称的目录时,此方法才会列出用户/home
。/home
实际上不是任何人的主目录,并且它们碰巧与现有的非人类用户相同的名称-或由空格分隔的单词组成,其中一个或多个具有相同的名称作为现有的非人类用户-那么某些非人类用户可能会包含在输出中。getent
调用来实现,因此,单词拆分不会产生虚假输出。但是并不能保证复杂性;从根本上讲,如果您/home
将其用作用户主目录的存放位置,则此方法将无法产生可靠的输出。)如果您决定采用一种检查用户ID的方法,以确保它们在代表人类的帐户的可能范围内(例如公认的答案或Oli的答案),那么为简洁起见,我建议这样做:
getent passwd | grep -oP '^[^:]+(?=:x:\d{4}:)'
这使用Perl正则表达式(-P
)显示:
^
不包含:
s([^:]+
)的行()开头的文本-这是第一个字段,:
其中的字段分隔符passwd
(?=
)
)密码字段x
-应该始终为x
,因为在Ubuntu中,密码哈希存储在shadow
数据库中,而不是世界可读的passwd
数据库中:\d{4}:
)组成。因此,这是公认答案中该技术的明显更短,更简单的变体。(那里描述的技术也很好用,它的好处是可以移植到grep
不支持的非GNU / Linux系统上-P
。)
如果要容纳非常高的UID并进行nobody
明确检查,则可以使用Oli的answer中的方法。但是,您可能要考虑,如果UID很高的用户确实应该被认为是人类用户,或者他们更有可能是其他一些特殊用途的非人类用户(例如nobody
)。在实践中,此类用户(除其他外)nobody
并不常见,因此,这实际上是您的判断要求。
可能的折衷办法是列出实际分配给新创建的非“系统”用户的UID范围内的用户。您可以在adduser.conf
以下位置进行检查:
$ grep -E '^(FIRST|LAST)_UID' /etc/adduser.conf
FIRST_UID=1000
LAST_UID=29999
以下是列出UID范围从1000到29999的用户的两种方法:
getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'
basename
很难看。没有比这更好的了ls
。我们不解析ls的原则原因是,这项工作可以通过其他工具更安全,更干净地完成,而不是使用样式。在这种情况下,外壳:cd /home; getent passwd *
。
ls
通常是关于样式的。关于“输出不令人满意”的第二点要点涵盖了该问题,但它会在后面的部分中出现。我已经改写清楚了,为什么在这种情况下解析ls
才是合适的。尽管采用某种形式通常表示一种更合理的方法,但我避免使用这种形式是为了避免使读者相信目录的内容以及添加了与实际用户不对应的怪异条目,仍然可以以某种方式作为指导内容用户存在。cd /home; getent passwd *
/home
TL; DR:仅人类用户具有SystemAccount = false
另一种方法是在忽略root的情况下列出的输出 ls /var/lib/AccountsService/users/ | grep -v root
。现在,有一个怪癖-gdm,一个迎宾/登录屏幕(或更正式的说是桌面管理器)也被列为用户。因此,仅从列表中我们就无法确定gdm是否是人类。
一种更有效,更正确的方法是浏览该文件夹中的文件,并找出列出哪些用户SystemAccount=false
。一线波纹管实现了
grep SystemAccount=false /var/lib/AccountsService/users/* | awk -F '/' '{gsub(":","/");print $6}'
mini.iso
并且没有安装显示管理器或X11),我有一个人工用户帐户-仍然/var/lib/AccountsService/users
是一个空目录。我希望这在开箱即用的Ubuntu Server安装上同样不起作用。此外,当此方法起作用时,它在某种程度上限制了使用户帐户“人性化”的条件:拥有useradd
甚至没有 的用户--system
都不会在中创建文件AccountsService/users
。
加入聚会后,我监督了使用LDAP的网络系统,外部有主目录,/home
而UID(由于脚本故障)有数百万。因此,当前的答案均无效。对我有用的测试是检查用户是否具有有效的登录外壳。有效的外壳是中列出的外壳/etc/shells
。最简单的形式:
getent passwd | grep -wFf /etc/shells
该文件可能包含注释(或空行),因此可能必须将其过滤掉:
getent passwd | grep -wFf <(grep '^/' /etc/shells)
root
(这也许不应该被认为是人类用户,因为人类通常根暂时的,为特定目的,而不是用它为自己的日常工作),现在看来似乎是最有可能失败的任何主要方式。在其他的答案(包括我)的方法可能会失败,取决于方法,如果主目录不在/home
,其他垃圾是在/home
,的UID是怪异的,或者系统不使用DM。在所有这些情况下,此答案都非常有效。
在Buntu系统上,普通用户(即人工用户)具有以1000开头的UID,这些UID在首次创建其帐户时会顺序分配给他们。所有这些归结为,在Buntu系统上创建的第一个帐户的UID为1000。下一个创建的帐户的UID为1001。依此类推。
因此,在我看来,列出系统上存在的所有人类用户帐户的最简单方法是检查/etc/passwd
文件中包含用户UID 的第三列是否大于或等于1000且小于等于2000 (对于典型的台式机来说,拥有一千个以上的用户帐户是非常不可能的,您是不是这样认为?):
$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd
nobody
。=)