Como listar todos os usuários em um grupo Linux?


273

Como listar todos os membros de um grupo no Linux (e possivelmente outros departamentos)?


1
@ Silmari89, não se ele quiser fazer isso programaticamente.
Paul Tomblin

2
Sou novo aqui, descobri que o SF existe logo depois que postei a pergunta. Concordo que pertence ao SF ou SO.
User323094

5
Heh, é claro, agora ele tem uma solução programática, então poderia ser justificado aqui também.
Zed

Respostas:


103

Infelizmente, não há uma maneira boa e portátil de fazer isso que eu conheça. Se você tentar analisar o / etc / group, como outros sugerem, sentirá falta dos usuários que têm esse grupo como grupo principal e de quem foi adicionado a esse grupo por um mecanismo diferente dos arquivos simples do UNIX (por exemplo, LDAP, NIS, pam-pgsql, etc.).

Se eu tivesse que fazer isso sozinho, provavelmente faria o inverso: use idpara obter os grupos de todos os usuários no sistema (que atraem todas as fontes visíveis para o NSS) e use Perl ou algo semelhante para manter um hash tabela para cada grupo descoberto, observando a associação desse usuário.

Edit: Obviamente, isso deixa você com um problema semelhante: como obter uma lista de todos os usuários do sistema. Como minha localização usa apenas arquivos simples e LDAP, posso obter uma lista dos dois locais, mas isso pode ou não ser verdadeiro para o seu ambiente.

Edit 2: Alguém de passagem lembrou-me que getent passwdretornará uma lista de todos os usuários do sistema, incluindo os do LDAP / NIS / etc., Mas getent group ainda assim sentirei falta dos usuários que são membros apenas através da entrada de grupo padrão, o que me inspirou a escreva este hack 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
Obrigado a todos que responderam. Eu estava procurando uma maneira portátil de fazer isso. Suas informações de que não existe uma maneira fácil e portátil foram úteis. Você também detalhou ao máximo as circunstâncias que me ajudaram a entender o problema mais profundamente. Aprecio isso e escolhi sua resposta como a aceita.
User323094

2
Seria possível para você doar seu script para a fundação Linux? É 2012 e ainda não há uma maneira fácil de conseguir os membros de um grupo. É isso que me frustra no Linux.
21712 winteck

6
Adicionei uma licença semelhante ao ISC para você, que deve ser compatível com praticamente qualquer grupo. Sinta-se livre para enviá-lo para qualquer lugar que você achar que será aceito.
Zed

O PAM não fornece informações da conta. É o switch de serviço de nome (nsswitch) que faz isso. Nem todos os 'bancos de dados' (provedores de dados) oferecerão suporte à enumeração, portanto, getent passwdpodem não funcionar (se, por exemplo, você estiver usando sssd).

Ponto válido sobre PAM vs NSS - alterei a referência. Embora eu não o tenha usado, o sssd parece uma substituição do nscd à primeira vista, em vez de um provedor de dados adequado, e se ele quebrar getent passwd, consideraria um bug no sssd.
Zed

239
getent group <groupname>;

É portátil no Linux e no Solaris e funciona com arquivos de grupo / senha locais, configurações NIS e LDAP.


43
Não mostra usuários que têm o grupo como grupo padrão.
rlpowell


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

7
Esta seria a melhor maneira, exceto que a tampa não está em uma instalação padrão do Debian. No Ubuntu, ele está no pacote opcional libuser (não é o id-utils com o mesmo nome). Não encontrei no Debian :(
user323094

Trabalhou para mim no Scientific Linux
blong

no Debian Wheezy, a tampa é em pacote libuser também
Lluís

2
@JohnMcGehee RHEL deveria ter sido chamado AustereLinux
goelakash

1
'-g' não é uma opção para mim. Eu tenho o id-utils versão 4.6 instalado no Ubuntu 16.04.
Wilson Biggs

25

O comando a seguir listará todos os usuários pertencentes a <your_group_name>, mas apenas aqueles gerenciados pelo /etc/groupbanco de dados, não LDAP, NIS, etc. Também funciona apenas para grupos secundários , não listará usuários que tenham esse grupo definido como principal, pois o grupo principal é armazenado como GID(ID do grupo numérico) no arquivo /etc/passwd.

grep <your_group_name> /etc/group

4
Você pode grep diretamente para esse arquivo como grep <username> / etc / group. Mais rápido e menos sobrecarga.
Paint28 de

16

O comando a seguir listará todos os usuários pertencentes a <your_group_name>, mas apenas aqueles gerenciados pelo /etc/groupbanco de dados, não LDAP, NIS, etc. Também funciona apenas para grupos secundários , não listará usuários que tenham esse grupo definido como principal, pois o grupo principal é armazenado como GID(ID do grupo numérico) no arquivo /etc/passwd.

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

7
Não mostra usuários que têm o grupo como grupo padrão.
rlpowell

3
Não verifica NIS e LDAP.
Paweł Nadolski

12

O script de shell a seguir percorre todos os usuários e imprime apenas os nomes de usuários que pertencem a um determinado grupo:

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

Exemplo de uso:

./script 'DOMAIN+Group Name'

Nota: Esta solução verificará o NIS e o LDAP para usuários e grupos (não apenas passwde grouparquivos). Ele também levará em conta os usuários não adicionados a um grupo, mas o grupo definido como grupo principal.

Editar: correção adicionada para um cenário raro em que o usuário não pertence ao grupo com o mesmo nome.

Edit: escrito na forma de um script de shell; adicionado truepara sair com o 0status, conforme sugerido por @Max Chernyak aka hakunin ; descartados stderrpara pular aqueles ocasionais groups: cannot find name for group ID xxxxxx.


Isso é ótimo, e muito concisa, mas imprime o nome do grupo, bem como os nomes de usuário
Andrew lorien

@andrewlorien, espero ter corrigido o problema mencionado, caso contrário, forneça mais detalhes.
Paweł Nadolski

Esse snippet é bom, mas retorna o código de saída 1, qualquer motivo pelo qual não retorna 0? Correção fácil, talvez?
precisa

@hakunin, não retorna 0 quando o último nome de usuário não pertence ao grupo. Você pode acrescentar "|| true" na instrução final para obter sempre 0 se é isso que você deseja. Você pode verificar a saída para ver se algum usuário foi encontrado.
Paweł Nadolski

@ PawełNadolski eu percebi, então acabei adicionando ; true. Retornar 0 é bom para evitar tropeçar no sistema de gerenciamento de configuração (Chef, Ansible, etc).
precisa

7

Você pode fazer isso em uma única linha de comando:

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

O comando acima lista todos os usuários que têm o nome do grupo como grupo principal

Se você também deseja listar os usuários com nome de grupo como grupo secundário, use o seguinte comando

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

1
Advertência: grepcorresponderá a um usuário cujo nome contenha o número do grupo (por exemplo sc0tt, será mostrado como parte do rootgrupo). Se isso for um problema, use a regex :$(getent group <groupname> | cut -d: -f3)\$(corresponde ao ponto-e-vírgula, ao ID do grupo e ao final da linha). (Não adicione aspas para o regex, ou festa reclama.)
Scott Stevens

@ ScottS Uma queda legítima. Recomendaria passos sugeriu
Bhavik

3

apenas um pouco de grep e tr:

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

4
Não mostra usuários que têm o grupo como grupo padrão.
rlpowell

3

A implementação de Zed provavelmente deve ser expandida para funcionar em alguns dos outros principais UNIX.

Alguém tem acesso ao hardware Solaris ou HP-UX ?; não testou esses 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";
    }
}

Se houver uma maneira melhor de compartilhar esta sugestão, entre em contato. Eu considerei muitas maneiras, e é isso que eu criei.


Confirmado o trabalho no Solaris 10 após mudar id -Gnpara/usr/xpg4/bin/id -G -n
user667489

3

Eu fiz isso semelhante ao código perl acima, mas substitui getent e id por funções perl nativas. É muito mais rápido e deve funcionar com 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";

Uma resposta apenas com um link não é considerada uma boa resposta no Stack Overflow. Considere excluir isso, pois isso não fornece uma resposta para a pergunta ou elabora mais sobre como essa resposta é melhor que a resposta aceita. Ou você pode adicionar isso como um comentário quando tiver reputação suficiente. Você sempre pode comentar em suas próprias postagens.
Dipen Shah

2

Existe um pacote útil do Debian e Ubuntu chamado ' members ' que fornece esta funcionalidade:

Descrição: mostra os membros de um grupo; por padrão, todos os membros membros são o complemento de grupos: enquanto grupos mostra os grupos aos quais um usuário especificado pertence, membros mostra usuários pertencentes a um grupo especificado.

... Você pode solicitar membros primários, secundários, ambos em uma linha, cada um em linhas separadas.


E se o op usar openwrt?
user2284570

Útil, de fato, mas infelizmente não informa os membros do grupo de domínio.
Simlev 24/04/19

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

Isso retorna uma lista separada por espaço de usuários que eu usei em scripts para preencher matrizes.

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

Aqui está um script que retorna uma lista de usuários de / etc / passwd e / etc / group que não verifica NIS ou LDAP, mas mostra aos usuários que têm o grupo como grupo padrão Testado no 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

ou como uma linha, você pode recortar e colar diretamente daqui (altere o nome do grupo na primeira variável)

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

No UNIX (ao contrário do GNU / Linux), há o comando listusers. Consulte a página do manual Solaris para listusers .

Observe que este comando faz parte do projeto Heirloom de código aberto . Suponho que ele esteja ausente do GNU / Linux porque o RMS não acredita em grupos e permissões. :-)


1
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada. - Do comentário
knuhol 11/11/2015

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

No site do Heirloom Project: O Heirloom Project fornece implementações tradicionais de utilitários padrão do Unix. Em muitos casos, eles foram derivados do material original do Unix, lançado como Open Source pela Caldera e Sun. As interfaces seguem a prática tradicional; eles geralmente permanecem compatíveis com o Sistema V, embora às vezes sejam fornecidas extensões que se tornaram comuns ao longo do tempo. A maioria dos utilitários também está incluída em uma variante que visa a conformidade com POSIX.
Alun Carr

0

Aqui está um script awk muito simples que leva em consideração todas as armadilhas comuns listadas nas outras respostas:

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

Estou usando isso com minha configuração habilitada para ldap, roda em qualquer coisa com o getent & awk compatível com os padrões, incluindo solaris 8+ e hpux.


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

Isto tem 3 partes:

1 - getent group groupnamemostra a linha do grupo no arquivo "/ etc / group". Alternativa para cat /etc/group | grep groupname.

2 - awkprint é apenas os membros em uma única linha separados por ','.

3 - trsubstitua ',' por uma nova linha e imprima cada usuário em uma linha.

4 - Opcional: Você também pode usar outro canal com sort, se os usuários forem muitos.

Saudações


0

Acho que a maneira mais fácil são as seguintes etapas, você não precisará instalar nenhum pacote ou software:

  1. Primeiro, você descobre o GID do grupo ao qual deseja conhecer os usuários, existem várias maneiras para isso: cat / etc / group (a última coluna é o GID) id user (o usuário é alguém que pertence a o grupo)

  2. Agora você listará todo o usuário no arquivo / etc / passwd, mas aplicará alguns filtros com a seguinte sequência de comandos para obter apenas os membros do grupo anterior.

cut -d: -f1,4 / etc / passwd | grep GID (o GID é o número que você obteve na etapa 1)

O comando cut selecionará apenas algumas "colunas" do arquivo, o parâmetro d define o delimitador ":" nesse caso, o parâmetro -f seleciona os "campos" (ou colunas) a serem mostrados 1 e 4 no caso final (em o arquivo / etc / passwd, a 1º coluna é o nome do usuário e o 4º é o GID do grupo ao qual o usuário pertence), para finalizar o | grep GID filtrará apenas o grupo (na 4ª coluna) que você tinha escolhido.


0

Aqui está outro liner Python que leva em consideração a associação ao grupo padrão do usuário (de /etc/passwd) e também o banco de dados do 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

Eu tentei grep 'sample-group-name' /etc/group, que listará todos os membros do grupo que você especificou com base no exemplo aqui


1
O Grepping já /etc/grouppossui pelo menos três outras respostas. Que valor sua resposta acrescenta a elas? Além disso, todas as outras respostas têm comentários de que essa solução funciona apenas para grupos secundários e também não funciona para contas gerenciadas por LDAP, NIS etc.
David Ferenczy Rogožan -
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.