¿Cómo enumero a todos los miembros de un grupo en Linux (y posiblemente otros unices)?
¿Cómo enumero a todos los miembros de un grupo en Linux (y posiblemente otros unices)?
Respuestas:
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 id
para 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 passwd
devolverá 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";
}
}
getent passwd
posible que no funcionen (si, por ejemplo, está utilizando sssd).
getent passwd
, lo consideraría un error en sssd.
Use Python para enumerar los miembros del grupo:
python -c "import grp; print grp.getgrnam ('GROUP_NAME') [3]"
lid -g groupname | cut -f1 -d'('
El siguiente comando enumerará todos los usuarios que pertenecen <your_group_name>
, pero solo aquellos administrados por la /etc/group
base 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
El siguiente comando enumerará todos los usuarios que pertenecen <your_group_name>
, pero solo aquellos administrados por la /etc/group
base 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
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 passwd
y group
archivos). 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 true
para salir con el 0
estado sugerido por @Max Chernyak, también conocido como hakunin ; descartados stderr
para omitir esos ocasionales groups: cannot find name for group ID xxxxxx
.
; true
. Devolver 0 es bueno para evitar tropezar con su sistema de administración de configuración (Chef, Ansible, etc.).
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'
grep
coincidirá con un usuario cuyo nombre contiene el número de grupo (por ejemplo sc0tt
, se mostrará como parte del root
grupo). 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.)
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ó.
id -Gn
a/usr/xpg4/bin/id -G -n
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";
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.
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')")
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
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. :-)
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.
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.
getent group groupname | awk -F: '{print $4}' | tr , '\n'
Esto tiene 3 partes:
1: getent group groupname
muestra la línea del grupo en el archivo "/ etc / group". Alternativa a cat /etc/group | grep groupname
.
2: awk
imprime solo los miembros en una sola línea separados con ','.
3 - tr
reemplace ',' 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
Creo que la forma más fácil es con los siguientes pasos, no necesitará instalar ningún paquete o software:
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)
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.
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]])"
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í
/etc/group
está 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.