Bagaimana cara membuat daftar semua pengguna dalam grup Linux?

273

Bagaimana cara mendaftar semua anggota grup di Linux (dan mungkin juga unit lainnya)?

pengguna323094
sumber
1
@ Silmari89, Tidak jika dia ingin melakukannya secara terprogram.
Paul Tomblin
2
Saya baru di sini, saya menemukan bahwa SF ada setelah saya memposting pertanyaan. Saya setuju itu milik SF atau SO.
user323094
5
Heh, tentu saja, sekarang memiliki solusi terprogram, sehingga bisa dibenarkan di sini juga.
Zed

Jawaban:

103

Sayangnya, tidak ada cara yang baik dan portabel untuk melakukan ini yang saya tahu. Jika Anda mencoba mem-parsing / etc / group, seperti yang disarankan orang lain, Anda akan kehilangan pengguna yang memiliki grup itu sebagai grup utama mereka dan siapa saja yang telah ditambahkan ke grup itu melalui mekanisme selain UNIX flat file (yaitu LDAP, NIS, pam-pgsql, dll.).

Jika saya benar-benar harus melakukan ini sendiri, saya mungkin akan melakukannya secara terbalik: gunakan iduntuk mendapatkan grup dari setiap pengguna pada sistem (yang akan menarik semua sumber terlihat ke NSS), dan menggunakan Perl atau sesuatu yang serupa untuk mempertahankan hash tabel untuk setiap kelompok ditemukan mencatat keanggotaan pengguna itu.

Sunting: Tentu saja, ini membuat Anda memiliki masalah serupa: bagaimana cara mendapatkan daftar setiap pengguna pada sistem. Karena lokasi saya hanya menggunakan file datar dan LDAP, saya hanya bisa mendapatkan daftar dari kedua lokasi, tetapi itu mungkin atau mungkin tidak berlaku untuk lingkungan Anda.

Sunting 2: Seseorang yang lewat mengingatkan saya bahwa getent passwdakan mengembalikan daftar semua pengguna pada sistem termasuk yang dari LDAP / NIS / dll., Tetapi getent group masih akan merindukan pengguna yang hanya menjadi anggota melalui entri grup default, sehingga mengilhami saya untuk tulis hack cepat ini.


#!/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 ([email protected] or [email protected])
#
# 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";
    }
}
Zed
sumber
3
Terima kasih untuk semua yang menjawab. Saya sedang mencari cara portabel untuk melakukannya. Informasi Anda bahwa tidak ada cara yang mudah dan portabel sangat membantu. Anda juga menjelaskan secara terperinci tentang keadaan yang membantu saya memahami masalah lebih dalam, saya menghargai itu dan saya memilih jawaban Anda sebagai yang diterima.
user323094
2
Apakah mungkin bagi Anda untuk menyumbangkan skrip Anda ke yayasan Linux? Ini adalah 2012 dan masih belum ada cara mudah untuk mendapatkan anggota grup. Itulah hal yang membuat saya frustrasi tentang Linux.
Musim dingin
6
Saya menambahkan lisensi mirip ISC untuk Anda, yang harus kompatibel dengan hampir semua grup. Jangan ragu untuk mengirimkannya di mana saja Anda pikir itu akan diterima.
Zed
PAM tidak menyediakan informasi akun. Ini adalah Sakelar Layanan Nama (nsswitch) yang melakukan itu. Tidak semua 'basis data' (penyedia data) akan mendukung pencacahan jadi getent passwdmungkin tidak berfungsi (jika misalnya Anda menggunakan sssd).
Poin valid tentang PAM vs NSS - Saya mengubah referensi. Walaupun saya belum menggunakannya, sssd terlihat seperti pengganti nscd pada pandangan pertama daripada penyedia data yang tepat, dan jika rusak getent passwdsaya akan menganggapnya sebagai bug di sssd.
Zed
239
getent group <groupname>;

Ini portabel di Linux dan Solaris, dan bekerja dengan file grup / kata sandi lokal, NIS, dan konfigurasi LDAP.

Josh H.
sumber
43
Tidak menampilkan pengguna yang memiliki grup sebagai grup default mereka.
rlpowell
40

Gunakan Python untuk mendaftar anggota grup:

python -c "import grp; cetak grp.getgrnam ('GROUP_NAME') [3]"

Lihat https://docs.python.org/2/library/grp.html

Narayanaperumal Gurusamy
sumber
1
Sayangnya, tidak melaporkan anggota grup domain.
simlev
39
lid -g groupname | cut -f1 -d'(' 
Memo
sumber
7
Ini akan menjadi cara terbaik, kecuali tutupnya yang tidak dalam instalasi standar Debian. Di Ubuntu ada di paket libuser opsional (bukan yang ada di id-utils dengan nama yang sama). Saya tidak menemukannya di Debian :(
user323094
Bekerja untuk saya di Scientific Linux
blong
pada Debian Wheezy, tutupnya ada pada paket libuser juga
Lluís
2
@JohnMcGehee RHEL seharusnya dipanggil AustereLinux
goelakash
1
'-g' bukan pilihan bagi saya. Saya memiliki id-utils versi 4.6 yang diinstal pada Ubuntu 16.04.
Wilson Biggs
25

Perintah berikut akan mencantumkan semua pengguna milik <your_group_name>, tetapi hanya mereka yang dikelola oleh /etc/groupbasis data, bukan LDAP, NIS, dll. Ini juga berfungsi untuk grup sekunder saja , itu tidak akan mencantumkan pengguna yang memiliki grup yang ditetapkan sebagai utama karena grup utama adalah disimpan sebagai GID(ID grup numerik) dalam file /etc/passwd.

grep <your_group_name> /etc/group
Jose Bagatelli
sumber
4
Anda dapat grep langsung ke file itu seperti grep <username> / etc / group. Lebih cepat dan lebih murah.
paintbox
16

Perintah berikut akan mencantumkan semua pengguna milik <your_group_name>, tetapi hanya mereka yang dikelola oleh /etc/groupbasis data, bukan LDAP, NIS, dll. Ini juga berfungsi untuk grup sekunder saja , itu tidak akan mencantumkan pengguna yang memiliki grup yang ditetapkan sebagai utama karena grup utama adalah disimpan sebagai GID(ID grup numerik) dalam file /etc/passwd.

awk -F: '/^groupname/ {print $4;}' /etc/group
Didier Trosset
sumber
7
Tidak menampilkan pengguna yang memiliki grup sebagai grup default mereka.
rlpowell
3
Tidak memeriksa NIS dan LDAP.
Paweł Nadolski
12

Script shell berikut akan mengulangi semua pengguna dan hanya mencetak nama-nama pengguna yang dimiliki grup tertentu:

#!/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

Contoh penggunaan:

./script 'DOMAIN+Group Name'

Catatan: Solusi ini akan memeriksa NIS dan LDAP untuk pengguna dan grup (tidak hanya file passwddan group). Ini juga akan mempertimbangkan pengguna akun yang tidak ditambahkan ke grup tetapi memiliki grup yang ditetapkan sebagai grup utama.

Sunting: Menambahkan perbaikan untuk skenario langka di mana pengguna bukan milik grup dengan nama yang sama.

Sunting: ditulis dalam bentuk skrip shell; ditambahkan trueuntuk keluar dengan 0status seperti yang disarankan oleh @Max Chernyak alias hakunin ; dibuang stderruntuk melewati mereka yang sesekali groups: cannot find name for group ID xxxxxx.

Paweł Nadolski
sumber
Ini bagus, dan sangat ringkas, tetapi ia mencetak nama grup dan juga nama pengguna
andrew lorien
@ andrewlorien, saya harap saya memperbaiki masalah yang Anda sebutkan, jika tidak tolong berikan detail lebih lanjut.
Paweł Nadolski
Cuplikan ini bagus, tetapi mengembalikan kode 1, alasan apa pun mengapa ia tidak mengembalikan 0? Mudah diperbaiki mungkin?
Max Chernyak
@hakunin, itu tidak mengembalikan 0 ketika nama pengguna terakhir bukan milik grup. Anda dapat menambahkan "|| true" di pernyataan akhir untuk selalu mendapatkan 0 jika ini yang Anda inginkan. Anda dapat memeriksa kemudian output untuk melihat apakah ada pengguna yang ditemukan.
Paweł Nadolski
@ PawełNadolski saya menyadari, jadi akhirnya menambahkan ; true. Mengembalikan 0 adalah baik untuk menghindari tersandungnya sistem manajemen konfigurasi Anda (Chef, Ansible, dll).
Max Chernyak
7

Anda dapat melakukannya dalam satu baris perintah:

cut -d: -f1,4 /etc/passwd | grep $(getent group <groupname> | cut -d: -f3) | cut -d: -f1

Daftar perintah di atas semua pengguna memiliki groupname sebagai kelompok utama mereka

Jika Anda juga ingin membuat daftar pengguna yang memiliki nama grup sebagai grup kedua, gunakan perintah berikut

getent group <groupname> | cut -d: -f4 |  tr ',' '\n'
Bhavik
sumber
1
Peringatan: grepakan cocok dengan pengguna yang namanya berisi nomor grup (mis. sc0ttAkan ditampilkan sebagai bagian dari rootgrup). Jika ini merupakan masalah maka gunakan regex :$(getent group <groupname> | cut -d: -f3)\$(cocok dengan tanda koma, id grup, dan akhir baris). (Jangan menambahkan tanda kutip ke regex, atau bash mengeluh.)
Scott Stevens
@ScottS Jatuh resmi. Akan merekomendasikan langkah-langkah yang disarankan
Bhavik
3

hanya sedikit grep and tr:

$ grep ^$GROUP /etc/group | grep -o '[^:]*$' | tr ',' '\n'
user1
user2
user3
osti
sumber
4
Tidak menampilkan pengguna yang memiliki grup sebagai grup default mereka.
rlpowell
3

Implementasi Zed mungkin harus diperluas untuk bekerja pada beberapa UNIX utama lainnya.

Seseorang memiliki akses ke perangkat keras Solaris atau HP-UX ?; tidak menguji kasus-kasus itu.

#!/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 ([email protected] or [email protected])
#
# 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";
    }
}

Jika ada cara yang lebih baik untuk membagikan saran ini, harap beri tahu saya; Saya mempertimbangkan banyak hal, dan inilah yang saya pikirkan.

Billy McCloskey
sumber
Dikonfirmasi bekerja pada Solaris 10 setelah berganti id -Gnke/usr/xpg4/bin/id -G -n
user667489
3

Saya sudah melakukan ini mirip dengan kode perl di atas, tetapi diganti getent dan id dengan fungsi perl asli. Itu jauh lebih cepat dan harus bekerja di berbagai rasa * 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";
soinkleined
sumber
Jawaban dengan tautan saja tidak menganggap jawaban yang baik di Stack Overflow. Harap pertimbangkan untuk menghapus ini karena ini tidak memberikan jawaban atas pertanyaan atau menguraikan lebih lanjut tentang bagaimana jawaban ini lebih baik daripada jawaban yang diterima. Atau Anda dapat menambahkan ini sebagai komentar setelah Anda memiliki reputasi yang cukup. Anda selalu dapat mengomentari posting Anda sendiri.
Dipen Shah
2

Ada paket Debian dan Ubuntu yang berguna yang disebut ' anggota ' yang menyediakan fungsionalitas ini:

Deskripsi: Menunjukkan anggota grup; secara default, semua anggota adalah pelengkap grup: sedangkan grup menunjukkan grup yang menjadi milik pengguna tertentu, anggota menunjukkan pengguna yang termasuk dalam grup yang ditentukan.

... Anda dapat meminta anggota utama, anggota sekunder, keduanya pada satu baris, masing-masing pada baris yang berbeda.

Andrew
sumber
Bagaimana jika op menggunakan openwrt?
user2284570
Memang berguna, tetapi sayangnya tidak melaporkan anggota grup domain.
simlev
1
getent group insert_group_name_here | awk -F ':' '{print $4}' | sed 's|,| |g'

Ini mengembalikan daftar ruang yang dipisahkan dari pengguna yang telah saya gunakan dalam skrip untuk mengisi array.

for i in $(getent group ftp | awk -F ':' '{print $4}' | sed 's|,| |g')
    do
        userarray+=("$i")
    done

atau

userarray+=("$(getent group GROUPNAME | awk -F ':' '{print $4}' | sed 's|,| |g')")
parsecpython
sumber
0

Berikut ini adalah skrip yang mengembalikan daftar pengguna dari / etc / passwd dan / etc / group yang tidak memeriksa NIS atau LDAP, tetapi itu menunjukkan pengguna yang memiliki grup sebagai grup default mereka Diuji pada Debian 4.7 dan 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

atau sebagai one-liner, Anda dapat memotong dan menempelkan langsung dari sini (ubah nama grup dalam variabel pertama)

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
andrew lorien
sumber
0

Di UNIX (tidak seperti GNU / Linux), ada perintah listusers. Lihat halaman manual Solaris untuk daftar pengguna .

Perhatikan bahwa perintah ini adalah bagian dari Proyek Heirloom open-source . Saya berasumsi bahwa itu hilang dari GNU / Linux karena RMS tidak percaya pada grup dan izin. :-)

Alun Carr
sumber
1
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
knuhol
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.
Alun Carr
Dari situs web Proyek Heirloom: Proyek Heirloom menyediakan implementasi tradisional dari utilitas Unix standar. Dalam banyak kasus, mereka berasal dari bahan Unix asli yang dirilis sebagai Open Source oleh Caldera dan Sun. Antarmuka mengikuti praktik tradisional; mereka umumnya tetap kompatibel dengan Sistem V, meskipun ekstensi yang telah menjadi umum digunakan selama waktu kadang-kadang disediakan. Sebagian besar utilitas juga termasuk dalam varian yang bertujuan untuk kesesuaian POSIX.
Alun Carr
0

Berikut ini adalah skrip awk yang sangat sederhana yang memperhitungkan semua perangkap umum yang tercantum dalam jawaban lain:

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}'

Saya menggunakan ini dengan pengaturan ldap-enabled saya, berjalan pada apa saja dengan getent & awk yang sesuai standar, termasuk solaris 8+ dan hpux.

yunake
sumber
0
getent group groupname | awk -F: '{print $4}' | tr , '\n'

Ini memiliki 3 bagian:

1 - getent group groupnamemenunjukkan baris grup dalam file "/ etc / group". Alternatif untuk cat /etc/group | grep groupname.

2 - awkcetak hanya anggota dalam satu baris yang dipisahkan dengan ','.

3 - trganti ',' dengan baris baru dan cetak setiap pengguna secara berurutan.

4 - Opsional: Anda juga dapat menggunakan pipa lain dengan sort, jika pengguna terlalu banyak.

Salam

ioaniatr
sumber
0

Saya pikir cara termudah adalah langkah-langkah berikut, Anda tidak perlu menginstal paket atau perangkat lunak apa pun:

  1. Pertama, Anda menemukan GID grup yang ingin Anda ketahui pengguna, ada banyak cara untuk itu: cat / etc / group (kolom terakhir adalah GID) id pengguna (pengguna adalah seseorang yang menjadi milik pengguna grup)

  2. Sekarang Anda akan mendaftar semua pengguna pada file / etc / passwd, tetapi Anda akan menerapkan beberapa filter dengan sekuel perintah berikut untuk mendapatkan hanya anggota grup sebelumnya.

cut -d: -f1,4 / etc / passwd | grep GID (GID adalah angka yang Anda dapatkan dari langkah 1)

perintah cut akan memilih hanya beberapa "kolom" dari file, parameter d menetapkan pembatas ":" dalam kasus ini, parameter -f memilih "bidang" (atau kolom) yang akan ditampilkan 1 dan 4 dalam kasus keluar (pada file / etc / passwd, kolom 1º adalah nama pengguna dan 4º adalah GID dari grup yang dimiliki pengguna), untuk menyelesaikan | grep GID akan memfilter hanya grup (pada kolom 4º) yang Anda telah memilih.

Mauro Matsudo
sumber
0

Berikut ini satu-baris Python lain yang memperhitungkan keanggotaan grup default pengguna (dari /etc/passwd) serta dari database grup ( /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]])"
Brian Minton
sumber
-1

Saya sudah mencoba grep 'sample-group-name' /etc/group, yang akan mencantumkan semua anggota grup yang Anda tentukan berdasarkan contoh di sini

jameshwart lopez
sumber
1
Grepping /etc/groupsudah ada dalam setidaknya 3 jawaban lain, apa nilai yang ditambahkan oleh jawaban Anda? Juga, semua jawaban lain memiliki komentar bahwa solusi tersebut hanya berfungsi untuk grup sekunder dan juga tidak berfungsi untuk akun yang dikelola oleh LDAP, NIS, dll.
David Ferenczy Rogožan