Come posso elencare tutti i membri di un gruppo in Linux (e possibilmente altri unices)?
Come posso elencare tutti i membri di un gruppo in Linux (e possibilmente altri unices)?
Risposte:
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 id
per 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 passwd
restituirà 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";
}
}
getent passwd
potrebbe non funzionare (se ad esempio si sta utilizzando sssd).
getent passwd
considererei un bug in sssd.
Usa Python per elencare i membri del gruppo:
python -c "import grp; print grp.getgrnam ('GROUP_NAME') [3]"
lid -g groupname | cut -f1 -d'('
Il seguente comando elencherà tutti gli utenti appartenenti <your_group_name>
, ma solo quelli gestiti dal /etc/group
database, 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
Il seguente comando elencherà tutti gli utenti appartenenti <your_group_name>
, ma solo quelli gestiti dal /etc/group
database, 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
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 passwd
egroup
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 true
per uscire con lo 0
stato come suggerito da @Max Chernyak aka hakunin ; scartato stderr
per saltare quelli occasionali groups: cannot find name for group ID xxxxxx
.
; true
. Restituire 0 è utile per evitare di far scattare il sistema di gestione della configurazione (Chef, Ansible, ecc.).
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'
grep
corrisponderà a un utente il cui nome contiene il numero del gruppo (ad es. sc0tt
Verrà mostrato come parte del root
gruppo). 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.)
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.
id -Gn
in/usr/xpg4/bin/id -G -n
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";
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.
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')")
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
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. :-)
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.
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.
getent group groupname | awk -F: '{print $4}' | tr , '\n'
Questo ha 3 parti:
1 - getent group groupname
mostra la linea del gruppo nel file "/ etc / group". Alternativa a cat /etc/group | grep groupname
.
2 - awk
stampa sono solo i membri in un'unica riga separati da ','.
3 - tr
sostituisci "," 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
Penso che il modo più semplice sia la seguente procedura, non sarà necessario installare alcun pacchetto o software:
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)
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.
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]])"
Ho provato grep 'sample-group-name' /etc/group
, che elencherà tutti i membri del gruppo specificato in base all'esempio qui
/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.