Jak wyświetlić listę wszystkich użytkowników w grupie Linux?

273

Jak wyświetlić listę wszystkich członków grupy w systemie Linux (i ewentualnie innych jednorożców)?

użytkownik323094
źródło
1
@ Silmari89, Nie, jeśli chce to zrobić programowo.
Paul Tomblin
2
Jestem tu nowy, dowiedziałem się, że SF istnieje zaraz po tym, jak opublikowałem pytanie. Zgadzam się, że należy do SF lub SO.
user323094
5
Heh, oczywiście, teraz ma programowe rozwiązanie, więc i tutaj może być uzasadnione.
Zed

Odpowiedzi:

103

Niestety, nie ma dobrego, przenośnego sposobu na zrobienie tego, o czym wiem. Jeśli spróbujesz parsować plik / etc / group, jak sugerują inni, przegapisz użytkowników, którzy mają tę grupę jako grupę podstawową, oraz każdego, kto został dodany do tej grupy za pomocą mechanizmu innego niż pliki płaskie UNIX (tj. LDAP, NIS, pam-pgsql itp.).

Gdybym absolutnie musiał to zrobić sam, prawdopodobnie zrobiłbym to w odwrotnym kierunku: użyj, idaby uzyskać grupy każdego użytkownika w systemie (który ściągnie wszystkie źródła widoczne dla NSS), i użyj Perla lub czegoś podobnego do utrzymania skrótu tabela dla każdej wykrytej grupy z podaniem członkostwa tego użytkownika.

Edycja: Oczywiście pozostawia to podobny problem: jak uzyskać listę każdego użytkownika w systemie. Ponieważ moja lokalizacja używa tylko płaskich plików i LDAP, mogę po prostu uzyskać listę z obu lokalizacji, ale może to być prawda lub nie dla twojego środowiska.

Edycja 2: Ktoś przechodzący przypomniał mi, że getent passwdzwróci listę wszystkich użytkowników w systemie, w tym użytkowników z LDAP / NIS / itp., Ale getent group nadal będzie tęsknił za użytkownikami będącymi członkami tylko poprzez domyślny wpis grupy, więc zainspirowało mnie to do napisz ten szybki hack.


#!/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 ([email protected] or [email protected])
#
# 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";
    }
}
Zed
źródło
3
Dziękujemy wszystkim, którzy odpowiedzieli. Szukałem przenośnego sposobu na zrobienie tego. Twoja informacja, że ​​nie ma łatwego i przenośnego sposobu, była pomocna. Uściśliłeś również najbardziej okoliczności, które pomogły mi głębiej zrozumieć problem, doceniam to i wybrałem twoją odpowiedź jako zaakceptowaną.
user323094
2
Czy byłoby możliwe przekazanie skryptu fundacji Linux? Jest rok 2012 i nadal nie ma łatwego sposobu na pozyskanie członków grupy. Właśnie to frustruje mnie w Linuksie.
winteck
6
Dodałem dla ciebie licencję podobną do ISC, która powinna być kompatybilna z prawie każdą grupą. Prześlij go w dowolnym miejscu, w którym uważasz, że zostanie zaakceptowane.
Zed
PAM nie podaje informacji o koncie. To robi przełącznik usługi nazw (nsswitch), który to robi. Nie wszystkie „bazy danych” (dostawcy danych) obsługują wyliczanie, więc getent passwdmogą nie działać (jeśli na przykład używasz sssd).
Ważny punkt dotyczący PAM vs NSS - zmieniłem odniesienie. Chociaż go nie użyłem, sssd na pierwszy rzut oka wygląda jak zamiennik nscd, a nie odpowiedni dostawca danych, a jeśli się zepsuje getent passwd, uznałbym to za błąd w sssd.
Zed
239
getent group <groupname>;

Jest przenośny zarówno w systemie Linux, jak i Solaris i współpracuje z lokalnymi plikami grup / haseł, konfiguracjami NIS i LDAP.

Josh H.
źródło
43
Nie pokazuje użytkowników, którzy mają grupę jako grupę domyślną.
rlpowell
40

Użyj Pythona, aby wyświetlić członków grupy:

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

Zobacz https://docs.python.org/2/library/grp.html

Narayanaperumal Gurusamy
źródło
1
Niestety nie zgłasza członków grupy domen.
simlev
39
lid -g groupname | cut -f1 -d'(' 
Notatka
źródło
7
Byłby to najpiękniejszy sposób, z wyjątkiem tego, że lid nie jest w standardowej instalacji Debiana. W Ubuntu jest w opcjonalnym pakiecie libuser (nie jest to ten w id-utils o tej samej nazwie). Nie znalazłem go w Debianie :(
user323094,
Pracowałem dla mnie w Scientific Linux
blong
na Debianie Wheezy, lid jest również na pakiecie libuser
Lluís
2
@JohnMcGehee RHEL powinien był nazywać się AustereLinux
goelakash,
1
„-g” nie jest dla mnie opcją. Mam wersję id-utils 4.6 zainstalowaną na Ubuntu 16.04.
Wilson Biggs,
25

Następujące polecenie wyświetli listę wszystkich użytkowników należących do <your_group_name>, ale tylko tych zarządzanych przez /etc/groupbazę danych, a nie LDAP, NIS itp. Działa również tylko dla grup drugorzędnych , nie wyświetli listy użytkowników, dla których ta grupa jest ustawiona jako podstawowa, ponieważ grupa podstawowa to przechowywane jako GID(numeryczny identyfikator grupy) w pliku /etc/passwd.

grep <your_group_name> /etc/group
Jose Bagatelli
źródło
4
Możesz grep bezpośrednio do tego pliku, takiego jak grep <nazwa użytkownika> / etc / group. Szybszy i mniejszy narzut.
paintbox
16

Następujące polecenie wyświetli listę wszystkich użytkowników należących do <your_group_name>, ale tylko tych zarządzanych przez /etc/groupbazę danych, a nie LDAP, NIS itp. Działa również tylko dla grup drugorzędnych , nie wyświetli listy użytkowników, dla których ta grupa jest ustawiona jako podstawowa, ponieważ grupa podstawowa to przechowywane jako GID(numeryczny identyfikator grupy) w pliku /etc/passwd.

awk -F: '/^groupname/ {print $4;}' /etc/group
Didier Trosset
źródło
7
Nie pokazuje użytkowników, którzy mają grupę jako grupę domyślną.
rlpowell
3
Nie sprawdza NIS i LDAP.
Paweł Nadolski
12

Poniższy skrypt powłoki wykona iterację przez wszystkich użytkowników i wydrukuje tylko te nazwy użytkowników, które należą do danej grupy:

#!/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

Przykład użycia:

./script 'DOMAIN+Group Name'

Uwaga: To rozwiązanie sprawdzi NIS i LDAP dla użytkowników i grup (nie tylko passwdi grouppliki). Uwzględnia również użytkowników, którzy nie zostali dodani do grupy, ale ustawili ją jako grupę podstawową.

Edycja: Dodano poprawkę do rzadkiego scenariusza, w którym użytkownik nie należy do grupy o tej samej nazwie.

Edycja: napisane w formie skryptu powłoki; dodano, trueaby wyjść ze 0statusem sugerowanym przez @Max Chernyak aka hakunin ; odrzucane stderr, aby czasami je pominąć groups: cannot find name for group ID xxxxxx.

Paweł Nadolski
źródło
Jest to świetne i bardzo zwięzłe, ale drukuje zarówno nazwę grupy, jak i nazwy użytkowników
andrew lorien
@andrewlorien, mam nadzieję, że rozwiązałem problem, o którym wspomniałeś, jeśli nie, podaj więcej szczegółów.
Paweł Nadolski,
Ten fragment kodu jest dobry, ale zwraca kod wyjścia 1, czy jest jakiś powód, dla którego nie zwraca 0? Może łatwa naprawa?
Max Chernyak
@ hakunin, nie zwraca 0, gdy ostatnia nazwa użytkownika nie należy do grupy. Możesz dołączyć „|| true” na końcu instrukcji, aby zawsze otrzymać 0, jeśli tego właśnie chcesz. Następnie możesz sprawdzić dane wyjściowe, aby sprawdzić, czy znaleziono dowolnego użytkownika.
Paweł Nadolski
@ PawełNadolski Zdałem sobie sprawę, więc ostatecznie dodałem ; true. Zwrócenie 0 jest dobre, aby uniknąć wyzwolenia systemu zarządzania konfiguracją (Chef, Ansible itp.).
Max Chernyak
7

Możesz to zrobić w jednym wierszu poleceń:

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

Powyższe polecenie wyświetla listę wszystkich użytkowników, których nazwa grupy jest grupą podstawową

Jeśli chcesz również wymienić użytkowników mających nazwę grupy jako grupę drugorzędną, użyj następującego polecenia

getent group <groupname> | cut -d: -f4 |  tr ',' '\n'
Bhavik
źródło
1
Zastrzeżenie: grepdopasuje użytkownika, którego nazwa zawiera numer grupy (np. sc0ttBędzie wyświetlana jako część rootgrupy). Jeśli jest to problem, użyj wyrażenia regularnego :$(getent group <groupname> | cut -d: -f3)\$(pasuje do średnika, identyfikatora grupy i końca linii). (Nie dodawaj cudzysłowów do wyrażenia regularnego, ani bash narzeka.)
Scott Stevens
@ScottS A leg pit-fall. Poleciłbym sugerowane kroki
Bhavik
3

tylko trochę grep i tr:

$ grep ^$GROUP /etc/group | grep -o '[^:]*$' | tr ',' '\n'
user1
user2
user3
osti
źródło
4
Nie pokazuje użytkowników, którzy mają grupę jako grupę domyślną.
rlpowell
3

Implementacja Zeda powinna prawdopodobnie zostać rozszerzona na niektóre inne ważne systemy UNIX.

Czy ktoś ma dostęp do sprzętu Solaris lub HP-UX ?; nie testowałem tych przypadków.

#!/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 ([email protected] or [email protected])
#
# 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";
    }
}

Jeśli istnieje lepszy sposób podzielenia się tą sugestią, daj mi znać; Rozważyłem wiele sposobów i właśnie to wymyśliłem.

Billy McCloskey
źródło
Potwierdzono pracę na Solarisie 10 po zmianie id -Gnna/usr/xpg4/bin/id -G -n
user667489,
3

Zrobiłem to podobnie do powyższego kodu perla, ale zastąpiłem getent i id natywnymi funkcjami perla. Jest o wiele szybszy i powinien działać w różnych smakach * 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";
tak pomylone
źródło
Odpowiedź zawierająca tylko łącze nie jest uważana za dobrą odpowiedź w przypadku przepełnienia stosu. Proszę rozważyć usunięcie tego, ponieważ nie daje to odpowiedzi na pytanie ani nie wyjaśnia, w jaki sposób ta odpowiedź jest lepsza niż odpowiedź zaakceptowana. Możesz też dodać to jako komentarz, gdy masz wystarczającą reputację. Zawsze możesz komentować własne posty.
Dipen Shah,
2

Istnieje przydatny pakiet Debian i Ubuntu o nazwie „ członkowie ”, który zapewnia tę funkcjonalność:

Opis: pokazuje członków grupy; domyślnie wszyscy członkowie są uzupełnieniem grup: podczas gdy grupy pokazują grupy, do których należy określony użytkownik, członkowie pokazują użytkowników należących do określonej grupy.

... Możesz poprosić o członków pierwotnych, członków drugorzędnych, oba w jednym wierszu, każdy w osobnych wierszach.

Andrzej
źródło
Co jeśli operacja użyje openwrt?
user2284570,
Przydatne, ale niestety nie zgłasza członków grupy domen.
simlev
1
getent group insert_group_name_here | awk -F ':' '{print $4}' | sed 's|,| |g'

Zwraca rozdzieloną spacjami listę użytkowników, których użyłem w skryptach do zapełniania tablic.

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

lub

userarray+=("$(getent group GROUPNAME | awk -F ':' '{print $4}' | sed 's|,| |g')")
parsecpython
źródło
0

Oto skrypt, który zwraca listę użytkowników z / etc / passwd i / etc / group, nie sprawdza NIS ani LDAP, ale pokazuje użytkowników, którzy mają grupę jako grupę domyślną Testowane na Debianie 4.7 i 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

lub jako linijka możesz wycinać i wklejać stąd (zmień nazwę grupy w pierwszej zmiennej)

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
Andrew Lorien
źródło
0

W UNIX (w przeciwieństwie do GNU / Linux) dostępna jest komenda listusers. Listusers można znaleźć na stronie podręcznika Solaris .

Zauważ, że to polecenie jest częścią projektu Heirloom Open Source . Zakładam, że brakuje go w GNU / Linux, ponieważ RMS nie wierzy w grupy i uprawnienia. :-)

Alun Carr
źródło
1
Chociaż ten link może odpowiedzieć na pytanie, lepiej jest dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie. - Z recenzji
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.
Alun Carr
Ze strony internetowej Heirloom Project: Heirloom Project zapewnia tradycyjne implementacje standardowych narzędzi uniksowych. W wielu przypadkach pochodzą one z oryginalnego materiału uniksowego wydanego jako Open Source przez Calderę i Sun. Interfejsy są zgodne z tradycyjną praktyką; pozostają one ogólnie kompatybilne z Systemem V, chociaż czasami udostępniane są rozszerzenia, które z czasem stały się powszechne. Większość narzędzi znajduje się również w wariancie, którego celem jest zgodność z POSIX.
Alun Carr
0

Oto bardzo prosty skrypt awk, który uwzględnia wszystkie typowe pułapki wymienione w innych odpowiedziach:

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}'

Używam tego z moją konfiguracją z obsługą ldap, działa na każdym sprzęcie zgodnym ze standardami getent & awk, w tym Solaris 8+ i HPux.

yunake
źródło
0
getent group groupname | awk -F: '{print $4}' | tr , '\n'

Składa się z 3 części:

1 - getent group groupnamepokazuje linię grupy w pliku „/ etc / group”. Alternatywa dla cat /etc/group | grep groupname.

2 - awkprint to tylko elementy w jednym wierszu z oddzielnym „,”.

3 - trzamień „,” na nowy wiersz i wypisz każdego użytkownika z rzędu.

4 - Opcjonalnie: Możesz również użyć innej rury sort, jeśli użytkowników jest zbyt wielu.

pozdrowienia

ioaniatr
źródło
0

Myślę, że najprostszym sposobem są następujące kroki, nie trzeba instalować żadnego pakietu ani oprogramowania:

  1. Najpierw dowiadujesz się o GID grupy, którą chcesz znać użytkowników, jest na to wiele sposobów: cat / etc / group (ostatnia kolumna to GID) id użytkownik (użytkownik to ktoś, kto należy do Grupa)

  2. Teraz wyświetlisz listę wszystkich użytkowników w pliku / etc / passwd, ale zastosujesz niektóre filtry z następującą sekwencją poleceń, aby uzyskać tylko członków poprzedniej grupy.

cut -d: -f1,4 / etc / passwd | grep GID (GID to liczba uzyskana z kroku 1)

polecenie cut wybierze tylko niektóre „kolumny” pliku, parametr d ustawia ogranicznik „:” w tym przypadku parametr -f wybiera „pola” (lub kolumny), które mają być pokazane 1 i 4 w przypadku (na plik / etc / passwd, kolumna 1º to nazwa użytkownika, a 4º to GID grupy, do której należy użytkownik), aby sfinalizować GID | grep filtruje tylko grupę (w kolumnie 4º), którą wybrał.

Mauro Matsudo
źródło
0

Oto kolejna linijka Pythona, która uwzględnia domyślne członkostwo użytkownika w grupie (od /etc/passwd), a także z bazy danych grupy ( /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]])"
Brian Minton
źródło
-1

Próbowałem grep 'sample-group-name' /etc/group, aby wyświetlić listę wszystkich członków grupy, którą określiłeś na podstawie przykładu tutaj

Jameshwart Lopez
źródło
1
Grepping /etc/groupjest już w co najmniej 3 innych odpowiedziach, jaką wartość dodaje do nich twoja odpowiedź? Ponadto wszystkie pozostałe odpowiedzi mają komentarze, że takie rozwiązanie działa tylko dla grup drugorzędnych, a także nie działa dla konta zarządzanego przez LDAP, NIS itp.
David Ferenczy Rogožan,