50

我有一个服务器正在运行,我使用 php 运行 bash 脚本来验证用户的某些信息。例如,我设置了一个虚拟主机服务器,为了能够向他们的帐户添加另一个域,我想验证用户是否实际上是“客户”组的成员。最好的方法是什么?

我搜索了谷歌,但它所提供的只是检查用户或组是否存在的方法,所以谷歌现在没有太大的帮助。

4

13 回答 13

42
if id -nG "$USER" | grep -qw "$GROUP"; then
    echo $USER belongs to $GROUP
else
    echo $USER does not belong to $GROUP
fi

解释:

  1. id -nG $USER显示用户所属的组名。
  2. grep -qw $GROUP静默检查 $GROUP 作为一个整体是否存在于输入中。
于 2015-04-10T09:04:30.827 回答
42

尝试这样做:

username=ANY_USERNAME
if getent group customers | grep -q "\b${username}\b"; then
    echo true
else
    echo false
fi

或者

username=ANY_USERNAME
if groups $username | grep -q '\bcustomers\b'; then
    echo true
else
    echo false
fi
于 2013-08-25T16:48:33.883 回答
14

使用零字符分隔的固定字符串 grep 检查组成员身份的稍微防错的方法。

if id -nGz "$USER" | grep -qzxF "$GROUP"
then
    echo User \`$USER\' belongs to group \`$GROUP\'
else
    echo User \`$USER\' does not belong to group \`$GROUP\'
fi

或使用长选项

if id --name --groups --zero "$USER" | 
   grep --quiet --null-data --line-regexp --fixed-strings "$GROUP"
then
    echo User \`$USER\' belongs to group \`$GROUP\'
else
    echo User \`$USER\' does not belong to group \`$GROUP\'
fi
于 2017-10-09T16:41:46.647 回答
8

我知道这可能是旧线程,但以防万一这也很好用:

id -Gn "username"|grep -c "groupname"

如果返回任何数字 > 0,则用户是该组的成员。

于 2015-05-15T05:52:20.750 回答
6

你可以使用 groups $username_here | grep -q '\busergroup\b'

如果找到匹配项,则退出代码将为 0,如果未找到匹配项,则为 1。

user_in_group()
{
    groups $1 | grep -q "\b$2\b"
}

您可以将此功能用作user_in_group userfoo groupbar

于 2015-04-10T08:13:16.477 回答
5

对于所有那些高尔夫球迷:

ingroup(){ [[ " `id -Gn $2` " == *" $1 "* ]]; }

用法:ingroup group [user]

例子:

if ingroup video; then
  echo 'Enjoy the show!'
fi

TL;DR 关键是我利用了内置的通配符来查找子字符串。

编辑:感谢@Anthony Geogheganid -Gn提示。

于 2015-03-08T12:55:57.070 回答
3

使用零分隔符按行分割:

id -nGz user | tr '\0' '\n' | grep '^group$'
于 2018-11-22T15:06:30.403 回答
2

前段时间,我写了一个 shell 函数来检查用户是否是组的成员。为了最大限度地提高可移植性,我希望它与 POSIX 兼容(虽然这个问题被标记为bash,但这个功能仍然可以工作)。为了性能,我想尽可能地使用内置的 shell 功能:它使用的唯一外部命令是idPOSIX 标准化实用程序,用于获取有关用户身份的数据。

is_in_group()
{
  groupname="$1"
  # The second argument is optional -- defaults to current user.
  current_user="$(id -un)"
  user="${2:-$current_user}"
  for group in $(id -Gn "$user") ; do
    if [ "$group" = "$groupname" ]; then
      return 0
    fi
  done
  # If it reaches this point, the user is not in the group.
  return 1
}

测试正面和负面情况的示例用法 - 并确保它优雅地处理不存在的用户名:

g=mail
userlist="anthony postfix xxx"
for u in $userlist; do
  if is_in_group "$g" "$u"; then
    printf "%s is in ‘%s’\n" "$u" "$g"
  else
    printf "%s is NOT in ‘%s’\n" "$u" "$g"
  fi
done

运行上述命令将打印以下输出:

anthony is NOT in ‘mail’
postfix is in ‘mail’
id: ‘xxx’: no such user
xxx is NOT in ‘mail’

尚未针对组或用户名称中包含空格或其他不寻常字符的情况进行测试,但一些研究表明此类名称不合法:组名称的 POSIX 基本定义指出

为了在符合标准的系统中可移植,该值由可移植文件名字符集中的字符组成。

移植文件名字符集指定为字母数字字符 AZ、az、0-9 以及句点、下划线和连字符减号。

于 2019-09-03T11:18:10.777 回答
1

听起来像另一个答案:

username='myuser'
if grep -q -E "^customers:.*[:,]$username(,.*|\b)" /etc/group; then
    echo 'true'
else
    echo 'false'
fi

正如命令sputnick输出所报告的,groups可能取决于您的操作系统。我不确定这段代码将如何执行,但很可能它会做得更好。

于 2013-08-25T18:20:38.763 回答
0

我的版本不依赖 grep。

第一个参数(必填):group
第二个参数(可选,默认为当前用户)

isInGroup(){
   group="$1"
   user="${2:-$(whoami)}"
   ret=false 
   for x in $(groups "$user" |sed "s/.*://g")
   do [[ "$x" == "$group" ]] && { ret=true ; break ; }
   done
   eval "$ret"
}
于 2015-02-19T13:45:56.180 回答
0
username='myuser'
if groups "$username" | grep -q -E ' customers(\s|$)'; then
    echo 'yes'
else
    echo 'no'
fi

我必须澄清一件事: groups可能会返回如下内容:

myuser : cdrom floppy sudo audio dip video plugdev fuse

但是当您的用户被命名时,有一个极端情况customers

customers : cdrom floppy sudo audio dip video plugdev fuse

例如,\bcustomers\b模式将查找用户名,而不是组。所以你必须确保它不是输出中的第一个单词。

此外,另一个好的正则表达式是:

grep -q ' customers\b'
于 2013-08-25T16:57:47.743 回答
0

Bash 单行:

[[ " $(groups) " =~ ' spark ' ]] && echo 'Is in group'

Bash 多行:

if [[ " $(groups) " =~ ' spark ' ]]; then
    echo 'Is in group'
fi
于 2020-05-05T09:59:13.443 回答
0

这是我的。

首先是长版

#!/bin/bash
if [[ $# -eq 0 ]]
then
  echo "Usage: $0 [-v] user group"
  echo ""
  echo "  -v verbose. Outputs a sentence for humans."
  echo ""
  echo "Example:"
  echo ""
  echo "  ingroup wilma sudo && echo Wilma has superpowers"
  exit 2
fi

if [[ "$1" == "-v" ]]
then
  verbose=1
  shift
fi

user=$1
grp=$2
# Get groups output
grps=$(groups $user)
# Create a regexp. Note that we must create the regexp in a var
# because it's the only way to allow for spaces in the regexp.
# Strangely we provide this var unquoted when using it; even 
# though it has spaces.
re="^.*:.* $2 "
if [[ "$grps" =~ $re ]]
then
  [[ -n "$verbose" ]] && echo "$user is in group $grp"
  # Success error code
  exit 0
else
  [[ -n "$verbose" ]] && echo "$user is not in group $grp"
  # Fail error code
  exit 1
fi

想要一个更短的版本作为一个函数?

ingroup() {
  re="^.*:.* $2 "
  [[ "$(groups $1) " =~ $re ]] || return 1
}

测试

# Basic positive test
$ ingroup -v wilma sudo && echo 'and therefore is cool'
wilma is in group sudo
and therefore is cool

# Basic negative test
$ ingroup -v wilma myprivateclub || echo 'sorry bout that'
wilma is not in group sudo
sorry bout that

# Test with hyphens in the group name
$ ingroup -v wilma systemd-journal
wilma is in group systemd-journal

# If the group does not exist, it's a negative
$ ingroup -v wilma somewronggroup
wilma is not in group somewronggroup
于 2020-11-04T10:41:30.997 回答