使用File :: Path创建目录,但未正确设置所有者和组

时间:2011-08-13 20:52:07

标签: perl perl-module

我正在尝试编写一个小的Perl脚本来创建目录结构。要创建目录,我使用标准模块File :: Path,如下所示:

make_path($directory,
    {
        owner   => 'apache',
        group   => 'apache',
        mode    => 0500
    }
);

执行脚本时,会根据需要创建目录,并按预期设置umask,但文件的所有者和组都是“root”。这是错误的,但错误在哪里?错误消息不会打印或由错误参数给出。

提前致谢,

斯特

3 个答案:

答案 0 :(得分:6)

我只是尝试了它并得到了与你相同的结果。我查看了文档:

perldoc File::Path

...而且没有提及'所有者'选项。但是,搜索最新版本(2.08,AFAICT)文档,它就在那里。你能检查一下你系统上模块的版本吗?

perl -MFile::Path -e 'print $File::Path::VERSION'

如果你没有运行2.08,那可能就是问题所在。我现在正试图追踪该模块的更改日志,但遇到困难......

[稍后]

好的,所以这就是你想要做的事情:

#!/usr/bin/perl -w

use strict;

use File::Path qw( make_path );

my $directory = $ARGV[0];
my $owner = 33;

make_path( $directory, { mode => 0500 } );
chown 33, 33, $directory;

最后,最后一行是你要注意的那一行。使用该版本的File :: Path创建所有者时,无法设置所有者,但您可以更改它。我的例子中的33是我系统上www-data用户的UID;显然,您希望将33更改为更适合您系统的内容。此外,您需要确保您的脚本以能够执行此操作的权限运行。例如,如果您以低用户身份运行它,它将无法工作,但如果您以root身份运行它,则chown将起作用。你可能想在那里找到一些中间地带。

答案 1 :(得分:2)

我认为这是File::Path中的错误;它悄悄地忽略了它无法识别的键。

#!/usr/bin/perl

use strict;
use warnings;

use File::Path;

print "Using File::Path version $File::Path::VERSION with Perl $]\n";

my $tmpdir = "/tmp/file-path-test-$$";

print "Creating $tmpdir\n";
mkdir $tmpdir, 0777 or die "$tmpdir: $!\n";

my @result = File::Path::make_path
                ( "$tmpdir/new-dir",
                  { owner => 'kst',
                    mode => 0500,
                    nosuchkey => 'WTF?' } );

print "Created ( @result )\n";

(请注意,这假设您的系统上有一个名为“kst”的帐户;根据您的系统需要进行调整。)

当我使用Perl 5.010001使用File :: Path版本2.07_03在sudo下运行时,创建的目录由root拥有;当我做同样的事情,但使用File :: Path版本2.08_01和Perl 5.014000时,该目录由kst拥有。在任何一种情况下,都没有迹象表明无法识别的密钥(旧版本为ownernosuchkey,新版本只有nosuchkey)。

perldoc File::Path没有解决这个问题(除非我错过了),并且我没有看到任何干净的方法让程序确定它使用的File::Path是否可以处理更新的选项。 (您可以检查$File::Path:VERSION,但这需要知道何时实施了新选项。)

我刚刚reported this

答案 2 :(得分:0)

只有当您想要创建单个目录而不是更多嵌套目录时,Kenny的回答才有用 - 例如。 make_path ( 'foo/bar' ); 在第二种情况下,只会更改最后一个目录的所有者/组。

更正确的方法可能是这样的:

#!/usr/bin/perl -w

use strict;

use File::Path qw( make_path );
use File::Spec;

my $directory = $ARGV[0];
my $gid = getgrnam( "my_group" );
my $uid = getpwnam( "my_user" );

make_path( $directory, { mode => 0750 } );
my @directories = File::Spec->splitdir( $directory );
my @path;
foreach my $dir ( @directories ) {
    push( @path, $dir );
    chown $uid, $gid, File::Spec->catdir( @path );
}