如何在Perl中获取POSIX组成员列表

时间:2013-01-09 05:11:37

标签: perl posix

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

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

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

2 个答案:

答案 0 :(得分:1)

我会说只使用getgrent()而不用担心空格。

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

在Linux上,useraddadduser命令甚至不允许文件名中的空格。在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'
$ 

您的系统上是否包含空格的用户名?

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

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

等。但这是一个真的不好的主意。 Perl的getgr*()无法判断某个论坛是否包含foo bar的一个条目或foobar的两个条目(这就是您要问的内容),我可以'使用shell的~name语法来引用帐户的主目录。我可以使用其他方法来获取这两个信息,但是首先避免创建这样的帐户要容易得多。

如果你真的很担心某些管理员愚蠢到创建这样一个帐户,那么你可以使用一些已经讨论过的替代方法。但正如我所说,我不认为这是值得的。

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

更新2:

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

  

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

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

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

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

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

答案 1 :(得分: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

资源