Come elencare tutti gli utenti in un gruppo Linux?


273

Come posso elencare tutti i membri di un gruppo in Linux (e possibilmente altri unices)?


1
@ Silmari89, non se lo vuole fare a livello di codice.
Paul Tomblin,

2
Sono nuovo qui, ho scoperto che SF esiste subito dopo aver pubblicato la domanda. Sono d'accordo che appartiene a SF o SO.
user323094,

5
Heh, ovviamente, ora ha una soluzione programmatica, quindi potrebbe essere giustificata anche qui.
Zed,

Risposte:


103

Sfortunatamente, non esiste un buon modo portatile per farlo che io conosca. Se tenti di analizzare / etc / group, come suggeriscono altri, ti mancheranno gli utenti che hanno quel gruppo come loro gruppo principale e chiunque sia stato aggiunto a quel gruppo tramite un meccanismo diverso dai file flat UNIX (ovvero LDAP, NIS, pam-pgsql, ecc.).

Se dovessi assolutamente farlo da solo, probabilmente lo farei al contrario: usare idper ottenere i gruppi di ogni utente sul sistema (che tirerà tutte le fonti visibili a NSS) e usare Perl o qualcosa di simile per mantenere un hash tabella per ciascun gruppo rilevata rilevando l'appartenenza di quell'utente.

Modifica: Naturalmente, questo ti lascia con un problema simile: come ottenere un elenco di tutti gli utenti sul sistema. Dal momento che la mia posizione utilizza solo file flat e LDAP, posso semplicemente ottenere un elenco da entrambe le posizioni, ma ciò può o meno essere vero per il tuo ambiente.

Modifica 2: Qualcuno di passaggio mi ha ricordato che getent passwdrestituirà un elenco di tutti gli utenti del sistema inclusi quelli di LDAP / NIS / ecc., Ma getent group continuerà comunque a mancare agli utenti membri solo tramite la voce di gruppo predefinita, quindi mi ha ispirato a scrivi questo trucco veloce.


#!/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
Grazie a tutti coloro che hanno risposto. Stavo cercando un modo portatile per farlo. Le tue informazioni secondo cui non esiste un modo semplice e portatile sono state utili. Mi hai anche dettagliato di più sulle circostanze che mi hanno aiutato a capire il problema più profondamente, lo apprezzo e ho scelto la tua risposta come accettata.
user323094,

2
Sarebbe possibile per te donare il tuo script alla fondazione Linux? È il 2012 e non esiste ancora un modo semplice per ottenere i membri di un gruppo. Questa è la cosa che mi frustra di Linux.
winteck,

6
Ho aggiunto una licenza simile a ISC per te, che dovrebbe essere compatibile con qualsiasi gruppo. Sentiti libero di inviarlo ovunque pensi che sarà accettato.
Zed,

PAM non fornisce informazioni sull'account. È l'interruttore del servizio dei nomi (nsswitch) che lo fa. Non tutti i "database" (fornitori di dati) supporteranno l'enumerazione, pertanto getent passwdpotrebbe non funzionare (se ad esempio si sta utilizzando sssd).

Punto valido su PAM vs NSS - Ho cambiato il riferimento. Anche se non l'ho usato, a prima vista sssd sembra una sostituzione nscd piuttosto che un fornitore di dati adeguato, e se si rompe getent passwdconsidererei un bug in sssd.
Zed,

239
getent group <groupname>;

È portatile su Linux e Solaris e funziona con file di gruppo / password locali, configurazioni NIS e LDAP.


43
Non mostra gli utenti che hanno il gruppo come gruppo predefinito.
rlpowell,


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

7
Questo sarebbe il modo migliore, tranne per il fatto che il coperchio non si trova in un'installazione Debian standard. In Ubuntu è nel pacchetto opzionale libuser (non è quello in id-utils con lo stesso nome). Non l'ho trovato in Debian :(
user323094

Ha funzionato per me su Scientific Linux
blong,

su Debian Wheezy, anche lid è sul pacchetto libuser
Lluís,

2
@JohnMcGehee RHEL avrebbe dovuto chiamarsi AustereLinux
goelakash,

1
'-g' non è un'opzione per me. Ho id-utils versione 4.6 installato su Ubuntu 16.04.
Wilson Biggs,

25

Il seguente comando elencherà tutti gli utenti appartenenti <your_group_name>, ma solo quelli gestiti dal /etc/groupdatabase, non LDAP, NIS, ecc. Funziona anche solo per gruppi secondari , non elencherà gli utenti che hanno quel gruppo impostato come primario poiché il gruppo primario è memorizzato come GID(ID gruppo numerico) nel file /etc/passwd.

grep <your_group_name> /etc/group

4
Puoi accedere direttamente a quel file come grep <nomeutente> / etc / group. Più veloce e meno sovraccarico.
paintbox,

16

Il seguente comando elencherà tutti gli utenti appartenenti <your_group_name>, ma solo quelli gestiti dal /etc/groupdatabase, non LDAP, NIS, ecc. Funziona anche solo per gruppi secondari , non elencherà gli utenti che hanno quel gruppo impostato come primario poiché il gruppo primario è memorizzato come GID(ID gruppo numerico) nel file /etc/passwd.

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

7
Non mostra gli utenti che hanno il gruppo come gruppo predefinito.
rlpowell,

3
Non controlla NIS e LDAP.
Paweł Nadolski,

12

Il seguente script di shell ripeterà tutti gli utenti e stamperà solo i nomi di utenti che appartengono a un determinato gruppo:

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

Esempio di utilizzo:

./script 'DOMAIN+Group Name'

Nota: questa soluzione controllerà NIS e LDAP per utenti e gruppi (non solo passwdegroup file). Considera anche gli utenti non aggiunti a un gruppo ma con gruppo impostato come gruppo primario.

Modificare: aggiunta correzione per uno scenario raro in cui l'utente non appartiene a un gruppo con lo stesso nome.

Modifica: scritto sotto forma di script di shell; aggiunto trueper uscire con lo 0stato come suggerito da @Max Chernyak aka hakunin ; scartato stderrper saltare quelli occasionali groups: cannot find name for group ID xxxxxx.


Questo è fantastico e molto conciso, ma stampa il nome del gruppo così come i nomi degli utenti
andrew lorien

@andrewlorien, spero di aver risolto il problema da te menzionato, altrimenti fornisci maggiori dettagli.
Paweł Nadolski,

Questo frammento è buono, ma restituisce il codice di uscita 1, qualche motivo per cui non restituisce 0? Facile soluzione forse?
Max Chernyak,

@hakunin, non restituisce 0 quando l'ultimo nome utente non appartiene al gruppo. Puoi aggiungere "|| true" all'istruzione end per ottenere sempre 0 se questo è quello che vuoi. È possibile controllare quindi l'output per vedere se è stato trovato un utente.
Paweł Nadolski,

@ PawełNadolski ho capito, quindi ho finito per aggiungere ; true. Restituire 0 è utile per evitare di far scattare il sistema di gestione della configurazione (Chef, Ansible, ecc.).
Max Chernyak,

7

Puoi farlo in una singola riga di comando:

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

Sopra il comando elenca tutti gli utenti che hanno nome gruppo come gruppo principale

Se si desidera anche elencare gli utenti con nome gruppo come gruppo secondario, utilizzare il comando seguente

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

1
Avvertenza: grepcorrisponderà a un utente il cui nome contiene il numero del gruppo (ad es. sc0ttVerrà mostrato come parte del rootgruppo). Se questo è un problema, usa regex :$(getent group <groupname> | cut -d: -f3)\$(corrisponde al punto e virgola, all'ID gruppo e alla fine della riga). (Non aggiungere citazioni al regex, o bash si lamenta.)
Scott Stevens,

@ScottS Un pit-fall legittimo. Consiglierei i passaggi consigliati
Bhavik,

3

solo un po 'grep e tr:

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

4
Non mostra gli utenti che hanno il gruppo come gruppo predefinito.
rlpowell,

3

L'implementazione di Zed dovrebbe probabilmente essere estesa per funzionare su alcuni degli altri principali UNIX.

Qualcuno ha accesso all'hardware Solaris o HP-UX ?; non ha testato quei casi.

#!/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";
    }
}

Se esiste un modo migliore per condividere questo suggerimento, per favore fatemi sapere; Ho considerato molti modi e questo è quello che mi è venuto in mente.


Confermato il lavoro su Solaris 10 dopo aver cambiato id -Gnin/usr/xpg4/bin/id -G -n
user667489

3

L'ho fatto in modo simile al codice perl sopra, ma ho sostituito getent e id con funzioni perl native. È molto più veloce e dovrebbe funzionare su diversi * nix sapori.

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

Una risposta con solo un collegamento non è considerata una buona risposta su Stack Overflow. Ti preghiamo di considerare di eliminare questo dato che non fornisce una risposta alla domanda o elabora di più su come questa risposta sia migliore della risposta accettata. Oppure puoi aggiungere questo come commento una volta che hai abbastanza reputazione. Puoi sempre commentare i tuoi post.
Dipen Shah,

2

Esiste un pratico pacchetto Debian e Ubuntu chiamato ' membri ' che fornisce questa funzionalità:

Descrizione: mostra i membri di un gruppo; per impostazione predefinita, tutti i membri membri sono il complemento dei gruppi: mentre i gruppi mostrano i gruppi a cui appartiene un utente specificato, i membri mostrano gli utenti appartenenti a un gruppo specificato.

... Puoi chiedere membri primari, membri secondari, entrambi su una riga, ciascuno su righe separate.


Cosa succede se l'op usa openwrt?
user2284570,

Pratico davvero, ma purtroppo non segnala i membri del gruppo di dominio.
simlev

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

Questo restituisce un elenco separato da spazi di utenti che ho usato negli script per popolare le matrici.

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

o

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

0

Ecco uno script che restituisce un elenco di utenti da / etc / passwd e / etc / group che non controlla NIS o LDAP, ma mostra agli utenti che hanno il gruppo come gruppo predefinito Testato su Debian 4.7 e 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

o come una riga puoi tagliare e incollare direttamente da qui (cambia il nome del gruppo nella prima variabile)

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

In UNIX (al contrario di GNU / Linux), c'è il comando listusers. Vedere la pagina man di Solaris per listusers .

Nota che questo comando fa parte del progetto Heirloom open source . Presumo che manchi da GNU / Linux perché RMS non crede nei gruppi e nelle autorizzazioni. :-)


1
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
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,

Dal sito web del Progetto Heirloom: Il Progetto Heirloom fornisce implementazioni tradizionali di utility Unix standard. In molti casi, sono stati derivati ​​dal materiale Unix originale rilasciato come Open Source da Caldera e Sun. Le interfacce seguono la pratica tradizionale; rimangono generalmente compatibili con System V, anche se a volte vengono fornite estensioni che sono diventate di uso comune nel corso del tempo. La maggior parte delle utility sono anche incluse in una variante che mira alla conformità POSIX.
Alun Carr,

0

Ecco uno script awk molto semplice che tiene conto di tutte le insidie ​​comuni elencate nelle altre risposte:

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

Lo sto usando con la mia configurazione abilitata per ldap, funziona su qualsiasi cosa con getent & awk conforme agli standard, inclusi solaris 8+ e hpux.


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

Questo ha 3 parti:

1 - getent group groupnamemostra la linea del gruppo nel file "/ etc / group". Alternativa a cat /etc/group | grep groupname.

2 - awkstampa sono solo i membri in un'unica riga separati da ','.

3 - trsostituisci "," con una nuova riga e stampa ogni utente di fila.

4 - Opzionale: è anche possibile utilizzare un'altra pipe con sort, se gli utenti sono troppi.

Saluti


0

Penso che il modo più semplice sia la seguente procedura, non sarà necessario installare alcun pacchetto o software:

  1. Innanzitutto, scopri il GID del gruppo che vuoi conoscere gli utenti, ci sono molti modi per farlo: cat / etc / group (l'ultima colonna è il GID) id user (l'utente è qualcuno a cui appartiene il gruppo)

  2. Ora elencherai tutti gli utenti sul file / etc / passwd, ma applicherai alcuni filtri con il seguente seguito di comandi per ottenere solo i membri del gruppo precedente.

cut -d: -f1,4 / etc / passwd | grep GID (il GID è il numero ottenuto dal passaggio 1)

Il comando cut selezionerà solo alcune "colonne" del file, il parametro d imposta il delimitatore ":" in questo caso, il parametro -f seleziona i "campi" (o colonne) da mostrare 1 e 4 in maiuscolo (on il file / etc / passwd, la colonna 1º è il nome dell'utente e il 4º è il GID del gruppo a cui appartiene l'utente, per finalizzare il GID | grep filtrerà solo il gruppo (sulla colonna 4º) che aveva scelto.


0

Ecco un altro one-liner di Python che tiene conto dell'appartenenza al gruppo predefinita dell'utente (da /etc/passwd) e del database del gruppo ( /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

Ho provato grep 'sample-group-name' /etc/group, che elencherà tutti i membri del gruppo specificato in base all'esempio qui


1
Grepping /etc/groupè già in almeno altre 3 risposte, quale valore aggiunge la tua risposta? Inoltre, tutte quelle altre risposte hanno commenti sul fatto che tale soluzione funziona solo per gruppi secondari e non funziona anche per account gestiti da LDAP, NIS, ecc.
David Ferenczy Rogožan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.