ฉันจะแสดงรายการสมาชิกทั้งหมดของกลุ่มใน Linux (และอาจเป็น unices อื่น ๆ ) ได้อย่างไร
ฉันจะแสดงรายการสมาชิกทั้งหมดของกลุ่มใน Linux (และอาจเป็น unices อื่น ๆ ) ได้อย่างไร
คำตอบ:
น่าเสียดายที่ไม่มีวิธีพกพาที่ดีในการทำสิ่งนี้ที่ฉันรู้ หากคุณพยายามแยก / etc / group ตามที่คนอื่นกำลังแนะนำคุณจะพลาดผู้ใช้ที่มีกลุ่มนั้นเป็นกลุ่มหลักและทุกคนที่ถูกเพิ่มในกลุ่มนั้นผ่านกลไกอื่นที่ไม่ใช่ไฟล์แฟล็ต UNIX (เช่น LDAP, NIS, pam-pgsql ฯลฯ )
หากฉันต้องทำสิ่งนี้ด้วยตัวเองฉันอาจทำแบบย้อนกลับ: ใช้id
เพื่อให้กลุ่มผู้ใช้ทุกคนในระบบ (ซึ่งจะดึงแหล่งที่มาทั้งหมดที่มองเห็นได้จาก NSS) และใช้ Perl หรือสิ่งที่คล้ายกันเพื่อรักษาแฮช ตารางสำหรับแต่ละกลุ่มค้นพบการสังเกตการเป็นสมาชิกของผู้ใช้นั้น
แก้ไข: แน่นอนสิ่งนี้ทำให้คุณมีปัญหาที่คล้ายกัน: วิธีการรับรายชื่อผู้ใช้ทุกคนในระบบ เนื่องจากที่ตั้งของฉันใช้เฉพาะไฟล์ flat และ LDAP เท่านั้นฉันสามารถรับรายการจากทั้งสองตำแหน่งได้ แต่อาจจะเป็นจริงหรือไม่ก็ได้
แก้ไข 2: ใครบางคนในการเตือนฉันว่าgetent passwd
จะส่งคืนรายชื่อผู้ใช้ทั้งหมดในระบบรวมถึงผู้ใช้จาก LDAP / NIS / etc แต่ 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
getent group <groupname>;
สามารถพกพาได้ทั้งใน Linux และ Solaris และสามารถทำงานกับไฟล์กลุ่ม / รหัสผ่านในท้องถิ่น, NIS และการกำหนดค่า LDAP
ใช้ Python เพื่อแสดงรายการ groupmembers:
python -c "import grp; พิมพ์ grp.getgrnam ('GROUP_NAME') [3]"
lid -g groupname | cut -f1 -d'('
คำสั่งต่อไปนี้จะแสดงรายการผู้ใช้ทั้งหมดที่เป็นของ<your_group_name>
แต่เฉพาะผู้ที่จัดการโดย/etc/group
ฐานข้อมูลไม่ใช่ LDAP, NIS ฯลฯ นอกจากนี้ยังสามารถใช้ได้กับกลุ่มรองเท่านั้นโดยจะไม่แสดงรายการผู้ใช้ที่มีกลุ่มนั้นถูกตั้งค่าเป็นกลุ่มหลักเนื่องจากกลุ่มหลักคือ เก็บไว้เป็นGID
(ID กลุ่มตัวเลข) /etc/passwd
ในแฟ้ม
grep <your_group_name> /etc/group
คำสั่งต่อไปนี้จะแสดงรายการผู้ใช้ทั้งหมดที่เป็นของ<your_group_name>
แต่เฉพาะผู้ที่จัดการโดย/etc/group
ฐานข้อมูลไม่ใช่ LDAP, NIS ฯลฯ นอกจากนี้ยังสามารถใช้ได้กับกลุ่มรองเท่านั้นโดยจะไม่แสดงรายการผู้ใช้ที่มีกลุ่มนั้นถูกตั้งค่าเป็นกลุ่มหลักเนื่องจากกลุ่มหลักคือ เก็บไว้เป็นGID
(ID กลุ่มตัวเลข) /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
PawełNadolskiฉันตระหนักจึงจบลงด้วยการเพิ่ม การส่งคืน 0 เป็นสิ่งที่ดีเพื่อหลีกเลี่ยงการสะดุดระบบการจัดการการกำหนดค่าของคุณ (Chef, Ansible และอื่น ๆ )
คุณสามารถทำได้ในบรรทัดคำสั่งเดียว:
cut -d: -f1,4 /etc/passwd | grep $(getent group <groupname> | cut -d: -f3) | cut -d: -f1
คำสั่งดังกล่าวรายชื่อผู้ใช้ทั้งหมดมีGROUPNAMEเป็นกลุ่มหลักของพวกเขา
หากคุณต้องการแสดงรายการผู้ใช้ที่มีgroupnameเป็นกลุ่มรองให้ใช้คำสั่งต่อไปนี้
getent group <groupname> | cut -d: -f4 | tr ',' '\n'
grep
จะจับคู่ผู้ใช้ที่ชื่อมีหมายเลขกลุ่ม (เช่นsc0tt
จะแสดงเป็นส่วนหนึ่งของroot
กลุ่ม) หากเป็นปัญหาให้ใช้ regex :$(getent group <groupname> | cut -d: -f3)\$
(ตรงกับเครื่องหมายอัฒภาค, id กลุ่มและจุดสิ้นสุดของบรรทัด) (อย่าเพิ่มเครื่องหมายคำพูดลงใน regex หรือ bash บ่น)
เพียง grep และ tr เล็กน้อย:
$ grep ^$GROUP /etc/group | grep -o '[^:]*$' | tr ',' '\n'
user1
user2
user3
การใช้งานของ 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 พื้นเมือง มันเร็วกว่ามากและควรใช้กับรสชาติที่แตกต่างกัน *
#!/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 สำหรับ ListUsers
โปรดทราบว่าคำสั่งนี้เป็นส่วนหนึ่งของโอเพนซอร์ส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 แต่คุณจะใช้ตัวกรองบางตัวที่มีภาคต่อของคำสั่งต่อไปนี้เพื่อรับเฉพาะสมาชิกของกลุ่มก่อนหน้า
ตัด -d: -f1,4 / etc / passwd | grep GID (GID คือหมายเลขที่คุณได้รับจากขั้นตอนที่ 1)
คำสั่ง cut จะเลือกเพียงบางส่วน "คอลัมน์" ของไฟล์พารามิเตอร์ d ตั้งค่าตัวคั่น ":" ในกรณีนี้พารามิเตอร์ -f เลือก "ฟิลด์" (หรือคอลัมน์) เพื่อแสดง 1 และ 4 ในกรณีออก (บน ไฟล์ / etc / passwd, คอลัมน์ 1 is คือชื่อของผู้ใช้และ4ºเป็น GID ของกลุ่มที่ผู้ใช้เป็นเจ้าของ), เพื่อจบ | grep GID จะกรองเฉพาะกลุ่ม (ในคอลัมน์4º) ที่คุณ ได้เลือก
นี่เป็นอีกหนึ่งงูเหลือมซับในที่คำนึงถึงความเป็นสมาชิกกลุ่มเริ่มต้นของผู้ใช้ (จาก/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 และอื่น ๆ