Як перелічити всіх користувачів групи Linux?


273

Як мені перелічити всіх членів групи в Linux (і, можливо, інших уніксах)?


1
@ Silmari89, не якщо він хоче це робити програмно.
Пол Томблін

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

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
Дякую всім, хто відповів. Я шукав портативний спосіб це зробити. Ваша інформація про те, що існує не простий і портативний спосіб, була корисною. Ви також детально описували обставини, які допомогли мені глибше зрозуміти проблему, я ціную це і вибрав вашу відповідь як прийняту.
користувач323094

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
Це було б найприємніше, за винятком того, що кришка не знаходиться в стандартній установці Debian. В Ubuntu він знаходиться в додатковому пакеті libuser (це не той, який знаходиться в однойменних id-utils). Я не знайшов його в Debian :(
user323094

Працював для мене в науковому Linux
вибух

на Debian Wheezy, кришка також у пакеті лібузера
Lluís

2
@JohnMcGehee RHEL повинні були називатися AustereLinux
goelakash

1
'-g' - це не варіант для мене. У мене на Ubuntu 16.04 встановлена ​​id-utils версії 4.6.
Вілсон Біггс

25

У наступній команді будуть перераховані всі користувачі, які належать <your_group_name>, але лише ті, якими керується /etc/groupбаза даних, а не LDAP, NIS тощо. Також вона працює лише для вторинних груп , вона не буде перераховувати користувачів, у яких ця група встановлена ​​як основна, оскільки первинна група є зберігається як GID(числовий ідентифікатор групи) у файлі /etc/passwd.

grep <your_group_name> /etc/group

4
Ви можете отримати папку безпосередньо до цього файлу, наприклад, grep <ім'я користувача> / тощо / group. Швидше і менше накладних витрат.
фарба

16

Наступна команда відображатиме список усіх користувачів, які належать <your_group_name>, але лише ті, якими керується /etc/groupбаза даних, а не LDAP, NIS тощо. Також вона працює лише для вторинних груп , вона не буде перераховувати користувачів, у яких ця група встановлена ​​як основна, оскільки первинна група є зберігається як GID(числовий ідентифікатор групи) у файлі /etc/passwd.

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

7
Не відображає користувачів, які мають групу як свою за замовчуванням.
rlpowell

3
Не перевіряє NIS та LDAP.
Paweł Nadolski

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.


Це чудово і дуже стисло, але він друкує назву групи, а також імена користувачів
andrew lorien

@andrewlorien, я сподіваюся, що я вирішив проблему, яку ви згадуєте, якщо не, будь ласка, надайте більше деталей.
Paweł Nadolski

Цей фрагмент хороший, але він повертає вихідний код 1, будь-яка причина, чому він не повертає 0? Легке виправлення, можливо?
Макс Черняк

@hakunin, він не повертає 0, коли прізвище користувача не належить до групи. Ви можете додати "|| true" в кінцевому твердженні, щоб завжди отримувати 0, якщо це те, що ви хочете. Ви можете перевірити потім вихід, щоб побачити, чи знайдено якогось користувача.
Paweł Nadolski

@ PawełNadolski Я зрозумів, тому закінчив додавати ; true. Повернення 0 добре, щоб уникнути відключення вашої системи управління конфігурацією (шеф-кухар, відповідь тощо).
Макс Черняк

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
Caveat: grepвідповідатиме користувачеві, ім'я якого містить номер групи (наприклад, sc0ttбуде показано як частину rootгрупи). Якщо це проблема, то використовуйте регулярний вираз :$(getent group <groupname> | cut -d: -f3)\$(відповідає крапці з комою, ідентифікатором групи та кінці рядка). (Не додайте лапок до регулярного виразу, або баш скаржиться.)
Скотт Стівенс

@ScottS Законний піт-падіння. Рекомендую запропоновані кроки
Бхавік

3

лише трохи греп і тр:

$ 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?
користувач2284570

Дійсно, але, на жаль, не повідомляється про членів доменної групи.
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. Перегляньте список користувачів 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. Інтерфейси відповідають традиційній практиці; вони залишаються загально сумісними із системою 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 користувача (користувач - хтось, хто належить група)

  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 тощо.
Девід Ференчі Рогожан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.