Làm cách nào để liệt kê tất cả các thành viên của một nhóm trong Linux (và có thể các đơn vị khác)?
Làm cách nào để liệt kê tất cả các thành viên của một nhóm trong Linux (và có thể các đơn vị khác)?
Câu trả lời:
Thật không may, không có cách tốt, di động để làm điều này mà tôi biết. Nếu bạn cố phân tích / etc / nhóm, như những người khác đang đề xuất, bạn sẽ bỏ lỡ những người dùng có nhóm đó là nhóm chính của họ và bất kỳ ai đã được thêm vào nhóm đó thông qua một cơ chế khác ngoài các tệp phẳng UNIX (ví dụ LDAP, NIS, pam-pssql, v.v.).
Nếu tôi hoàn toàn phải tự làm điều này, có lẽ tôi sẽ làm điều ngược lại: sử dụng id
để có được các nhóm của mọi người dùng trên hệ thống (sẽ kéo tất cả các nguồn hiển thị cho NSS) và sử dụng Perl hoặc một cái gì đó tương tự để duy trì hàm băm bảng cho mỗi nhóm phát hiện ghi chú thành viên của người dùng đó.
Chỉnh sửa: Tất nhiên, điều này khiến bạn gặp phải một vấn đề tương tự: làm thế nào để có được danh sách mọi người dùng trên hệ thống. Vì vị trí của tôi chỉ sử dụng các tệp phẳng và LDAP, tôi chỉ có thể nhận danh sách từ cả hai vị trí, nhưng điều đó có thể đúng hoặc không đúng với môi trường của bạn.
Chỉnh sửa 2: Một người nào đó đã nhắc nhở tôi rằng getent passwd
sẽ trả về danh sách tất cả người dùng trên hệ thống, bao gồm cả những người dùng từ LDAP / NIS / v.v., nhưng getent group
vẫn sẽ nhớ những người dùng chỉ là thành viên thông qua mục nhập nhóm mặc định, vì vậy điều đó đã truyền cảm hứng cho tôi viết hack nhanh này.
#!/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
có thể không hoạt động (ví dụ: nếu bạn đang sử dụng sssd).
getent passwd
tôi sẽ coi đó là một lỗi trong sssd.
Sử dụng Python để liệt kê các thành viên nhóm:
python -c "nhập grp; in grp.getgrnam ('GROUP_NAME') [3]"
lid -g groupname | cut -f1 -d'('
Lệnh sau sẽ liệt kê tất cả người dùng thuộc về <your_group_name>
, nhưng chỉ những người được quản lý bởi /etc/group
cơ sở dữ liệu, không phải LDAP, NIS, v.v. Nó cũng chỉ hoạt động cho các nhóm thứ cấp , nó sẽ không liệt kê những người dùng có nhóm đó được đặt làm chính vì nhóm chính là được lưu dưới dạng GID
(ID nhóm số) trong tệp /etc/passwd
.
grep <your_group_name> /etc/group
Lệnh sau sẽ liệt kê tất cả người dùng thuộc về <your_group_name>
, nhưng chỉ những người được quản lý bởi /etc/group
cơ sở dữ liệu, không phải LDAP, NIS, v.v. Nó cũng chỉ hoạt động cho các nhóm thứ cấp , nó sẽ không liệt kê những người dùng có nhóm đó được đặt làm chính vì nhóm chính là được lưu dưới dạng GID
(ID nhóm số) trong tệp /etc/passwd
.
awk -F: '/^groupname/ {print $4;}' /etc/group
Tập lệnh shell sau sẽ lặp qua tất cả người dùng và chỉ in những tên người dùng thuộc về một nhóm nhất định:
#!/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
Ví dụ sử dụng:
./script 'DOMAIN+Group Name'
Lưu ý: Giải pháp này sẽ kiểm tra NIS và LDAP cho người dùng và nhóm (không chỉ passwd
và group
các tệp). Nó cũng sẽ đưa vào tài khoản người dùng không được thêm vào một nhóm nhưng có nhóm được đặt làm nhóm chính.
Chỉnh sửa: Đã thêm sửa chữa cho kịch bản hiếm khi người dùng không thuộc nhóm có cùng tên.
Chỉnh sửa: được viết dưới dạng một kịch bản shell; được thêm vào true
để thoát với 0
trạng thái theo đề xuất của @Max Chernyak aka hakunin ; loại bỏ stderr
để bỏ qua những thỉnh thoảng groups: cannot find name for group ID xxxxxx
.
; true
. Trở về 0 là tốt để tránh vấp ngã hệ thống quản lý cấu hình của bạn (Chef, Ansible, v.v.).
Bạn có thể làm điều đó trong một dòng lệnh duy nhất:
cut -d: -f1,4 /etc/passwd | grep $(getent group <groupname> | cut -d: -f3) | cut -d: -f1
Lệnh trên liệt kê tất cả người dùng có tên nhóm là nhóm chính của họ
Nếu bạn cũng muốn liệt kê những người dùng có tên nhóm là nhóm phụ của họ, hãy sử dụng lệnh sau
getent group <groupname> | cut -d: -f4 | tr ',' '\n'
grep
sẽ khớp với người dùng có tên chứa số nhóm (ví dụ: sc0tt
sẽ được hiển thị như một phần của root
nhóm). Nếu đây là một vấn đề thì hãy sử dụng regex :$(getent group <groupname> | cut -d: -f3)\$
(khớp với dấu chấm phẩy, id nhóm và cuối dòng). (Đừng thêm dấu ngoặc kép vào biểu thức chính quy hoặc bash phàn nàn.)
Việc triển khai của Zed có lẽ nên được mở rộng để hoạt động trên một số UNIX chính khác.
Ai đó có quyền truy cập vào phần cứng Solaris hoặc HP-UX?; đã không kiểm tra những trường hợp đó.
#!/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";
}
}
Nếu có một cách tốt hơn để chia sẻ đề xuất này, xin vui lòng cho tôi biết; Tôi đã xem xét nhiều cách, và đây là những gì tôi nghĩ ra.
id -Gn
thành/usr/xpg4/bin/id -G -n
Tôi đã thực hiện điều này tương tự như mã perl ở trên, nhưng đã thay thế getent và id bằng các hàm perl gốc. Nó nhanh hơn nhiều và sẽ hoạt động trên các hương vị * nix khác nhau.
#!/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";
Có một gói Debian và Ubuntu tiện dụng được gọi là ' thành viên ' cung cấp chức năng này:
Mô tả: Hiển thị các thành viên của một nhóm; theo mặc định, tất cả các thành viên là phần bổ sung của các nhóm: trong khi các nhóm hiển thị các nhóm mà người dùng được chỉ định thuộc về, các thành viên hiển thị người dùng thuộc về một nhóm được chỉ định.
... Bạn có thể yêu cầu các thành viên chính, thành viên phụ, cả hai trên một dòng, mỗi dòng trên các dòng riêng biệt.
getent group insert_group_name_here | awk -F ':' '{print $4}' | sed 's|,| |g'
Điều này trả về một danh sách người dùng được phân tách bằng dấu cách mà tôi đã sử dụng trong các tập lệnh để điền vào các mảng.
for i in $(getent group ftp | awk -F ':' '{print $4}' | sed 's|,| |g')
do
userarray+=("$i")
done
hoặc là
userarray+=("$(getent group GROUPNAME | awk -F ':' '{print $4}' | sed 's|,| |g')")
Đây là tập lệnh trả về danh sách người dùng từ / etc / passwd và / etc / group, nó không kiểm tra NIS hoặc LDAP, nhưng nó cho thấy người dùng có nhóm là nhóm mặc định của họ được thử nghiệm trên Debian 4.7 và 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
hoặc dưới dạng một lớp lót, bạn có thể cắt và dán thẳng từ đây (thay đổi tên nhóm trong biến đầu tiên)
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
Trong UNIX (trái ngược với GNU / Linux), có lệnh người nghe. Xem trang người đàn ông Solaris để biết người nghe .
Lưu ý rằng lệnh này là một phần của Dự án Gia truyền nguồn mở . Tôi cho rằng nó thiếu từ GNU / Linux vì RMS không tin vào các nhóm và quyền. :-)
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.
Đây là một kịch bản awk rất đơn giản có tính đến tất cả các cạm bẫy phổ biến được liệt kê trong các câu trả lời khác:
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}'
Tôi đang sử dụng tính năng này với thiết lập hỗ trợ ldap của mình, chạy trên mọi thứ với getent & awk tuân thủ tiêu chuẩn, bao gồm solaris 8+ và hpux.
getent group groupname | awk -F: '{print $4}' | tr , '\n'
Điều này có 3 phần:
1 - getent group groupname
hiển thị dòng của nhóm trong tệp "/ etc / group". Thay thế cho cat /etc/group | grep groupname
.
2 - chỉ awk
in các thành viên trong một dòng được phân tách bằng ','.
3 - tr
thay thế ',' bằng một dòng mới và in mỗi người dùng liên tiếp.
4 - Tùy chọn: Bạn cũng có thể sử dụng một đường ống khác với sort
, nếu người dùng quá nhiều.
Trân trọng
Tôi nghĩ cách dễ nhất là các bước sau, bạn sẽ không cần cài đặt bất kỳ gói hoặc phần mềm nào:
Trước tiên, bạn tìm ra GID của nhóm mà bạn muốn biết người dùng, có rất nhiều cách cho việc đó: cat / etc / group (cột cuối cùng là người dùng id GID) (người dùng là người thuộc về nhóm)
Bây giờ bạn sẽ liệt kê tất cả người dùng trên tệp / etc / passwd, nhưng bạn sẽ áp dụng một số bộ lọc với các lệnh tiếp theo sau để chỉ nhận các thành viên của nhóm trước.
cut -d: -f1,4 / etc / passwd | grep GID (GID là số bạn nhận được từ bước 1)
Lệnh cắt sẽ chỉ chọn một số "cột" của tệp, tham số d đặt dấu phân cách ":" trong trường hợp này, tham số -f chọn "trường" (hoặc cột) để hiển thị 1 và 4 trong trường hợp ngoài (bật tệp / etc / passwd, cột 1 is là tên của người dùng và 4º là GID của nhóm mà người dùng thuộc về), để hoàn thiện | grep GID sẽ chỉ lọc nhóm (trên cột 4)) mà bạn đã chọn.
Đây là một lớp lót Python khác có tính đến tư cách thành viên nhóm mặc định của người dùng (từ /etc/passwd
) cũng như từ cơ sở dữ liệu nhóm ( /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]])"
Tôi đã thử grep 'sample-group-name' /etc/group
, nó sẽ liệt kê tất cả các thành viên của nhóm bạn đã chỉ định dựa trên ví dụ ở đây
/etc/group
có ít nhất 3 câu trả lời khác, câu trả lời của bạn có giá trị gì đối với chúng? Ngoài ra, tất cả những câu trả lời khác đều có nhận xét rằng giải pháp đó chỉ hoạt động cho các nhóm thứ cấp và cũng không hoạt động đối với tài khoản được quản lý bởi LDAP, NIS, v.v.