¿Cómo enumerar todos los usuarios en un grupo de Linux?


273

¿Cómo enumero a todos los miembros de un grupo en Linux (y posiblemente otros unices)?


1
@ Silmari89, no si quiere hacerlo programáticamente.
Paul Tomblin

2
Soy nuevo aquí, descubrí que SF existe justo después de publicar la pregunta. Estoy de acuerdo en que pertenece a SF o SO.
user323094

55
Je, por supuesto, ahora tiene una solución programática, por lo que también podría justificarse aquí.
Zed

Respuestas:


103

Desafortunadamente, no hay una forma buena y portátil de hacer esto que yo sepa. Si intenta analizar / etc / group, como sugieren otros, extrañará a los usuarios que tienen ese grupo como su grupo principal y a cualquiera que se haya agregado a ese grupo a través de un mecanismo que no sea archivos planos UNIX (es decir, LDAP, NIS, pam-pgsql, etc.).

Si tuviera que hacer esto por mí mismo, probablemente lo haría a la inversa: use idpara obtener los grupos de cada usuario en el sistema (que extraerá todas las fuentes visibles para NSS) y use Perl o algo similar para mantener un hash tabla para cada grupo descubierto observando la pertenencia de ese usuario.

Editar: Por supuesto, esto te deja con un problema similar: cómo obtener una lista de cada usuario en el sistema. Dado que mi ubicación usa solo archivos planos y LDAP, puedo obtener una lista de ambas ubicaciones, pero eso puede o no ser cierto para su entorno.

Edición 2: alguien de pasada me recordó que getent passwddevolverá una lista de todos los usuarios en el sistema, incluidos los de LDAP / NIS / etc., pero getent group aún extrañará a los usuarios que son miembros solo a través de la entrada de grupo predeterminada, por lo que me inspiró a escribe este truco rápido


#!/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
Gracias a todos los que respondieron. Estaba buscando una forma portátil de hacerlo. Su información de que no hay una manera fácil y portátil fue útil. También detallaste más sobre las circunstancias que me ayudaron a entender el problema más profundamente, lo aprecio y elegí tu respuesta como la aceptada.
user323094

2
¿Sería posible que donaras tu script a la fundación Linux? Es 2012 y todavía no hay una manera fácil de obtener los miembros de un grupo. Eso es lo que me frustra de Linux.
winteck

66
Agregué una licencia similar a ISC para usted, que debería ser compatible con casi cualquier grupo. Siéntase libre de enviarlo a cualquier lugar que piense que será aceptado.
Zed

PAM no proporciona información de la cuenta. Es el conmutador de servicio de nombres (nsswitch) que hace eso. No todas las 'bases de datos' (proveedores de datos) admitirán la enumeración, por lo que es getent passwdposible que no funcionen (si, por ejemplo, está utilizando sssd).

Punto válido sobre PAM vs NSS - Cambié la referencia. Aunque no lo he usado, sssd parece un reemplazo de nscd a primera vista en lugar de un proveedor de datos adecuado, y si se rompe getent passwd, lo consideraría un error en sssd.
Zed

239
getent group <groupname>;

Es portátil en Linux y Solaris, y funciona con archivos de grupo / contraseña local, NIS y configuraciones LDAP.


43
No muestra a los usuarios que tienen el grupo como su grupo predeterminado.
rlpowell


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

77
Esta sería la mejor manera, excepto que la tapa no está en una instalación estándar de Debian. En Ubuntu está en el paquete opcional libuser (no es el de id-utils con el mismo nombre). No lo encontré en Debian :(
user323094

Trabajó para mí en Scientific Linux
blong

en Debian Wheezy, la tapa también está en el paquete libuser
Lluís

2
@JohnMcGehee RHEL debería haberse llamado AustereLinux
goelakash

1
'-g' no es una opción para mí. Tengo id-utils versión 4.6 instalada en Ubuntu 16.04.
Wilson Biggs

25

El siguiente comando enumerará todos los usuarios que pertenecen <your_group_name>, pero solo aquellos administrados por la /etc/groupbase de datos, no LDAP, NIS, etc. También funciona para grupos secundarios , no enumerará a los usuarios que tienen ese grupo establecido como primario ya que el grupo primario es almacenado como GID(ID de grupo numérico) en el archivo /etc/passwd.

grep <your_group_name> /etc/group

44
Puede grep directamente a ese archivo como grep <nombre de usuario> / etc / group. Más rápido y menos gastos generales.
caja de pinturas

16

El siguiente comando enumerará todos los usuarios que pertenecen <your_group_name>, pero solo aquellos administrados por la /etc/groupbase de datos, no LDAP, NIS, etc. También funciona para grupos secundarios , no enumerará a los usuarios que tienen ese grupo establecido como primario ya que el grupo primario es almacenado como GID(ID de grupo numérico) en el archivo /etc/passwd.

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

77
No muestra a los usuarios que tienen el grupo como su grupo predeterminado.
rlpowell

3
No verifica NIS y LDAP.
Paweł Nadolski

12

El siguiente script de shell iterará a través de todos los usuarios e imprimirá solo los nombres de usuario que pertenecen a un grupo dado:

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

Ejemplo de uso:

./script 'DOMAIN+Group Name'

Nota: Esta solución verificará NIS y LDAP para usuarios y grupos (no solo passwdy grouparchivos). También tendrá en cuenta a los usuarios que no se hayan agregado a un grupo pero que tengan un grupo establecido como grupo primario.

Editar: Se agregó una corrección para un escenario raro en el que el usuario no pertenece al grupo con el mismo nombre.

Editar: escrito en forma de script de shell; agregado truepara salir con el 0estado sugerido por @Max Chernyak, también conocido como hakunin ; descartados stderrpara omitir esos ocasionales groups: cannot find name for group ID xxxxxx.


Esto es genial y muy conciso, pero imprime el nombre del grupo y los nombres de usuario
andrew lorien

@andrewlorien, espero haber solucionado el problema que mencionas, si no, proporciona más detalles.
Paweł Nadolski

Este fragmento es bueno, pero devuelve el código de salida 1, ¿alguna razón por la que no devuelve 0? Solución fácil tal vez?
Max Chernyak

@hakunin, no devuelve 0 cuando el último nombre de usuario no pertenece al grupo. Puede agregar "|| true" en la declaración final para obtener siempre 0 si esto es lo que desea. Puede verificar la salida para ver si se encontró algún usuario.
Paweł Nadolski

@ PawełNadolski me di cuenta, así que terminé agregando ; true. Devolver 0 es bueno para evitar tropezar con su sistema de administración de configuración (Chef, Ansible, etc.).
Max Chernyak

7

Puedes hacerlo en una sola línea de comando:

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

Comando lista de entre todos los usuarios que tienen nombre de grupo como su grupo primario

Si también desea una lista de los usuarios que tienen nombre de grupo como su grupo secundario, utilice siguiente comando

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

1
Advertencia: grepcoincidirá con un usuario cuyo nombre contiene el número de grupo (por ejemplo sc0tt, se mostrará como parte del rootgrupo). Si esto es un problema, use la expresión regular :$(getent group <groupname> | cut -d: -f3)\$(coincide con el punto y coma, la identificación del grupo y el final de la línea). (No agregue citas a la expresión regular, o bash se queja.)
Scott Stevens

@ScottS Una caída en boxes legítima. Recomendaría los pasos sugeridos
Bhavik

3

solo un poco grep y tr:

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

44
No muestra a los usuarios que tienen el grupo como su grupo predeterminado.
rlpowell

3

La implementación de Zed probablemente debería ampliarse para funcionar en algunos de los otros UNIX principales.

¿Alguien tiene acceso al hardware Solaris o HP-UX ?; no probó esos casos.

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

Si hay una mejor manera de compartir esta sugerencia, hágamelo saber; Lo consideré de muchas maneras, y esto es lo que se me ocurrió.


Se confirmó que trabajaba en Solaris 10 después de cambiar id -Gna/usr/xpg4/bin/id -G -n
user667489

3

He hecho esto de manera similar al código perl anterior, pero reemplacé getent e id con funciones perl nativas. Es mucho más rápido y debería funcionar en diferentes sabores * 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";

Una respuesta solo con un enlace no se considera una buena respuesta en Stack Overflow. Considere eliminar esto, ya que no proporciona una respuesta a la pregunta ni explica más sobre cómo esta respuesta es mejor que la respuesta aceptada. O puede agregar esto como un comentario una vez que tenga suficiente reputación. Siempre puedes comentar tus propias publicaciones.
Dipen Shah

2

Hay un práctico paquete de Debian y Ubuntu llamado ' miembros ' que proporciona esta funcionalidad:

Descripción: muestra los miembros de un grupo; de manera predeterminada, todos los miembros miembros son el complemento de los grupos: mientras que los grupos muestran los grupos a los que pertenece un usuario específico, los miembros muestran los usuarios que pertenecen a un grupo específico.

... Puede solicitar miembros primarios, miembros secundarios, ambos en una línea, cada uno en líneas separadas.


¿Qué pasa si el operador usa openwrt?
user2284570

Prácticamente útil, pero desafortunadamente no informa a los miembros del grupo de dominio.
simlev

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

Esto devuelve una lista de usuarios separados por espacios que he usado en scripts para llenar matrices.

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

Aquí hay un script que devuelve una lista de usuarios de / etc / passwd y / etc / group que no verifica NIS o LDAP, pero muestra a los usuarios que tienen el grupo como su grupo predeterminado Probado en Debian 4.7 y 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 como una línea, puede cortar y pegar directamente desde aquí (cambie el nombre del grupo en la primera variable)

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

En UNIX (a diferencia de GNU / Linux), está el comando listusers. Consulte la página de manual de Solaris para ver los usuarios de la lista .

Tenga en cuenta que este comando es parte del proyecto Heirloom de código abierto . Supongo que falta en GNU / Linux porque RMS no cree en grupos y permisos. :-)


1
Si bien este enlace puede responder la pregunta, es mejor incluir aquí las partes esenciales de la respuesta y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. - De la opinión
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

Desde el sitio web de Heirloom Project: The Heirloom Project proporciona implementaciones tradicionales de utilidades estándar de Unix. En muchos casos, se han derivado del material original de Unix lanzado como Open Source por Caldera y Sun. Las interfaces siguen la práctica tradicional; generalmente son compatibles con el Sistema V, aunque a veces se proporcionan extensiones que se han convertido en un uso común en el transcurso del tiempo. La mayoría de las utilidades también se incluyen en una variante que apunta a la conformidad POSIX.
Alun Carr

0

Aquí hay un script awk muy simple que tiene en cuenta todas las trampas comunes enumeradas en las otras respuestas:

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

Estoy usando esto con mi configuración habilitada para ldap, se ejecuta en cualquier cosa con getent & awk que cumpla con los estándares, incluidos solaris 8+ y hpux.


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

Esto tiene 3 partes:

1: getent group groupnamemuestra la línea del grupo en el archivo "/ etc / group". Alternativa a cat /etc/group | grep groupname.

2: awkimprime solo los miembros en una sola línea separados con ','.

3 - trreemplace ',' con una nueva línea e imprima a cada usuario en una fila.

4 - Opcional: también puede usar otra tubería con sort, si los usuarios son demasiados.

Saludos


0

Creo que la forma más fácil es con los siguientes pasos, no necesitará instalar ningún paquete o software:

  1. Primero, descubres el GID del grupo que deseas conocer a los usuarios, hay muchas maneras de hacerlo: cat / etc / group (la última columna es el GID) id de usuario (el usuario es alguien que pertenece a el grupo)

  2. Ahora enumerará a todos los usuarios en el archivo / etc / passwd, pero aplicará algunos filtros con la siguiente secuela de comandos para obtener solo los miembros del grupo anterior.

cut -d: -f1,4 / etc / passwd | grep GID (el GID es el número que obtuvo del paso 1)

el comando de corte seleccionará solo algunas "columnas" del archivo, el parámetro d establece el delimitador ":" en este caso, el parámetro -f selecciona los "campos" (o columnas) que se mostrarán 1 y 4 en nuestro caso (en el archivo / etc / passwd, la 1º columna es el nombre del usuario y la 4º es el GID del grupo al que pertenece el usuario), para finalizar | grep GID filtrará solo el grupo (en la 4º columna) que usted había elegido.


0

Aquí hay otra línea única de Python que tiene en cuenta la membresía de grupo predeterminada del usuario (desde /etc/passwd), así como desde la base de datos del grupo ( /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

Lo he intentado grep 'sample-group-name' /etc/group, que mostrará una lista de todos los miembros del grupo que especificó según el ejemplo aquí


1
Grepping ya /etc/groupestá en al menos otras 3 respuestas, ¿qué valor le agrega su respuesta? Además, todas esas otras respuestas tienen comentarios de que dicha solución funciona solo para grupos secundarios y tampoco funciona para cuentas administradas por LDAP, NIS, etc.
David Ferenczy Rogožan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.