Як мені перелічити всіх членів групи в Linux (і, можливо, інших уніксах)?
Як мені перелічити всіх членів групи в Linux (і, можливо, інших уніксах)?
Відповіді:
На жаль, немає жодного хорошого, портативного способу зробити це, про що я знаю. Якщо ви спробуєте проаналізувати / etc / group, як це пропонують інші, ви пропустите користувачів, які мають цю групу як свою основну групу, і всіх, хто був доданий до цієї групи через механізм, відмінний від плоских файлів UNIX (наприклад, LDAP, NIS, pam-pgsql тощо).
Якби я абсолютно повинен був зробити це сам, я, мабуть, зробив би це в зворотному порядку: використовувати id
щоб отримати групи кожного користувача в системі (яка буде витягувати всі джерела, видимі для NSS), і використовувати Perl або щось подібне для підтримки хешу таблиці для кожної виявленої групи із зазначенням належності цього користувача.
Редагувати: Звичайно, це викликає у вас схожу проблему: як отримати список кожного користувача в системі. Оскільки в моєму розташуванні використовуються лише плоскі файли та LDAP, я можу просто отримати список з обох локацій, але це може бути, а може і не бути правдою для вашого оточення.
Змінити 2: Хто - мимохідь нагадав мені , що getent passwd
буде повертати список всіх користувачів системи , включаючи ті з LDAP / NIS / і т.д.,. , Але getent group
до цих пір все ще міс користувачі , які є членами тільки через запис групи по замовчуванням, так що надихнуло мене написати цей швидкий хак.
#!/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
можуть не працювати (якщо, наприклад, ви використовуєте sssd).
getent passwd
я вважаю, що помилка в sssd.
Використовуйте Python для переліку членів групи:
python -c "імпортувати grp; друкувати grp.getgrnam (" GROUP_NAME ") [3]"
lid -g groupname | cut -f1 -d'('
У наступній команді будуть перераховані всі користувачі, які належать <your_group_name>
, але лише ті, якими керується /etc/group
база даних, а не LDAP, NIS тощо. Також вона працює лише для вторинних груп , вона не буде перераховувати користувачів, у яких ця група встановлена як основна, оскільки первинна група є зберігається як GID
(числовий ідентифікатор групи) у файлі /etc/passwd
.
grep <your_group_name> /etc/group
Наступна команда відображатиме список усіх користувачів, які належать <your_group_name>
, але лише ті, якими керується /etc/group
база даних, а не LDAP, NIS тощо. Також вона працює лише для вторинних груп , вона не буде перераховувати користувачів, у яких ця група встановлена як основна, оскільки первинна група є зберігається як GID
(числовий ідентифікатор групи) у файлі /etc/passwd
.
awk -F: '/^groupname/ {print $4;}' /etc/group
Наступний скрипт оболонки повторює всіх користувачів та друкує лише ті імена користувачів, які належать до певної групи:
#!/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
Приклад використання:
./script 'DOMAIN+Group Name'
Примітка: Це рішення буде перевіряти NIS і LDAP для користувачів і груп (не тільки passwd
і group
файлів). Він також враховує користувачів, які не додані до групи, але мають групу, встановлену як основну групу.
Редагувати: Додано виправлення для рідкісного сценарію, коли користувач не належить до групи з тим самим іменем.
Правка: написана у формі сценарію оболонки; додано true
для виходу зі 0
статусом, як запропонував @Max Chernyak aka hakunin ; відкинути stderr
, щоб пропустити ці випадкові groups: cannot find name for group ID xxxxxx
.
; true
. Повернення 0 добре, щоб уникнути відключення вашої системи управління конфігурацією (шеф-кухар, відповідь тощо).
Це можна зробити в одному командному рядку:
cut -d: -f1,4 /etc/passwd | grep $(getent group <groupname> | cut -d: -f3) | cut -d: -f1
Над списки команд всіх користувачів , які мають імя_группи в якості своєї основної групи
Якщо ви також хочете перерахувати користувачів, які мають ім'я групи як свою вторинну групу, використовуйте наступну команду
getent group <groupname> | cut -d: -f4 | tr ',' '\n'
grep
відповідатиме користувачеві, ім'я якого містить номер групи (наприклад, sc0tt
буде показано як частину root
групи). Якщо це проблема, то використовуйте регулярний вираз :$(getent group <groupname> | cut -d: -f3)\$
(відповідає крапці з комою, ідентифікатором групи та кінці рядка). (Не додайте лапок до регулярного виразу, або баш скаржиться.)
Реалізація Zed, мабуть, має бути розширена для роботи над деякими іншими основними UNIX.
Хтось має доступ до обладнання Solaris або HP-UX ?; не перевіряв цих випадків.
#!/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";
}
}
Якщо є кращий спосіб поділитися цією пропозицією, будь ласка, дайте мені знати; Я розглядав багато способів, і це те, що я придумав.
id -Gn
на/usr/xpg4/bin/id -G -n
Я робив це аналогічно коду perl, наведеному вище, але замінив getent та id на нативні функції perl. Це набагато швидше і має працювати в різних * 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";
Існує зручний пакет Debian і Ubuntu під назвою " members ", який забезпечує цю функціональність:
Опис: Показує членів групи; за замовчуванням усі члени є доповненням груп: тоді як групи показують групи, до яких належить визначений користувач, члени показують користувачів, що належать до визначеної групи.
... Ви можете попросити первинних членів, другорядних членів, обидва в одному рядку, кожен в окремих рядках.
getent group insert_group_name_here | awk -F ':' '{print $4}' | sed 's|,| |g'
Це повертає список розділених пробілом користувачів, яких я використовував у скриптах для заповнення масивів.
for i in $(getent group ftp | awk -F ':' '{print $4}' | sed 's|,| |g')
do
userarray+=("$i")
done
або
userarray+=("$(getent group GROUPNAME | awk -F ':' '{print $4}' | sed 's|,| |g')")
Ось сценарій, який повертає список користувачів з / etc / passwd та / etc / group, він не перевіряє NIS або LDAP, але він показує користувачам, які мають групу як свою групу за замовчуванням Тестовано на Debian 4.7 та 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
або як однолінійку ви можете вирізати та вставити прямо звідси (змінити назву групи в першій змінній)
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
У UNIX (на відміну від GNU / Linux) є команда listusers. Перегляньте список користувачів Solaris на сторінці користувачів .
Зауважте, що ця команда є частиною проекту Heirloom з відкритим кодом . Я припускаю, що він відсутній у GNU / Linux, оскільки RMS не вірить у групи та дозволи. :-)
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.
Ось дуже простий скрипт awk, який враховує всі загальні підводні камені, перелічені в інших відповідях:
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}'
Я використовую це для моєї установки з підтримкою ldap, працює на будь-що, що відповідає стандартам getent & awk, включаючи solaris 8+ та hpux.
getent group groupname | awk -F: '{print $4}' | tr , '\n'
Це 3 частини:
1 - getent group groupname
відображається рядок групи у файлі "/ etc / group". Альтернатива cat /etc/group | grep groupname
.
2 - awk
друкують лише члени в одному рядку, відокремленому символами ','.
3 - tr
замініть ',' на новий рядок і надрукуйте кожного користувача підряд.
4 - Необов’язково: Ви також можете використовувати іншу трубу sort
, якщо користувачів занадто багато.
З повагою
Я думаю, що найпростішим способом є наступні кроки, вам не потрібно буде встановлювати будь-який пакет чи програмне забезпечення:
По-перше, ви дізнаєтесь, GID групи, яку ви хочете знати користувачів, для цього є багато способів: cat / etc / group (останній стовпець - це GID) id користувача (користувач - хтось, хто належить група)
Тепер ви перерахуєте всіх користувачів у файлі / etc / passwd, але застосуєте кілька фільтрів із наступним продовженням команд, щоб отримати лише членів попередньої групи.
cut -d: -f1,4 / etc / passwd | grep GID (GID - це число, яке ви отримали з кроку 1)
команда cut вибере лише декілька "стовпців" файлу, параметр d встановлює роздільник ":" у цьому випадку параметр -f вибирає "поля" (або стовпці), які будуть відображатись 1 і 4 у випадку (на файл / etc / passwd, стовпець 1º - це ім'я користувача, а 4º - GID групи, до якої належить користувач), для завершення | grep GID буде фільтрувати лише ту групу (у стовпці 4º), яку ви обрали.
Ось ще один однокласник Python, який враховує членство групи (за замовчуванням /etc/passwd
), а також групову базу даних ( /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]])"
Я спробував grep 'sample-group-name' /etc/group
, це перерахує всіх членів групи, яку ви вказали, виходячи з прикладу тут
/etc/group
вже принаймні у 3 інших відповідях, яке значення додає до них ваша відповідь? Крім того, всі інші відповіді мають коментарі, що таке рішення працює лише для вторинних груп, а також не працює для облікових записів, якими керуються LDAP, NIS тощо.