POSIX
有没有办法在 Perl中获取一个组的所有成员的列表?
我不能使用getgrent()
和类似的,因为它将列表作为空格分隔的字符串返回,并且某些用户名中可以有空格。
我必须处理用户名和组名中的空格,因为我在 AD 环境中工作,其他组织可以在其中创建用户和组,所以我试图考虑可能的边缘情况。
POSIX
有没有办法在 Perl中获取一个组的所有成员的列表?
我不能使用getgrent()
和类似的,因为它将列表作为空格分隔的字符串返回,并且某些用户名中可以有空格。
我必须处理用户名和组名中的空格,因为我在 AD 环境中工作,其他组织可以在其中创建用户和组,所以我试图考虑可能的边缘情况。
我会说只是使用getgrent()
,不要担心空间。
可以通过手动编辑创建一个包含一个或多个空格的用户名/etc/passwd
,但它也会导致其他问题。例如,~foo
isfoo
的主目录,但~foo bar
is notfoo bar
的主目录。
在 Linux 上,useradd
andadduser
命令甚至不允许文件名中有空格。在 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
,我可以这样做:
等等,但这是一个非常糟糕的主意。Perlgetgr*()
无法判断一个组是否包含一个用于和的条目或foo bar
两个条目(这是您要问的),而且我不能使用 shell 的语法来引用帐户的主目录。我可以使用其他方法来获取这两条信息,但首先避免创建这样的帐户要容易得多。foo
bar
~name
如果您非常担心某些管理员愚蠢地创建了这样的帐户,那么您可以使用一些已经讨论过的替代方法。但正如我所说,我认为这不值得付出努力。
(Perl 可以通过用字符而不是空格分隔列表来避免这个问题:
,因为这些实际上与系统所依赖的/etc/passwd
and的格式不兼容/etc/group
。但现在改变它为时已晚。)
更新 2:
正如您在评论中所说(我已将其编辑到您的问题中):
我必须处理用户名和组名中的空格,因为我在 AD 环境中工作,其他组织可以在其中创建用户和组,所以我试图考虑可能的边缘情况。
您来自同一评论的解决方案:
map((getgrgrid($_))[0], split(/ /, `id -G $username`))
可能是最好的解决方法。(id -G
打印数字组 ID;显然不能包含空格。)
可能还值得检查您是否真的有用户名或组名,其中包含空格(当然,这并不能防止将来添加此类名称)。我想知道您的 POSIX 系统实际上是如何处理这些名称的。如果它们以某种方式自动翻译它们,我不会感到惊讶。即便如此,您的id -G
解决方案仍然有效。
如果我有/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