1

POSIX有没有办法在 Perl中获取一个组的所有成员的列表?

我不能使用getgrent()和类似的,因为它将列表作为空格分隔的字符串返回,并且某些用户名中可以有空格。

我必须处理用户名和组名中的空格,因为我在 AD 环境中工作,其他组织可以在其中创建用户和组,所以我试图考虑可能的边缘情况。

4

2 回答 2

1

我会说只是使用getgrent(),不要担心空间。

可以通过手动编辑创建一个包含一个或多个空格的用户名/etc/passwd,但它也会导致其他问题。例如,~fooisfoo的主目录,但~foo baris notfoo bar的主目录。

在 Linux 上,useraddandadduser命令甚至不允许文件名中有空格。在 Linux Mint 14(基于 Ubuntu 12.10)上:

$ sudo adduser 'foo bar'
adduser: To avoid problems, the username should consist only of
letters, digits, underscores, periods, at signs and dashes, and not start with
a dash (as defined by IEEE Std 1003.1-2001). For compatibility with Samba
machine accounts $ is also supported at the end of the username
$ sudo useradd !$
sudo useradd 'foo bar'
useradd: invalid user name 'foo bar'
$ 

你的系统上真的有带空格的用户名吗?

更新:我发现实际上可以使用空格创建用户名。useradd并且adduser不允许它(并且您应该使用其中一个命令或类似的命令来创建新帐户)。/etc/passwd但是如果我使用手动编辑sudo vipw,我可以创建一个名为 的用户foo bar,我可以这样做:

  • su - '富吧'
  • ssh 'foo bar@localhost'

等等,但这是一个非常糟糕的主意。Perlgetgr*()无法判断一个组是否包含一个用于和的条目或foo bar两个条目(这是您要问的),而且我不能使用 shell 的语法来引用帐户的主目录。我可以使用其他方法来获取这两条信息,但首先避免创建这样的帐户要容易得多。foobar~name

如果您非常担心某些管理员愚蠢地创建了这样的帐户,那么您可以使用一些已经讨论过的替代方法。但正如我所说,我认为这不值得付出努力。

(Perl 可以通过用字符而不是空格分隔列表来避免这个问题:,因为这些实际上与系统所依赖的/etc/passwdand的格式不兼容/etc/group。但现在改变它为时已晚。)

更新 2:

正如您在评论中所说(我已将其编辑到您的问题中):

我必须处理用户名和组名中的空格,因为我在 AD 环境中工作,其他组织可以在其中创建用户和组,所以我试图考虑可能的边缘情况。

您来自同一评论的解决方案:

map((getgrgrid($_))[0], split(/ /, `id -G $username`))

可能是最好的解决方法。(id -G打印数字组 ID;显然不能包含空格。)

可能还值得检查您是否真的有用户名或组名,其中包含空格(当然,这并不能防止将来添加此类名称)。我想知道您的 POSIX 系统实际上是如何处理这些名称的。如果它们以某种方式自动翻译它们,我不会感到惊讶。即便如此,您的id -G解决方案仍然有效。

于 2013-01-09T07:42:43.940 回答
0

如果我有/etc/group

...
postgres:x:26:
fsniper:x:481:
clamupdate:x:480:
some spacey group:x:482:saml, some spacey user

我可以使用以下命令查看该组的成员:

% getent group
...
postgres:x:26:
fsniper:x:481:
clamupdate:x:480:
some spacey group:x:482:saml,some spacey user

或者,如果您知道您感兴趣的特定群体:

% getent group "some spacey group"
some spacey group:x:482:saml,some spacey user

这些可以像这样包装在 Perl 脚本中:

#!/usr/bin/perl

use feature qw(say);
chomp (my $getent = `getent group "some spacey group" | sed 's/.*://'`);
my @users = split(/,/, $getent);
foreach my $i (@users) { say $i; }

运行它:

% ./b.pl 
saml
some spacey user

资源

于 2013-01-09T06:02:41.810 回答