Como listar todos os membros de um grupo no Linux (e possivelmente outros departamentos)?
Como listar todos os membros de um grupo no Linux (e possivelmente outros departamentos)?
Respostas:
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 id
para 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 passwd
retornará 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";
}
}
getent passwd
podem não funcionar (se, por exemplo, você estiver usando sssd).
getent passwd
, consideraria um bug no sssd.
Use o Python para listar os membros do grupo:
python -c "import grp; imprime grp.getgrnam ('GROUP_NAME') [3]"
lid -g groupname | cut -f1 -d'('
O comando a seguir listará todos os usuários pertencentes a <your_group_name>
, mas apenas aqueles gerenciados pelo /etc/group
banco 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
O comando a seguir listará todos os usuários pertencentes a <your_group_name>
, mas apenas aqueles gerenciados pelo /etc/group
banco 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
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 passwd
e group
arquivos). 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 true
para sair com o 0
status, conforme sugerido por @Max Chernyak aka hakunin ; descartados stderr
para pular aqueles ocasionais groups: cannot find name for group ID xxxxxx
.
; true
. Retornar 0 é bom para evitar tropeçar no sistema de gerenciamento de configuração (Chef, Ansible, etc).
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'
grep
corresponderá a um usuário cujo nome contenha o número do grupo (por exemplo sc0tt
, será mostrado como parte do root
grupo). 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.)
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.
id -Gn
para/usr/xpg4/bin/id -G -n
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";
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.
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')")
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
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. :-)
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.
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.
getent group groupname | awk -F: '{print $4}' | tr , '\n'
Isto tem 3 partes:
1 - getent group groupname
mostra a linha do grupo no arquivo "/ etc / group". Alternativa para cat /etc/group | grep groupname
.
2 - awk
print é apenas os membros em uma única linha separados por ','.
3 - tr
substitua ',' 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
Acho que a maneira mais fácil são as seguintes etapas, você não precisará instalar nenhum pacote ou software:
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)
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.
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]])"
Eu tentei grep 'sample-group-name' /etc/group
, que listará todos os membros do grupo que você especificou com base no exemplo aqui
/etc/group
possui 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.