Как составить список всех пользователей в группе Linux? - PullRequest
268 голосов
/ 14 мая 2010

Как мне перечислить всех членов группы в Linux (и, возможно, других объединений)?

Ответы [ 19 ]

233 голосов
/ 18 ноября 2011
getent group <groupname>;

Он переносим как в Linux, так и в Solaris и работает с локальными файлами групп / паролей, конфигурациями NIS и LDAP.

101 голосов
/ 14 мая 2010

К сожалению, нет хорошего, портативного способа сделать это, о котором я знаю. Если вы попытаетесь проанализировать / etc / group, как предлагают другие, вы будете скучать по пользователям, у которых эта группа является основной, и по всем, кто был добавлен в эту группу с помощью механизма, отличного от плоских файлов UNIX (например, LDAP, NIS, pam-pgsql и т. д.).

Если бы мне абсолютно необходимо было сделать это самому, я бы, вероятно, сделал это наоборот: используйте id, чтобы получить группы всех пользователей в системе (которые будут извлекать все источники, видимые для NSS), и использовать Perl или что-то похожее на ведение хеш-таблицы для каждой обнаруженной группы, отмечая членство этого пользователя.

Edit: Конечно, это оставляет вас с похожей проблемой: как получить список каждого пользователя в системе. Поскольку мое местоположение использует только плоские файлы и LDAP, я могу просто получить список из обоих местоположений, но это может или не может быть правдой для вашей среды.

Редактировать 2: Кто-то мимоходом напомнил мне, что getent passwd вернет список всех пользователей в системе, включая пользователей из LDAP / NIS / и т. Д., , но 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";
    }
}
39 голосов
/ 29 августа 2012

Используйте Python для вывода списка участников группы:

python -c "import grp; print grp.getgrnam ('GROUP_NAME') [3]"

См. https://docs.python.org/2/library/grp.html

39 голосов
/ 15 августа 2011
lid -g groupname | cut -f1 -d'(' 
25 голосов
/ 05 ноября 2013

Следующая команда выведет список всех пользователей, принадлежащих к <your_group_name>, но только тех, кто управляется базой данных /etc/group, а не LDAP, NIS и т. Д. Она также работает только для вторичных групп , она выиграла ' Перечислите пользователей, для которых эта группа установлена ​​в качестве основной, поскольку основная группа хранится как GID (числовой идентификатор группы) в файле /etc/passwd.

grep <your_group_name> /etc/group
16 голосов
/ 14 мая 2010

Следующая команда выведет список всех пользователей, принадлежащих к <your_group_name>, но только тех, кто управляется базой данных /etc/group, а не LDAP, NIS и т. Д. Она также работает только для дополнительных групп , она выиграла ' Перечислите пользователей, для которых эта группа установлена ​​в качестве основной, поскольку основная группа хранится как GID (числовой идентификатор группы) в файле /etc/passwd.

awk -F: '/^groupname/ {print $4;}' /etc/group
12 голосов
/ 30 января 2012

Следующий скрипт оболочки будет перебирать всех пользователей и печатать только те имена пользователей, которые принадлежат данной группе:

#!/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 для пользователей и групп (не только файлов passwd и group). Также будут учитываться пользователи, не добавленные в группу, но имеющие группу, установленную в качестве основной группы.

Редактировать: Добавлено исправление для редкого сценария, когда пользователь не принадлежит к группе с тем же именем.

Редактировать: написано в виде сценария оболочки; добавлено true для выхода со статусом 0 в соответствии с предложением @ Макс Черняк aka hakunin ; отбрасывается stderr, чтобы пропустить эти случайные groups: cannot find name for group ID xxxxxx.

6 голосов
/ 07 марта 2017

Вы можете сделать это в одной командной строке:

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

Команда выше перечисляет всех пользователей, имеющих имя_группы в качестве основной группы

Если вы также хотите перечислить пользователей, имеющих groupname в качестве своей вторичной группы, используйте следующую команду

getent group <groupname> | cut -d: -f4 |  tr ',' '\n'
3 голосов
/ 13 июля 2015

Я сделал это аналогично приведенному выше коду perl, но заменил getent и id на собственные функции perl. Это намного быстрее и должно работать с различными * 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";
3 голосов
/ 31 декабря 2013

Реализация 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";
    }
}

Если есть лучший способ поделиться этим предложением, пожалуйста, дайте мне знать; Я рассмотрел много способов, и это то, что я придумал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...