Как составить список всех пользователей в группе Linux?


273

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


1
@ Silmari89, Нет, если он хочет сделать это программно.
Пол Томблин

2
Я новичок здесь, я узнал, что SF существует сразу после того, как я отправил вопрос. Я согласен, что он принадлежит либо SF, либо SO.
user323094

5
Хех, конечно, теперь у него есть программное решение, так что и здесь это может быть оправдано.
Зед

Ответы:


103

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

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

Изменить: Конечно, это оставляет вас с похожей проблемой: как получить список каждого пользователя в системе. Поскольку мое местоположение использует только плоские файлы и 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";
    }
}

3
Спасибо всем, кто ответил. Я искал портативный способ сделать это. Ваша информация о том, что нет простого и переносимого способа, была полезна Вы также подробно рассказали об обстоятельствах, которые помогли мне глубже понять проблему, я ценю это и выбрал ваш ответ в качестве принятого.
user323094

2
Вы могли бы пожертвовать свой сценарий в фонд Linux? Это 2012 год, и до сих пор нет простого способа получить членов группы. Это то, что разочаровывает меня в Linux.
winteck

6
Я добавил ISC-подобную лицензию для вас, которая должна быть совместима практически с любой группой. Не стесняйтесь подавать его везде, где, по вашему мнению, оно будет принято.
Зед

PAM не предоставляет информацию об учетной записи. Это делает переключатель службы имен (nsswitch). Не все «базы данных» (поставщики данных) будут поддерживать перечисление, поэтому getent passwdмогут не работать (если, например, вы используете sssd).

Действительный пункт о PAM против NSS - я изменил ссылку. Хотя я не использовал его, на первый взгляд sssd выглядит как замена nscd, а не как должный поставщик данных, и если он сломается, getent passwdя бы посчитал это ошибкой в ​​sssd.
Зед

239
getent group <groupname>;

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


43
Не показывает пользователей, которые имеют группу в качестве группы по умолчанию.
rlpowell


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

7
Это был бы самый хороший способ, за исключением того, что lid отсутствует в стандартной установке Debian. В Ubuntu он находится в необязательном пакете libuser (он не в id-utils с тем же именем). Я не нашел его в Debian :(
user323094

Работал для меня на Scientific Linux
blong

на Debian Wheezy, крышка тоже на пакете libuser
Lluís

2
@JohnMcGehee RHEL должен был называться AustereLinux
goelakash

1
«-g» не вариант для меня. У меня установлена ​​версия id-utils 4.6 в Ubuntu 16.04.
Уилсон Биггс

25

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

grep <your_group_name> /etc/group

4
Вы можете использовать grep непосредственно в этот файл, например, grep <username> / etc / group. Быстрее и меньше накладных расходов.
Paintbox

16

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

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

7
Не показывает пользователей, которые имеют группу в качестве группы по умолчанию.
rlpowell

3
Не проверяет NIS и LDAP.
Павел Надольский

12

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

#!/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статусом, предложенным @Max Chernyak aka hakunin ; отбрасывается stderr, чтобы пропустить те случайные groups: cannot find name for group ID xxxxxx.


Это здорово и очень кратко, но в нем напечатаны имя группы и имена пользователей
Эндрю Лориен

@andrewlorien, надеюсь, я исправил упомянутую вами проблему, если нет, пожалуйста, предоставьте более подробную информацию.
Павел Надольский

Этот фрагмент хорош, но он возвращает код выхода 1, есть ли причина, по которой он не возвращает 0? Легко ли это исправить?
Макс Черняк

@hakunin, он не возвращает 0, когда последнее имя пользователя не принадлежит группе. Вы можете добавить «|| true» в конце оператора, чтобы всегда получать 0, если это то, что вы хотите. Вы можете проверить вывод, чтобы увидеть, был ли найден какой-либо пользователь.
Павел Надольский

@ PawełNadolski Я понял, так что в итоге добавил ; true. Возвращать 0 - это хорошо, чтобы избежать отключения вашей системы управления конфигурацией (Chef, Ansible и т. Д.).
Макс Черняк

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)\$(соответствует точке с запятой, идентификатору группы и концу строки). (Не добавляйте цитаты к регулярному выражению, или Баш жалуется.)
Скотт Стивенс

@ Скоттс Законное падение. Рекомендовал бы предложенные шаги
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";
    }
}

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


Подтвердили работу на Solaris 10 после перехода id -Gnна/usr/xpg4/bin/id -G -n
user667489

3

Я сделал это аналогично приведенному выше коду 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";

Ответ со ссылкой только не считается хорошим ответом при переполнении стека. Пожалуйста, рассмотрите возможность удаления этого, поскольку это не дает ответа на вопрос или более подробно о том, как этот ответ лучше принятого ответа. Или вы можете добавить это как комментарий, как только у вас будет достаточно репутации. Вы всегда можете комментировать свои собственные сообщения.
Дипен Шах

2

Существует удобный пакет Debian и Ubuntu, называемый ' members ', который обеспечивает эту функциональность:

Описание: показывает участников группы; по умолчанию все члены-члены являются дополнением к группам: в то время как группы показывают группы, к которым принадлежит указанный пользователь, участники показывают пользователей, принадлежащих к указанной группе.

... Вы можете запросить первичных, вторичных участников, как на одной строке, так и на каждой отдельной строке.


Что если в опе используется openwrt?
user2284570 13.12.15

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

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. См. Справочную страницу Solaris для пользователей списков .

Обратите внимание, что эта команда является частью проекта Heirloom с открытым исходным кодом . Я предполагаю, что это отсутствует в 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: Проект Heirloom предоставляет традиционные реализации стандартных утилит Unix. Во многих случаях они были получены из оригинального материала Unix, выпущенного Caldera и Sun как Open Source. Интерфейсы следуют традиционной практике; в целом они остаются совместимыми с 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'

Это имеет 3 части:

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 user (пользователь - это тот, кто принадлежит группа)

  2. Теперь вы перечислите всех пользователей в файле / etc / passwd, но вы примените некоторые фильтры со следующим набором команд, чтобы получить только членов предыдущей группы.

cut -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
Грэппинг уже /etc/groupесть как минимум в 3 других ответах, какую ценность ваш ответ добавляет к ним? Кроме того, все остальные ответы содержат комментарии о том, что такое решение работает только для вторичных групп, а также не для учетной записи, управляемой LDAP, NIS и т. Д.
David Ferenczy Rogožan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.