【问题标题】:Python script to list users and groups用于列出用户和组的 Python 脚本
【发布时间】:2010-09-30 02:44:20
【问题描述】:

我正在尝试编写一个脚本,在自己的行上输出每个用户及其组,如下所示:

user1 group1  
user2 group1  
user3 group2  
...  
user10 group6

等等。

我正在为此用 python 编写一个脚本,但想知道 SO 是如何做到这一点的。

附言用任何语言尝试一下,但我更喜欢 python。

编辑:我在 Linux 上工作。 Ubuntu 8.10 或 CentOS =)

【问题讨论】:

  • 您使用的是哪个操作系统?
  • 感谢您的评论,没有它我不知道这个问题是关于什么的(用户?组?什么?)。
  • 请注意,一个用户可以(并且经常)在多个组中。

标签: python linux sysadmin


【解决方案1】:

grp.getgrall() 的python 调用仅显示本地组,这与对返回所有用户的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

获取所有用户的列表以运行此函数同样需要弄清楚 getent passwd 进行了哪些 c 调用并在 python 中调用它。

【讨论】:

  • 为了让这个 Python3 友好,因为字节和字符串更加分离并且不会发生自动编码。 getgrouplist 应该有一个字节字符串作为它的第一个参数,如下所示:getgrouplist(bytes(user.pw_name, 'UTF-8'), ...)。显然xrange 在 Python3 中也是 range。但这清除了从 Python2 到 Python3 的任何转换问题。
  • 在我的系统 (rhel) 上,find_library('libc') 返回无。无论如何它似乎都可以工作,也许表明 libc 是默认值,但我仍然建议使用 find_library('c') 代替。
【解决方案2】:

一个简单的函数,它能够处理任何一个文件(/etc/passwd 和 /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 组。
【解决方案3】:

对于 *nix,您有 pwdgrp 模块。您遍历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 时)
【解决方案4】:

sh/bash:

getent passwd | cut -f1 -d: | while read name; do echo -n "$name " ; groups $name ; done

【讨论】:

  • 他做到了,但他补充说“用任何语言尝试一下,但我更喜欢 python。”
【解决方案5】:

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 | wc -l 406
  • 我认为我所看到的是我正在使用它的服务器上有大量没有用户的组(旧的、旧的组)碰巧仍然存在。此脚本忽略其中没有用户的组,这很好,这就是我需要的! =)
  • 此解决方案仅列出用户的 辅助 组。我读到的问题是它要求“他们的组”,即 [singular] 用户的 primary 组?
  • 查看 S.Lott 的回答,了解仅显示主要组的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
相关资源
最近更新 更多