我做了这个,但是很糟糕:(例如,里面有魔法数字、文本解析.. 呸!)
这该怎么做才是正确的呢?
awk -F: '{if($3 >= 1000 && $3 < 2**16-2) print $1}' /etc/passwd
这该怎么做才是正确的呢?
一些Unix系统不使用/etc/passwd
,或者有未在其中指定的用户。您应该使用getent passwd
而不是读取/etc/passwd
。
我的系统还有被禁用的用户,他们不能再使用其登录命令,而是将其设置为/bin/false
或/usr/sbin/nologin
。您可能也希望将它们排除在外。
以下是适用于我的内容,包括arheops awk命令和ansgar的代码以从login.defs
获取最小值和最大值:
getent passwd | \
grep -vE '(nologin|false)$' | \
awk -F: -v min=`awk '/^UID_MIN/ {print $2}' /etc/login.defs` \
-v max=`awk '/^UID_MAX/ {print $2}' /etc/login.defs` \
'{if(($3 >= min)&&($3 <= max)) print $1}' | \
sort -u
| sort -u
来消除重复项。 - Ansgar Wiechersawk
命令中使用临时数组来实现,也可以使用临时数组作为一部分。 - Adrian Frühwirth/etc/login.defs
中提取最小和最大用户ID,然后从/etc/passwd
中选择ID在这些范围内的用户:UID_MIN=$(awk '/^UID_MIN/ {print $2}' /etc/login.defs)
UID_MAX=$(awk '/^UID_MAX/ {print $2}' /etc/login.defs)
awk -F: -v min=$UID_MIN -v max=$UID_MAX '$3 >= min && $3 <= max{print $1}' /etc/passwd
if
是多余的...只需执行 '$3 >= min && $3 <= max{print $1}'
。 - Adrian Frühwirth这里有另一种方法,只会产生一个外部程序getent
(由@AnsgarWiechers建议),因此本地和网络密码数据库都将被使用。这种方法将forks的数量仅减少到getent
本身的一个。然而,它的可移植性有些受限,需要bash4。
get_users ()
{
local IFS=$' \t#'
while read var val ; do
case "$var" in
UID_MIN) min="$val" ;;
UID_MAX) max="$val" ;;
esac
done < /etc/login.defs
declare -A users
local IFS=:
while read user pass uid gid gecos home shell; do
if (( min <= uid && uid <= max )) && [[ ! $shell =~ '/(nologin|false)$' ]]; then
users[$user]=1
fi
done < <(getent passwd 2>/dev/null)
echo ${!users[@]}
}
bash4
,因此不是一个非常可移植的解决方案。 - Adrian Frühwirth我不确定为什么你只做 > 1000,因为在redhat系统上它从500开始。
对我来说,这个awk脚本可以正常工作:
awk -F: '{if(($3 >= 500)&&($3 <65534)) print $1}' /etc/passwd
仅限使用密码的用户:
awk -F: '{if(!(( $2 == "!!")||($2 == "*"))) print $1}' /etc/shadow
&&
的优先级低于>=
和<
。 - Adrian Frühwirthcut -d":" -f1 /etc/passwd
编辑:
如果你只需要用户自定义列表(而非系统用户),你可以使用以下其中之一:
grep -E ":[0-9]{4,6}:[0-9]{4,6}:" /etc/passwd | cut -d: -f1
^ 这假设您的系统对于用户定义的用户使用1000及以上的UID和GID
grep /home /etc/passwd | cut -d: -f1
^ 这假设每个用户定义的用户都有一个主目录。
其他解决方案取决于更详细的标准和系统设置。
NR==FNR
习惯用法,我认为它更易读。请注意保留html标签。getent passwd |
awk 'NR==FNR { if ($1 ~ /^UID_(MIN|MAX)$/) m[$1] = $2; next }
{ split ($0, a, /:/);
if (a[3] >= m["UID_MIN"] && a[3] <= m["UID_MAX"] && a[7] !~ /(false|nologin)$/)
print a[1] }' /etc/login.defs -