51

Я пробовал гуглить, но никуда не денешься. Как я могу перечислить всех членов группы под названием mygroup из командной строки в OS X?

$ dscl . list /groups получит мне все группы ... но как я могу видеть участников каждой группы?

7 ответов7

60

Там нет стандартной команды, которая перечисляет всех членов группы в OS X, поэтому вот функция оболочки, которая делает это:

members () { dscl . -list /Users | while read user; do printf "$user "; dsmemberutil checkmembership -U "$user" -G "$*"; done | grep "is a member" | cut -d " " -f 1; }; 

Скопируйте приведенную выше командную строку в терминал, а затем введите members mygroup (где mygroup - это имя существующей группы).


Некоторое объяснение для тех, кто заинтересован:

Есть пять различных способов (о которых я знаю), что пользователь может быть членом группы в OS X. Команда dscl . -read /Groups/mygroup GroupMembership не гарантирует вывод всех или даже любых членов mygroup, поскольку членство также зависит от идентификатора основной группы пользователей, членства по UUID пользователя, наследования членства от одной группы к другой, и членство, которое рассчитывается системой, например, группа каждый.

Поэтому вместо того, чтобы пытаться отслеживать все это, лучше всего просто проверить членство каждого пользователя в системе (используя dsmemberutil), и именно это делают функция оболочки и приведенный ниже скрипт.


Этот скрипт- член эквивалентен функции оболочки, но имеет лучшую обработку неверного ввода:

#!/bin/bash

# members -- list all members of a group
#
# SYNOPSIS
#   members groupname
#
# http://superuser.com/questions/279891/list-all-members-of-a-group-mac-os-x
#  by Arne
# Expected to work on Mac OS 10.5 and newer, tested on 10.6 and 10.7.
# It could be rewritten to work on 10.4 by using "dseditgroup -o checkmember"
# instead of "dsmemberutil checkmembership".
# By using dseditgroup, the script could also be extended to handle
# other Directory Service nodes than the default local node.
#

the_group="$1"
# Input check and usage
  if [[ $# != 1 || $1 == -* || $1 =~ [[:space:]] ]]; then
    echo "Usage: ${0##*/} groupname" >&2
    echo "Lists all members of the group." >&2
    exit 64
  elif (dsmemberutil checkmembership -U root -G "$the_group" 2>&1 \
    | grep "group .* cannot be found") >&2; then
    exit 1
  fi

# Check every user
exec dscl . -list /Users \
  | while read each_username
  do
    printf "$each_username "
    dsmemberutil checkmembership -U "$each_username" -G "$the_group"
  done \
    | grep "is a member" | cut -d " " -f 1

# eof

Дополнительная информация:

Пять способов быть членом группы:

  1. PrimaryGroupID пользователя
  2. Входит в состав группы GroupMembership
  3. UUID перечислены в GroupMembers группы
  4. Унаследованное членство в группе X, будучи членом группы Y, которая указана в NestedGroups группы X
  5. Членство рассчитывается системой

Это можно изучить с помощью команд, таких как dscl . -read /Groups/somegroup

Пример 4. Членство в группе операторов печати __lpoperator_ наследуется членами группы администраторов печати __lpadmin_, а членство в этой группе наследуется членами группы администраторов .

Пример 5:

$ dscl . -read /Groups/netaccounts Comment
Comment:
 Group membership calculated by system
 Accounts from a remote directory server
$ 

СМОТРИТЕ ТАКЖЕ
    id(1), dscl(1), dsmemberutil(1), dseditgroup(8), DirectoryServiceAttributes(7), uuid(3)

38

Ты можешь использовать:

dscacheutil -q group -a name admin

или же:

dscacheutil -q group -a name staff

и т.п.

9

Примечание. Это был мой первоначальный ответ, написанный до того, как я понял, что этот ответ все еще дает неполный результат. (Например, он не находит членов группы Everyone !)Поэтому я написал лучший ответ, который включает в себя скрипт, который перечисляет всех членов группы в OS X.


Свойство GroupMembership mygroup может быть напечатано с помощью dscl следующим образом:

dscl . -read /Groups/mygroup GroupMembership

Но это не гарантирует вывод всех (или даже любых) членов группы. Чего не хватает, так это пользователей, которые являются членами группы, только имея ее в качестве основного идентификатора группы.

Типичным примером этого в OS X являются обычные учетные записи, которые имеют сотрудников (группа 20) в качестве своей основной группы, но не перечислены в свойстве GroupMembership группы персонала .

Этих пользователей можно найти, выполнив поиск числового идентификатора первичной группы (gid), как в этом примере для группы персонала (gid 20):

dscl . -list /Users PrimaryGroupID | grep " 20$"

и числовой идентификатор (PrimaryGroupID) mygroup находится:

dscl . -read /Groups/mygroup PrimaryGroupID
6

Чтобы получить все группы, в которые входит пользователь, вы можете использовать следующее:

id -nG <username>

Пример вывода:

staff com.apple.sharepoint.group.1 everyone localaccounts _appserverusr admin _appserveradm _lpadmin _appstore _lpoperator _developer com.apple.access_ftp com.apple.access_screensharing com.apple.access_ssh

Используя приведенную выше команду, можно получить всех пользователей, принадлежащих к группе:

OSX:

group=staff;
for i in $(dscl . list /users);
do [[ $(id -nG $i | grep $group) ]] && echo $i;
done

Unix:

group=sudo;
# This only outputs lines that match a username (from the start of line to a colon must not be a hash indicating a comment) 
for i in $(grep -oE "^[^#:]+" /etc/passwd);
do [[ $(id -nG $i | grep $group) ]] && echo $i;
done
4

dscl . -read /Groups/[groupname] | grep GroupMembership

ВНИМАНИЕ: Команда выше не всегда отображает полный список ВСЕХ членов группы. Например, для группы "штат" вы получаете только "root" как член группы, который является неполным. Для проверки используйте одну из следующих команд в качестве пользователя по умолчанию (НЕ "root"): id -Gn ИЛИ groups

В результате вы увидите все группы, в которые входит ваш зарегистрированный пользователь по умолчанию. Одним из них должен быть "персонал". Таким образом, помимо "root" есть еще члены группы "staff", которые не перечислены командой dscl . -read /Groups/[groupname] | grep GroupMembership . То же самое касается команды dscacheutil -q group -a name staff которая также предполагает, что только "root" является членом группы "staff", что, очевидно, является неполным.

Единственный надежный способ получить действительно ВСЕХ членов группы в терминале на OSX уже предоставлен здесь Арне Стенстрём. Это использует его функцию оболочки соответственно его сценарий оболочки. Оба прекрасно работают!

1

команда

Как и в ответе @ duperuser, следующее будет выводить только пользователей группы admin с пробелами между ними:

dscacheutil -q group -a name admin | grep -e '^users:' | sed 's/users: //'

Выход

Выполнение вышеупомянутой команды выдаст что-то вроде этого:

root your_username someone_else

Сломать

Команда dscacheutil используется для запроса информации о различных категориях системного кэша службы каталогов. Опция -q позволяет вам указать категорию, которую вы хотите запросить. Доступные категории: группа, хост, монтирование, протокол, rpc, сервис и пользователь. Далее мы запросим эту категорию, указав пару ключ-значение с опцией -a . В этом случае мы хотим перечислить группу, name ключа которой равно значению admin . Приведенная выше команда dscacheutil производит вывод, подобный следующему:

name: admin
password: *
gid: 80
users: root yourusername

Далее труба этот текст в grep и выбрать строку , содержащую строку users: в самом начале. Опция -e заставляет grep распознавать регулярные выражения. Символ ^ указывает на то, что мы хотим, чтобы users: находились в начале строки.

Это дает нам

users: root yourusername

Наконец, мы передаем это в sed и заменяем текстовых users: пустой строкой. В sed первая буква s означает замену. Текст между первой парой слешей (/users: /) - это то, что мы хотим заменить, а следующая пара косых черт (//) - это то, что мы хотим заменить (в данном случае, ничего).

0

Вот реализация этой проблемы, которая была получена из реализации в связанном обсуждении. Процедура является несколько общей, с ловушкой поиска службы каталогов для любой конкретной платформы / архитектуры, поэтому ее можно использовать без изменений в гетерогенной сети. Мы установили символическую ссылку на эту утилиту с именем zed . Другие источники этой реализации упоминаются в разделе атрибуции скрипта. Этот инструмент предназначен для работы как минимум на OSX, HP-UX, linux и SunOS, но не тестировался на SunOS и HP-UX. Скрипт был максимально протестирован на Ubuntu Linux 12.04 и Mavericks OSX 10.9.1. Выходные данные этого сценария совпадают с выходными данными для первой реализации сценария оболочки для этой проблемы и поэтому считаются правильными.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .