Я пытаюсь написать сценарий, который выводит каждого пользователя и его группу в отдельной строке следующим образом:
user1 group1
user2 group1
user3 group2
...
user10 group6
и т.п.
Я пишу для этого сценарий на Python, но мне было интересно, как SO может это сделать.
p.s. Попробуйте его на любом языке, но я бы предпочел питон.
Обновлено: Я работаю над Linux. Ubuntu 8.10 или CentOS =)
Спасибо за этот комментарий, без него я бы не понял, о чем этот вопрос (пользователи? Группы? ЧТО?).
Обратите внимание, что пользователь может быть (и часто бывает) в нескольких группах.






модуль grp - ваш друг. Посмотрите на grp.getgrall(), чтобы получить список всех групп и их участников.
Пример РЕДАКТИРОВАТЬ:
import grp
groups = grp.getgrall()
for group in groups:
for user in group[3]:
print user, group[0]
Это сработало, но, похоже, это не список всех пользователей. Есть предположения? $ ./script.py | wc -l 81 $ sudo cat / etc / shadow | туалет -l 406
Я думаю, что я вижу, что сервер, на котором я использую это, имеет массу групп без пользователей в них (старые, старые группы), которые все еще существуют. Этот скрипт игнорирует группы, в которых нет пользователей, и это нормально, это то, что мне нужно! знак равно
Это решение перечисляет только группы пользователей вторичный. Я прочитал вопрос, что он запрашивает «их группу», то есть группу начальный [единственного] пользователя?
См. Ответ С.Лотта для решения, которое показывает только основную группу.
Для * nix у вас есть модули pwd и grp. Вы повторяете pwd.getpwall(), чтобы получить всех пользователей. Вы можете найти их названия групп с помощью grp.getgrgid(gid).
import pwd, grp
for p in pwd.getpwall():
print p[0], grp.getgrgid(p[3])[0]
pwd.getpwall показывает только локальных пользователей, а не пользователей, например, ldap (когда enumerate = false)
ш / баш:
getent passwd | cut -f1 -d: | while read name; do echo -n "$name " ; groups $name ; done
Он это сделал, но добавил: «Попробуй его на любом языке, но я бы предпочел python».
a simple function which is capable to deal with the structure of any one of these files (/etc/passwd and /etc/group).
Я считаю, что этот код соответствует вашим потребностям, со встроенными функциями Python и без дополнительного модуля:
#!/usr/bin/python
def read_and_parse(filename):
"""
Reads and parses lines from /etc/passwd and /etc/group.
Parameters
filename : str
Full path for filename.
"""
data = []
with open(filename, "r") as f:
for line in f.readlines():
data.append(line.split(":")[0])
data.sort()
for item in data:
print("- " + item)
read_and_parse("/etc/group")
read_and_parse("/etc/passwd")
Пропускает группы LDAP.
Вызов python для grp.getgrall() показывает только локальные группы, в отличие от вызова функции getgrouplist c, которая повторно запускает всех пользователей, например. также пользователи в sssd, которые поддерживаются ldap, но с отключенным перечислением. (как в FreeIPA).
После поиска самого простого способа получить все группы, к которым принадлежит пользователь, в python, лучший способ, который я нашел, - это фактически вызвать функцию Getgrouplist c:
#!/usr/bin/python
import grp, pwd, os
from ctypes import *
from ctypes.util import find_library
libc = cdll.LoadLibrary(find_library('libc'))
getgrouplist = libc.getgrouplist
# 50 groups should be enought?
ngroups = 50
getgrouplist.argtypes = [c_char_p, c_uint, POINTER(c_uint * ngroups), POINTER(c_int)]
getgrouplist.restype = c_int32
grouplist = (c_uint * ngroups)()
ngrouplist = c_int(ngroups)
user = pwd.getpwuid(2540485)
ct = getgrouplist(user.pw_name, user.pw_gid, byref(grouplist), byref(ngrouplist))
# if 50 groups was not enough this will be -1, try again
# luckily the last call put the correct number of groups in ngrouplist
if ct < 0:
getgrouplist.argtypes = [c_char_p, c_uint, POINTER(c_uint *int(ngrouplist.value)), POINTER(c_int)]
grouplist = (c_uint * int(ngrouplist.value))()
ct = getgrouplist(user.pw_name, user.pw_gid, byref(grouplist), byref(ngrouplist))
for i in xrange(0, ct):
gid = grouplist[i]
print grp.getgrgid(gid).gr_name
Получение списка всех пользователей для запуска этой функции аналогичным образом потребует выяснить, какой вызов c выполняется getent passwd, и вызвать его в python.
Чтобы сделать этот Python3 дружественным, поскольку байты и строки более разделены, и автоматическое кодирование не происходит. getgrouplist должен иметь строку байтов в качестве первого аргумента, например: getgrouplist(bytes(user.pw_name, 'UTF-8'), ...). Очевидно, что xrange также является range в Python3. Но это устраняет любые проблемы с преобразованием из Python2 в Python3.
В моей системе (rhel) find_library('libc') вернул None. Казалось, что это все равно работает, возможно, указывая на то, что libc используется по умолчанию, но я все же рекомендовал бы вместо этого использовать find_library('c').
С какой операционной системой вы работаете?