我正在尝试编写一个脚本来查找用户是否有效以及他们当前是否已登录。我无法让其等待用户输入有效的 ID。
while read one
do
if id "$one" >/dev/null 2>1;
then
Matrix=$(who -u |grep -q "$one" || test && echo "logged on" || echo "not logged on")
fullname=$(grep "$one" /etc/passwd | cut -d ':' -f5 | sort -k 2 | tr ",,:" " " | awk '{print $2,$1}')
echo "$fullname is $Matrix"
else
echo "user doesnt exist"
fi
break
done
echo "maybe"
答案1
该read
实用程序将等待直到输入数据,所以
read username
直到用户输入 shell 存储为 的内容后才会返回$username
。
如果您所说的“等待”意味着“循环直到输入有效的用户名”,那么您可以执行类似的操作
while true; do
read -p 'Enter username: ' username
if id "$username" >/dev/null 2>&1; then
printf 'Username "%s" is valid\n' "$username"
break
fi
printf 'Username "%s" is not valid\n' "$username"
echo 'Try again...'
done
这会进入无限循环,只有当用户输入有效的用户名时才会退出。使用该实用程序检查有效性id
,您的代码似乎也在使用该实用程序。如果实用程序退出时没有错误,则通过 转义循环break
。
在此循环之后,您知道您在 中有一个有效的用户名$username
。
要测试用户是否已登录,您可以who
像以前一样使用(此处稍作修改):
if who | grep -q "^$username\>"; then
printf 'User "%s" is logged on\n' "$username"
else
printf 'User "%s" is not logged on\n' "$username"
fi
用户名可以在 输出的第一列中找到who
。因此,我们将用户名锚定到行的开头^
。我们还确保将用户名末尾的单词边界与 相匹配\>
(这样arthur
我们在实际查找时就不会检测到用户art
)。
相反,who
我们可以拥有users
实用程序。
要获取用户的全名,您可以这样做
name=$( getent passwd "$username" | cut -d : -f 5 | cut -d , -f 1 )
该getent
实用程序用于获取密码数据库或其中的条目等。在这里,我们使用它来获取我们感兴趣的特定用户的密码数据库条目。然后,我们从 GECOS 字段的第一个逗号分隔值中解析出全名。
请注意,我们可以使用getent
该实用程序来测试有效的用户名(因为如果您使用无效的用户名,它会返回非零退出状态),这样就可以在过程中获得用户的全名,而无需之后再进行一次查询。
综合起来:
#!/bin/bash
while true; do
read -p 'Enter username: ' username
if id "$username" >/dev/null 2>&1; then
printf 'Username "%s" is valid\n' "$username"
break
fi
printf 'Username "%s" is not valid\n' "$username"
echo 'Try again...'
done
name=$( getent passwd "$username" | cut -d : -f 5 | cut -d , -f 1 )
printf 'Full name of "%s" is %s\n' "$username" "$name"
if who | grep -q "^$username"; then
printf '%s is logged on\n' "$name"
else
printf '%s is not logged on\n' "$name"
fi
答案2
您可以预设错误结果以进入循环,在循环内执行工作,并在下一次迭代期间询问真实结果。
就像是:
#!/bin/bash
ok=1
while [ $ok -gt 0 ]; do
read one
< your check of $one >
ok=$?
done