Comment lister tous les utilisateurs d'un groupe Linux?


273

Comment répertorier tous les membres d'un groupe sous Linux (et éventuellement d'autres unités)?


1
@ Silmari89, pas s'il veut le faire par programmation.
Paul Tomblin

2
Je suis nouveau ici, j'ai découvert que SF existe juste après avoir posté la question. J'accepte qu'il appartient à SF ou SO.
user323094

5
Heh, bien sûr, maintenant il a une solution programmatique, donc cela pourrait être justifié ici aussi.
Zed

Réponses:


103

Malheureusement, il n'y a aucun bon moyen portable de faire cela que je sache. Si vous essayez d'analyser / etc / group, comme d'autres le suggèrent, vous manquerez les utilisateurs qui ont ce groupe comme groupe principal et toute personne qui a été ajoutée à ce groupe via un mécanisme autre que les fichiers plats UNIX (c'est-à-dire LDAP, NIS, pam-pgsql, etc.).

Si je devais absolument le faire moi-même, je le ferais probablement à l'envers: utilisez idpour obtenir les groupes de chaque utilisateur sur le système (ce qui tirera toutes les sources visibles pour NSS), et utilisez Perl ou quelque chose de similaire pour maintenir un hachage table pour chaque groupe découvert en notant l'appartenance de cet utilisateur.

Edit: Bien sûr, cela vous laisse avec un problème similaire: comment obtenir une liste de chaque utilisateur sur le système. Étant donné que mon emplacement utilise uniquement des fichiers plats et LDAP, je peux simplement obtenir une liste des deux emplacements, mais cela peut ou non être vrai pour votre environnement.

Edit 2: Quelqu'un en passant m'a rappelé qu'il getent passwdretournerait une liste de tous les utilisateurs du système, y compris ceux de LDAP / NIS / etc., mais getent group qu'il manquerait toujours les utilisateurs qui sont membres uniquement via l'entrée de groupe par défaut, ce qui m'a inspiré écrivez ce hack rapide.


#!/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
Merci à tous ceux qui ont répondu. Je cherchais un moyen portable de le faire. Votre information selon laquelle il n'existe pas de moyen facile et portable a été utile. Vous avez également détaillé le plus sur les circonstances qui m'ont aidé à comprendre le problème plus profondément, je l'apprécie et j'ai choisi votre réponse comme acceptée.
user323094

2
Serait-il possible pour vous de faire don de votre script à la fondation Linux? Nous sommes en 2012 et il n'y a toujours pas de moyen facile d'obtenir les membres d'un groupe. C'est ce qui me frustre à propos de Linux.
winteck

6
J'ai ajouté une licence de type ISC pour vous, qui devrait être compatible avec à peu près n'importe quel groupe. N'hésitez pas à le soumettre partout où vous pensez qu'il sera accepté.
Zed

PAM ne fournit pas d'informations sur le compte. C'est le Name Service Switch (nsswitch) qui le fait. Toutes les «bases de données» (fournisseurs de données) ne prendront pas en charge l'énumération et getent passwdpeuvent donc ne pas fonctionner (si, par exemple, vous utilisez sssd).

Point valable sur PAM vs NSS - J'ai changé la référence. Bien que je ne l'ai pas utilisé, sssd ressemble à un remplacement de nscd à première vue plutôt qu'à un fournisseur de données approprié, et s'il se casse, getent passwdje considérerais qu'il s'agit d'un bogue dans sssd.
Zed

239
getent group <groupname>;

Il est portable sur Linux et Solaris, et il fonctionne avec les fichiers de groupe / mot de passe locaux, les configurations NIS et LDAP.


43
N'affiche pas les utilisateurs qui ont le groupe comme groupe par défaut.
rlpowell


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

7
Ce serait la meilleure façon, sauf que le couvercle n'est pas dans une installation Debian standard. Dans Ubuntu, c'est dans le paquet facultatif libuser (ce n'est pas celui dans id-utils avec le même nom). Je ne l'ai pas trouvé dans Debian :(
user323094

A travaillé pour moi sur Scientific Linux
blong

sur Debian Wheezy, le couvercle est également sur le paquet libuser
Lluís

2
@JohnMcGehee RHEL aurait dû s'appeler AustereLinux
goelakash

1
'-g' n'est pas une option pour moi. J'ai id-utils version 4.6 installé sur Ubuntu 16.04.
Wilson Biggs

25

La commande suivante liste tous les utilisateurs appartenant <your_group_name>, mais seulement celles qui sont gérées par la /etc/groupbase de données, pas LDAP, NIS, etc. Il a également travaille pour des groupes secondaires seulement , il ne sera pas les utilisateurs de la liste qui ont cet ensemble du groupe comme principal puisque le groupe primaire est stocké sous GID(ID de groupe numérique) dans le fichier /etc/passwd.

grep <your_group_name> /etc/group

4
Vous pouvez grep directement dans ce fichier comme grep <username> / etc / group. Plus rapide et moins de frais généraux.
Paintbox

16

La commande suivante liste tous les utilisateurs appartenant <your_group_name>, mais seulement celles qui sont gérées par la /etc/groupbase de données, pas LDAP, NIS, etc. Il a également travaille pour des groupes secondaires seulement , il ne sera pas les utilisateurs de la liste qui ont cet ensemble du groupe comme principal puisque le groupe primaire est stocké sous GID(ID de groupe numérique) dans le fichier /etc/passwd.

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

7
N'affiche pas les utilisateurs qui ont le groupe comme groupe par défaut.
rlpowell

3
Ne vérifie pas NIS et LDAP.
Paweł Nadolski

12

Le script shell suivant parcourra tous les utilisateurs et n'imprimera que les noms d'utilisateur qui appartiennent à un groupe donné:

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

Exemple d'utilisation:

./script 'DOMAIN+Group Name'

Remarque: Cette solution vérifiera NIS et LDAP pour les utilisateurs et les groupes (pas seulement passwdet les groupfichiers). Il prendra également en compte les utilisateurs non ajoutés à un groupe mais dont le groupe est défini comme groupe principal.

Modifier: correction d'un scénario rare dans lequel l'utilisateur n'appartient pas à un groupe du même nom.

Edit: écrit sous la forme d'un script shell; ajouté truepour quitter avec le 0statut suggéré par @Max Chernyak aka hakunin ; jetés stderrafin de sauter ceux qui sont occasionnels groups: cannot find name for group ID xxxxxx.


C'est génial et très concis, mais il imprime le nom du groupe ainsi que les noms d'utilisateur
andrew lorien

@andrewlorien, j'espère avoir résolu le problème que vous mentionnez, sinon veuillez fournir plus de détails.
Paweł Nadolski

Cet extrait est bon, mais il renvoie le code de sortie 1, pour quelle raison ne renvoie-t-il pas 0? Solution facile peut-être?
Max Chernyak

@hakunin, il ne renvoie pas 0 lorsque le dernier nom d'utilisateur n'appartient pas au groupe. Vous pouvez ajouter "|| true" à la fin de l'instruction pour toujours obtenir 0 si c'est ce que vous voulez. Vous pouvez vérifier puis sortir pour voir si un utilisateur a été trouvé.
Paweł Nadolski

@ PawełNadolski J'ai réalisé, donc j'ai fini par ajouter ; true. Renvoyer 0 est bon pour éviter de déclencher votre système de gestion de configuration (Chef, Ansible, etc.).
Max Chernyak

7

Vous pouvez le faire en une seule ligne de commande:

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

La commande ci-dessus répertorie tous les utilisateurs dont le nom de groupe est leur groupe principal

Si vous souhaitez également répertorier les utilisateurs dont le nom de groupe est leur groupe secondaire, utilisez la commande suivante

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

1
Avertissement: grepcorrespondra à un utilisateur dont le nom contient le numéro de groupe (par exemple, sc0ttsera affiché comme faisant partie du rootgroupe). Si c'est un problème, utilisez l'expression régulière :$(getent group <groupname> | cut -d: -f3)\$(correspond au point-virgule, à l'ID de groupe et à la fin de la ligne). (N'ajoutez pas de guillemets au regex, ou bash se plaint.)
Scott Stevens

@ScottS Un piège légitime. Je recommanderais les étapes suggérées
Bhavik

3

juste un peu de grep et tr:

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

4
N'affiche pas les utilisateurs qui ont le groupe comme groupe par défaut.
rlpowell

3

L'implémentation de Zed devrait probablement être étendue pour fonctionner sur certains des autres grands UNIX.

Quelqu'un a accès au matériel Solaris ou HP-UX ?; n'a pas testé ces cas.

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

S'il existe une meilleure façon de partager cette suggestion, faites-le moi savoir; J'ai envisagé plusieurs façons, et c'est ce que j'ai trouvé.


Confirmation du travail sur Solaris 10 après le passage id -Gnà/usr/xpg4/bin/id -G -n
user667489

3

J'ai fait cela de la même manière que le code perl ci-dessus, mais j'ai remplacé getent et id par des fonctions perl natives. Il est beaucoup plus rapide et devrait fonctionner avec différentes saveurs * 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";

Une réponse avec un lien uniquement n'est pas considérée comme une bonne réponse sur Stack Overflow. Veuillez envisager de le supprimer car cela ne fournit pas de réponse à la question ou de préciser davantage en quoi cette réponse est meilleure que la réponse acceptée. Ou vous pouvez l'ajouter en tant que commentaire une fois que vous avez suffisamment de réputation. Vous pouvez toujours commenter vos propres messages.
Dipen Shah

2

Il existe un paquet Debian et Ubuntu pratique appelé « membres » qui fournit cette fonctionnalité:

Description: affiche les membres d'un groupe; par défaut, tous les membres membres sont le complément des groupes: alors que groupes affiche les groupes auxquels appartient un utilisateur spécifié, membres montre les utilisateurs appartenant à un groupe spécifié.

... Vous pouvez demander des membres principaux, des membres secondaires, sur une même ligne, chacun sur des lignes distinctes.


Et si l'op utilisait openwrt?
user2284570

Pratique en effet, mais ne rapporte malheureusement pas les membres du groupe de domaine.
simlev

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

Cela renvoie une liste d'utilisateurs séparés par des espaces que j'ai utilisés dans des scripts pour remplir les tableaux.

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

ou

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

0

Voici un script qui retourne une liste d'utilisateurs de / etc / passwd et / etc / group qu'il ne vérifie pas NIS ou LDAP, mais il montre les utilisateurs qui ont le groupe comme groupe par défaut Testé sur Debian 4.7 et 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

ou en une ligne, vous pouvez couper et coller directement à partir d'ici (changez le nom du groupe dans la première 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

Sous UNIX (par opposition à GNU / Linux), il y a la commande listusers. Consultez la page de manuel Solaris pour les utilisateurs .

Notez que cette commande fait partie du projet Heirloom open-source . Je suppose qu'il est absent de GNU / Linux car RMS ne croit pas aux groupes et aux autorisations. :-)


1
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien de référence. Les réponses de lien uniquement peuvent devenir invalides si la page liée change. - De l'avis
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

Depuis le site Web du projet Heirloom: Le projet Heirloom fournit des implémentations traditionnelles des utilitaires Unix standard. Dans de nombreux cas, ils sont issus de matériel Unix original publié en Open Source par Caldera et Sun. Les interfaces suivent la pratique traditionnelle; ils restent généralement compatibles avec System V, bien que des extensions devenues courantes au fil du temps soient parfois fournies. La plupart des utilitaires sont également inclus dans une variante qui vise la conformité POSIX.
Alun Carr

0

Voici un script awk très simple qui prend en compte tous les pièges courants répertoriés dans les autres réponses:

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

J'utilise cela avec ma configuration compatible LDAP, fonctionne sur n'importe quoi avec getent & awk conforme aux normes, y compris Solaris 8+ et hpux.


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

Cela comprend 3 parties:

1 - getent group groupnamemontre la ligne du groupe dans le fichier "/ etc / group". Alternative à cat /etc/group | grep groupname.

2 - awkaffiche uniquement les membres sur une seule ligne séparée par ','.

3 - tr remplacez le ',' par une nouvelle ligne et imprimez chaque utilisateur d'affilée.

4 - Facultatif: vous pouvez également utiliser un autre tuyau avec sort , si les utilisateurs sont trop nombreux.

Cordialement


0

Je pense que le moyen le plus simple est les étapes suivantes, vous n'aurez pas besoin d'installer de package ou de logiciel:

  1. Tout d'abord, vous découvrez le GID du groupe dont vous souhaitez connaître les utilisateurs, il existe de nombreuses façons pour cela: cat / etc / group (la dernière colonne est le GID) id user (l'utilisateur est quelqu'un qui appartient à le groupe)

  2. Vous allez maintenant lister tous les utilisateurs sur le fichier / etc / passwd, mais vous appliquerez quelques filtres avec la suite de commandes suivante pour obtenir uniquement les membres du groupe précédent.

cut -d: -f1,4 / etc / passwd | grep GID (le GID est le numéro obtenu à l'étape 1)

La commande cut sélectionnera seulement quelques "colonnes" du fichier, le paramètre d définit le délimiteur ":" dans ce cas, le paramètre -f sélectionne les "champs" (ou colonnes) à afficher 1 et 4 dans le cas (sur le fichier / etc / passwd, la colonne 1º est le nom de l'utilisateur et le 4º est le GID du groupe auquel l'utilisateur appartient), pour finaliser le | grep GID filtrera juste le groupe (sur la colonne 4º) que vous avait choisi.


0

Voici un autre one-liner Python qui prend en compte l'appartenance au groupe par défaut de l'utilisateur (de /etc/passwd) ainsi que de la base de données de groupe ( /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

J'ai essayé grep 'sample-group-name' /etc/group, cela listera tous les membres du groupe que vous avez spécifié sur la base de l'exemple ici


1
Grepping /etc/groupest déjà dans au moins 3 autres réponses, quelle valeur votre réponse leur ajoute-t-elle? En outre, toutes ces autres réponses indiquent que cette solution ne fonctionne que pour les groupes secondaires et ne fonctionne pas non plus pour les comptes gérés par LDAP, NIS, etc.
David Ferenczy Rogožan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.