我正在尝试编写一个 bash 脚本,根据用户提供的 uid 显示用户名:
#!/bin/bash
read -p "donner l UID" cheruid
if [ $(grep -w $cheruid) -n ]
then
grep -w $cheruid /etc/passwd | cut -d ":" -f "1" | xargs echo "user is : "
else
echo "user not found"
fi
当我执行此命令时,终端仅显示提示消息,然后停止工作。
我错过了什么吗?
答案1
使用 GNU id
,您可以执行以下操作:
id -un -- "$cheruid"
这将查询帐户数据库(无论是存储在/etc/passwd
LDAP、NIS+、RDBMS...中)以查找具有该 uid 的第一个用户名。
一般来说,每个uid只有一个用户名,但这并不能保证,用户帐户数据库中的关键是用户名,而不是用户id。
如果你想知道给定 uid 的所有用户名,你可以这样做:
getent passwd | ID=$cheruid awk -F: '$3 == ENVIRON["ID"] {print $1}'
但这可能不适用于某些不支持的帐户数据库可枚举的(有时大型基于 LDAP 的情况就是如此)。
答案2
$ printf 'User is %s\n' "$( getent passwd 1001 | cut -d : -f 1 )"
User is myself
myself
(我的系统上有一个UID 1001的用户)
这将passwd
在数据库中查询给定的 UID,从该响应中删除用户名,并将结果用作 的参数printf
。这在 macOS 上不起作用。
要捕获未知的 UID:
$ printf 'User is %s\n' "$( { getent passwd 1001 || echo 'UNKNOWN USER'; } | cut -d : -f 1 )"
User is myself
$ printf 'User is %s\n' "$( { getent passwd 1002 || echo 'UNKNOWN USER'; } | cut -d : -f 1 )"
User is UNKNOWN USER
作为在命令行上采用任意数量的 UID 的脚本(稍微改变输出):
#!/bin/sh
for uid do
printf 'User with UID %d is %s\n' "$uid" \
"$( { getent passwd "$uid" || echo 'NOT KNOWN'; } | cut -d : -f 1 )"
done
测试(这将通过我的 OpenBSD 系统上的一些服务帐户的 UID):
$ sh ./script.sh {110..115}
User with UID 110 is _sndiop
User with UID 111 is NOT KNOWN
User with UID 112 is _syspatch
User with UID 113 is NOT KNOWN
User with UID 114 is NOT KNOWN
User with UID 115 is _slaacd
答案3
帮助了解原始 shell 脚本
if 语句中的测试导致了问题。我建议使用以下 shellscript,
#!/bin/bash
read -p "donner l UID " cheruid
if [ "$(grep -w "^$cheruid" /etc/passwd)" != "" ]
then
grep -w "$cheruid" /etc/passwd | cut -d ":" -f "1" | xargs echo "user is : "
else
echo "user not found"
fi
编辑1:我添加了一个^
在测试中仅查找行开头的匹配项。
编辑2:自从:
是一个分隔符,您可以删除它和后面的所有内容,并直接在行中使用结果(echo
如果在测试中接受),并将 shellscript 简化为
#!/bin/bash
read -p "donner l UID " cheruid
cheruid=${cheruid%%:*}
user=$(grep -wo "^$cheruid" /etc/passwd)
if [ "$user" != "" ]
then
echo "user is : $user"
else
echo "user not found"
fi
这可以帮助您编写一个好的 bash shell 脚本。
查找用户 ID 的有效且更通用的方法id
如果您想要一种有效的方法来检查特定用户名是否存在,<test-name>
您可以使用id
,如 Stéphane Chazelas 对您的问题的另一个答案所示:
id -un -- <test-name>
例如
id -un -- mehdi
id
不仅会发现存储在其中的用户 ID,还会发现/etc/passwd
以其他方式管理和存储的用户 ID,例如 LDAP,正如 Matteo Italia 所评论的,LDAP 在专业服务器系统中很常见。
如果你想扫描所有用户
系统用户,在许多用户数 < 1000 的 Linux 系统中
“人类”用户,在许多用户数量 >= 1000 的 Linux 系统中
并假设所有用户的数量<2000(如果需要,请修改)
您可以使用以下bash
单行代码,它使用一个循环id
,
for ((i=0;i<2000;i++));do name=$(id -un $i 2>/dev/null);if [ $? -eq 0 ];then echo "$i: $name" ;fi;done
如果您只想查看“人类”用户并假设没有跳过任何用户 ID 号(没有删除的用户),则以下bash
oneliner 非常快,
i=1000;while true;do name=$(id -un $i 2>/dev/null);if [ $? -eq 0 ];then echo "$name" ;else break;fi;i=$((i+1));done
但更可靠的假设是某些ID号可能会被跳过(删除用户),
for ((i=1000;i<2000;i++));do name=$(id -un $i 2>/dev/null);if [ $? -eq 0 ];then echo "$i: $name" ;fi;done
还有users
打印who
用户的用户名的当前登录到当前主机。
答案4
使用 grep 意味着任何数字都将被匹配。作为用户 ID 或组 ID:
$ grep '109' /etc/passwd
uuidd:x:105:109::/run/uuidd:/bin/false
usbmux:x:109:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false
而且也可能会匹配1109
。即使称为as grep -w
,这也会避免匹配1109
。这是一个重要的问题。
使用getent:
$ getent passwd 109
usbmux:x:109:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false
哪个会匹配仅有的找到的第一个用户条目的帐户数据库( /etc/passwd
、LDAP
、 、 ...)的数字 uid,而不是 gid(如果给定数字,如果给定文本则为名称) 。NIS+
不适用于 macOS。
所以,脚本可以是:
#!/bin/bash
read -p "donner l UID: " cheruid
if name=$(getent passwd "$cheruid")
then name=${name%%:*}
echo "user is : $name"
else echo "user not found"
fi
无需 sed、awk、cut 即可获得名称。