如何列出Linux组中的所有用户?


273

如何列出Linux中某个组的所有成员(可能还包括其他unice)?


1
@ Silmari89,如果他想以编程的方式来做,那就不是。
Paul Tomblin

2
我是新来的,发现问题后我就发现SF存在。我同意它属于SF还是SO。
user323094 2010年

5
嘿,当然,现在有了程序化的解决方案,因此在这里也可以证明是合理的。
Zed

Answers:


103

不幸的是,据我所知,没有很好的便携式方法可以做到这一点。如果您尝试解析/ etc / group(如其他人所建议的那样),则会错过以该组为主要组的用户以及通过UNIX平面文件(例如LDAP,NIS, pam-pgsql等)。

如果绝对要自己做,则可能相反:使用id来获取系统上每个用户的组(这将使NSS看到所有源),并使用Perl或类似的方法来维护哈希发现的每个组的表,注意该用户的成员资格。

编辑:当然,这给您带来了一个类似的问题:如何获取系统上每个用户的列表。由于我的位置仅使用平面文件和LDAP,因此我只能从这两个位置获取列表,但这可能对您的环境不适用。

编辑2:有人提醒我,getent passwd它将返回系统上所有用户的列表,包括来自LDAP / NIS / etc。的用户,但是 getent group仍然会通过默认组条目错过仍是成员的用户,因此启发了我写这个快速技巧。


#!/usr/bin/perl -T
#
# Lists members of all groups, or optionally just the group
# specified on the command line
#
# Copyright © 2010-2013 by Zed Pobre (zed@debian.org or zed@resonant.org)
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#

use strict; use warnings;

$ENV{"PATH"} = "/usr/bin:/bin";

my $wantedgroup = shift;

my %groupmembers;
my $usertext = `getent passwd`;

my @users = $usertext =~ /^([a-zA-Z0-9_-]+):/gm;

foreach my $userid (@users)
{
    my $usergrouptext = `id -Gn $userid`;
    my @grouplist = split(' ',$usergrouptext);

    foreach my $group (@grouplist)
    {
        $groupmembers{$group}->{$userid} = 1;
    }
}

if($wantedgroup)
{
    print_group_members($wantedgroup);
}
else
{
    foreach my $group (sort keys %groupmembers)
    {
        print "Group ",$group," has the following members:\n";
        print_group_members($group);
        print "\n";
    }
}

sub print_group_members
{
    my ($group) = @_;
    return unless $group;

    foreach my $member (sort keys %{$groupmembers{$group}})
    {
        print $member,"\n";
    }
}

3
感谢所有回答。我一直在寻找一种便携式的方式来做到这一点。您没有一种简便易行的方法的信息对您有所帮助。您还详细介绍了有助于我更深入地了解问题的情况,我对此表示赞赏,并选择了您的答案作为可接受的答案。
user323094 2010年

2
您可以将脚本捐赠给Linux基金会吗?现在是2012年,仍然没有简单的方法来招募小组成员。那就是令我沮丧的Linux。
winteck

6
我为您添加了类似ISC的许可证,该许可证应该与几乎所有组兼容。随时将其提交给您认为会被接受的任何地方。
Zed 2012年

PAM不提供帐户信息。是由名称服务交换机(nsswitch)来完成的。并非所有的“数据库”(数据提供程序)都支持枚举,因此getent passwd可能不起作用(例如,如果您使用的是sssd)。

关于PAM与NSS的有效观点-我更改了参考。尽管我没有使用过,但sssd乍看起来就像是nscd的替代品,而不是适当的数据提供者,如果它破裂了,getent passwd我会认为sssd中的错误。
Zed 2013年

239
getent group <groupname>;

它可以在Linux和Solaris上移植,并且可以与本地组/密码文件,NIS和LDAP配置一起使用。


43
不显示将组作为默认组的用户。
rlpowell


39
lid -g groupname | cut -f1 -d'(' 

7
这是最好的方法,只不过标准的Debian安装中没有lid。在Ubuntu中,它位于libuser可选软件包中(不是id-utils中的同名软件包)。我没在Debian中找到它:(
user323094

在Scientific Linux上为我工作
大约

在Debian喘息,盖子是libuser包太
LLUIS

2
@JohnMcGehee RHEL应该被称为AustereLinux
goelakash

1
'-g'不是我的选择。我在Ubuntu 16.04上安装了id-utils版本4.6。
威尔逊·比格斯

25

以下命令将列出属于的所有用户<your_group_name>,但仅列出由/etc/group数据库管理的用户,而不列出LDAP,NIS等。它也仅适用于辅助组,由于主要组为,因此不会列出将该组设置为主的用户。存储为GID(数字组ID)在文件中/etc/passwd

grep <your_group_name> /etc/group

4
您可以直接grep到该文件,例如grep <用户名> / etc / group。更快,开销更少。
彩盒

16

以下命令将列出属于的所有用户<your_group_name>,但仅列出由/etc/group数据库管理的用户,而不列出LDAP,NIS等。它也仅适用于辅助组,由于主要组为,因此不会列出将该组设置为主的用户。存储为GID(数字组ID)在文件中/etc/passwd

awk -F: '/^groupname/ {print $4;}' /etc/group

7
不显示将组作为默认组的用户。
rlpowell

3
不检查NIS和LDAP。
帕维尔Nadolski

12

以下shell脚本将遍历所有用户,并仅打印属于给定组的那些用户名:

#!/usr/bin/env bash
getent passwd | while IFS=: read name trash
do
    groups $name 2>/dev/null | cut -f2 -d: | grep -i -q -w "$1" && echo $name
done
true

用法示例:

./script 'DOMAIN+Group Name'

注意:此解决方案将检查NIS和LDAP中的用户和组(不仅包括文件passwdgroup文件)。它还将考虑未添加到组中但将组设置为主组的用户。

编辑:添加了针对罕见场景的修复程序,其中用户不属于具有相同名称的组。

编辑:以shell脚本的形式编写;添加true@Max Chernyak aka hakunin0建议的状态退出; 为了偶尔跳过而丢弃。stderrgroups: cannot find name for group ID xxxxxx


这很棒,非常简洁,但是它同时打印了组名和用户名
andrew lorien 2013年

@andrewlorien,希望我解决您提到的问题,否则请提供更多详细信息。
帕维尔Nadolski

这个代码片段不错,但是它返回退出代码1,是什么原因导致它不返回0?容易修复?
Max Chernyak

@hakunin,当最后一个用户名不属于组时,它不会返回0。如果需要,可以在end语句后附加“ || true”,使其始终为0。您可以检查然后输出以查看是否找到任何用户。
帕维尔Nadolski

我意识到@PawełNadolski,所以最后添加; true。返回0可以避免启动配置管理系统(Chef,Ansible等)。
Max Chernyak 2014年

7

您可以在单个命令行中执行此操作:

cut -d: -f1,4 /etc/passwd | grep $(getent group <groupname> | cut -d: -f3) | cut -d: -f1

具有上述命令列出所有用户组名称作为其主要组

如果你也想列出具有用户组名称作为其辅助组,可以使用下面的命令

getent group <groupname> | cut -d: -f4 |  tr ',' '\n'

1
警告:grep将匹配名称包含组号的用户(例如,sc0tt将显示为root组的一部分)。如果这是一个问题,请使用正则表达式:$(getent group <groupname> | cut -d: -f3)\$(匹配分号,组ID和行尾)。(不要在正则表达式中添加引号,否则bash会抱怨。)
Scott Stevens

@ScottS合法陷阱。将建议建议的步骤
巴哈维克(Bhavik)

3

只是一点点grep和tr:

$ grep ^$GROUP /etc/group | grep -o '[^:]*$' | tr ',' '\n'
user1
user2
user3

4
不显示将组作为默认组的用户。
rlpowell

3

Zed的实现可能应该扩展为在其他一些主要的UNIX上工作。

有人可以访问Solaris或HP-UX硬件吗?没有测试那些案例。

#!/usr/bin/perl
#
# Lists members of all groups, or optionally just the group
# specified on the command line
#
# Date:         12/30/2013
# Author:       William H. McCloskey, Jr.
# Changes:      Added logic to detect host type & tailor subset of getent (OSX)
# Attribution:
#   The logic for this script was directly lifted from Zed Pobre's work.
#     See below for Copyright notice.
#   The idea to use dscl to emulate a subset of the now defunct getent on OSX
#     came from
#       http://zzamboni.org/\
#         brt/2008/01/21/how-to-emulate-unix-getent-with-macosxs-dscl/
#     with an example implementation lifted from
#       https://github.com/petere/getent-osx/blob/master/getent
#
# Copyright © 2010-2013 by Zed Pobre (zed@debian.org or zed@resonant.org)
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#

use strict; use warnings;

$ENV{"PATH"} = "/usr/bin:/bin";

# Only run on supported $os:
my $os;
($os)=(`uname -a` =~ /^([\w-]+)/);
unless ($os =~ /(HU-UX|SunOS|Linux|Darwin)/)
    {die "\$getent or equiv. does not exist:  Cannot run on $os\n";}

my $wantedgroup = shift;

my %groupmembers;

my @users;

# Acquire the list of @users based on what is available on this OS:
if ($os =~ /(SunOS|Linux|HP-UX)/) {
    #HP-UX & Solaris assumed to be like Linux; they have not been tested.
    my $usertext = `getent passwd`;
    @users = $usertext =~ /^([a-zA-Z0-9_-]+):/gm;
};
if ($os =~ /Darwin/) {
    @users = `dscl . -ls /Users`;
    chop @users;
}

# Now just do what Zed did - thanks Zed.
foreach my $userid (@users)
{
    my $usergrouptext = `id -Gn $userid`;
    my @grouplist = split(' ',$usergrouptext);

    foreach my $group (@grouplist)
    {
        $groupmembers{$group}->{$userid} = 1;
    }
}

if($wantedgroup)
{
    print_group_members($wantedgroup);
}
else
{
    foreach my $group (sort keys %groupmembers)
    {
        print "Group ",$group," has the following members:\n";
        print_group_members($group);
        print "\n";
    }
}

sub print_group_members
{
    my ($group) = @_;
    return unless $group;

    foreach my $member (sort keys %{$groupmembers{$group}})
    {
        print $member,"\n";
    }
}

如果有更好的方法可以分享此建议,请告诉我;我考虑了很多方法,这就是我想到的。


更改id -Gn/usr/xpg4/bin/id -G -n
user667489,2015年

3

我完成了类似于上面的perl代码的操作,但是用本地perl函数替换了getent和id。它速度更快,并且可以在不同的* nix风格下工作。

#!/usr/bin/env perl

use strict;
my $arg=shift;
my %groupMembers; # defining outside of function so that hash is only built once for multiple function calls

sub expandGroupMembers{
my $groupQuery=shift;
unless (%groupMembers){
    while (my($name,$pass,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire)=getpwent()) {
            my $primaryGroup=getgrgid($gid);
            $groupMembers{$primaryGroup}->{$name}=1;
    }
    while (my($gname,$gpasswd,$gid,$members)=getgrent()) {
            foreach my $member (split / /, $members){
                    $groupMembers{$gname}->{$member}=1;
            }
    }
}
my $membersConcat=join(",",sort keys %{$groupMembers{$groupQuery}});
return "$membersConcat" || "$groupQuery Does have any members";
}
print &expandGroupMembers($arg)."\n";

仅带有链接的答案不是堆栈溢出的好答案。请考虑删除此内容,因为这不能提供问题的答案,也不能详细说明该答案比接受的答案更好。或者,一旦您拥有足够的声誉,就可以将其添加为评论。您可以随时对自己的帖子发表评论。
Dipen Shah 2015年

2

有一个方便的Debian和Ubuntu软件包,名为“ members ”,提供了以下功能:

描述:显示组的成员;默认情况下,所有成员都是组的补充:组显示指定用户所属的组,而成员显示属于指定组的用户。

...您可以在一行中要求主要成员,次要成员,每个成员都在单独的行中。


如果op使用openwrt怎么办?
user2284570 2015年

确实方便,但不幸的是没有报告域组成员。
simlev

1
getent group insert_group_name_here | awk -F ':' '{print $4}' | sed 's|,| |g'

这将返回用空格分隔的用户列表,这些脚本已在脚本中用来填充数组。

for i in $(getent group ftp | awk -F ':' '{print $4}' | sed 's|,| |g')
    do
        userarray+=("$i")
    done

要么

userarray+=("$(getent group GROUPNAME | awk -F ':' '{print $4}' | sed 's|,| |g')")

0

这是一个脚本,该脚本从/ etc / passwd和/ etc / group返回用户列表,它不检查NIS或LDAP,但确实显示了将该组作为其默认组的用户在Debian 4.7和solaris 9上进行了测试。

#!/bin/bash

MYGROUP="user"

# get the group ID
MYGID=`grep $MYGROUP /etc/group | cut -d ":" -f3`
if [[ $MYGID != "" ]]
then
  # get a newline-separated list of users from /etc/group 
  MYUSERS=`grep $MYGROUP /etc/group | cut -d ":" -f4| tr "," "\n"`
  # add a newline
  MYUSERS=$MYUSERS$'\n'
  # add the users whose default group is MYGROUP from /etc/passwod 
  MYUSERS=$MYUSERS`cat /etc/passwd |grep $MYGID | cut -d ":" -f1`

  #print the result as a newline-separated list with no duplicates (ready to pass into a bash FOR loop)
  printf '%s\n' $MYUSERS  | sort | uniq
fi

或者也可以从此处直接剪切并粘贴(在第一个变量中更改组名)

MYGROUP="user";MYGID=`grep $MYGROUP /etc/group | cut -d ":" -f3`;printf '%s\n' `grep $MYGROUP /etc/group | cut -d ":" -f4| tr "," "\n"`$'\n'`cat /etc/passwd |grep $MYGID | cut -d ":" -f1`  | sort | uniq

0

在UNIX(与GNU / Linux相对)中,有listusers命令。有关listusers,请参见Solaris手册页

请注意,此命令是开源Heirloom Project的一部分。我认为GNU / Linux中缺少它,因为RMS不相信组和权限。:-)


1
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会无效。- 评分
knuhol

NAME listusers - print a list of user logins SYNOPSIS listusers [-g groups] [-l logins] DESCRIPTION Listusers prints the name and the gecos information of all users known to the system, sorted by username. Valid options are: -g groups Only print the names of users that belong to the given group. Multiple groups are accepted if separated by commas. -l logins Print only user names that match logins. Multiple user names are accepted if separated by commas.
阿伦·卡尔

在Heirloom Project网站上:Heirloom Project提供了标准Unix实用程序的传统实现。在许多情况下,它们是由Caldera和Sun作为Open Source发布的原始Unix资料衍生的。接口遵循传统惯例;它们有时仍与System V兼容,尽管有时会提供一些在一段时间内已变得很普遍的扩展。大多数实用程序也包含在旨在实现POSIX一致性的变体中。
阿伦·卡尔

0

这是一个非常简单的awk脚本,其中考虑了其他答案中列出的所有常见陷阱:

getent passwd | awk -F: -v group_name="wheel" '
  BEGIN {
    "getent group " group_name | getline groupline;
    if (!groupline) exit 1;
    split(groupline, groupdef, ":");
    guid = groupdef[3];
    split(groupdef[4], users, ",");
    for (k in users) print users[k]
  }
  $4 == guid {print $1}'

我在启用了ldap的安装程序中使用了此程序,该程序可以在符合标准的getent&awk的任何程序上运行,包括solaris 8+和hpux。


0
getent group groupname | awk -F: '{print $4}' | tr , '\n'

这包括三个部分:

1- getent group groupname在“ / etc / group”文件中显示组的行。替代cat /etc/group | grep groupname

2- awk打印只有一行中用','分隔的成员。

3- tr用新行替换','并连续打印每个用户。

4-可选:sort如果用户太多,也可以将另一个管道与一起使用。

问候


0

我认为最简单的方法是执行以下步骤,您无需安装任何软件包或软件:

  1. 首先,找到您想了解用户的组的GID,有很多方法: cat / etc / group (最后一列是GID) id用户 (用户是属于该用户的人)群组)

  2. 现在,您将在文件/ etc / passwd上列出所有用户,但是您将通过以下命令序列应用一些过滤器,以仅获取上一组的成员。

切-d:-f1,4 / etc / passwd | grep GID (GID是您从步骤1获得的数字)

cut命令将仅选择文件的某些“列”,在这种情况下,参数d设置定界符“:”,在情况下,参数-f选择要显示为1和4的“字段”(或列)。 / etc / passwd文件,其中1º列是用户名,4º是用户所属组的GID),要最终确定| grep GID,将仅过滤您所使用的组(在4º列上)选择了。


0

这里是另一个Python一班轮,考虑到(从用户的默认组成员/etc/passwd),以及从组数据库(/etc/group

python -c "import grp,pwd; print set(grp.getgrnam('mysupercoolgroup')[3]).union([u[0] for u in pwd.getpwall() if u.pw_gid == grp.getgrnam('mysupercoolgroup')[2]])"

-1

我已经尝试过grep 'sample-group-name' /etc/group,它将根据此处的示例列出您指定的组的所有成员


1
Grepping /etc/group在其他至少3个答案已经,什么样的价值你的答案加不给他们吗?另外,所有其他的答案有评论认为,这种解决方案适用于第二组的唯一,也确实为帐户通过LDAP,NIS等管理工作不
大卫FerenczyRogožan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.