【问题标题】:Perl error: can't call method "encpass" on an undefined value - WHY?Perl 错误:不能在未定义的值上调用方法“encpass” - 为什么?
【发布时间】:2011-09-14 12:29:56
【问题描述】:

以下代码作为“root”用户有什么问题:

chpwd.pl

#!/usr/bin/perl
use Unix::PasswdFile;

use strict;
use warnings;

$pw = new Unix::PasswdFile "/etc/passwd";
$pw->passwd("johndoe", $pw->encpass("newpass"));
$pw->commit();
undef $pw;

每当我尝试执行上述脚本时,都会收到以下错误:

无法在 /var/www/chpwd.pl 第 5 行的未定义值上调用方法“encpass”

我确认文件/etc/passwd不是空的或符号链接,它拥有

rw-r--r-- root:root 1022 密码

用户johndoe确实存在于系统中。

请帮忙。谢谢。

跟踪输出(部分):

Unix::ConfigFile::mode(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:152):
152:        my $this = shift;
Unix::ConfigFile::mode(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:153):
153:        return $this->{mode} unless @_;
Unix::ConfigFile::new(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:64):
64:     $this->lock() or return undef;
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:165):
165:        my $this = shift;
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:167):
167:        return 1 if ($this->locking eq "none");
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:127):
127:        my $this = shift;
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:129):
129:        return $this->{locking} unless @_;
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:168):
168:        return 0 if $this->{locked};
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:169):
169:        if ($this->locking eq "flock") {
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:127):
127:        my $this = shift;
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:129):
129:        return $this->{locking} unless @_;
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:127):
127:        my $this = shift;
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:129):
129:        return $this->{locking} unless @_;
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:174):
174:        my $fh = new IO::File $this->lockfile, O_CREAT|O_EXCL|O_RDWR;
Unix::ConfigFile::lockfile(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:145):
145:        my $this = shift;
Unix::ConfigFile::lockfile(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:146):
146:        @_ ? $this->{lockfile} = shift : $this->{lockfile};
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:35):
35:     my $type = shift;
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:36):
36:     my $class = ref($type) || $type || "IO::File";
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:37):
37:     @_ >= 0 && @_ <= 3
38:     or croak "usage: new $class [FILENAME [,MODE [,PERMS]]]";
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:39):
39:     my $fh = $class->SUPER::new();
IO::Handle::new(/usr/lib/perl/5.10/IO/Handle.pm:54):
54:     my $class = ref($_[0]) || $_[0] || "IO::Handle";
IO::Handle::new(/usr/lib/perl/5.10/IO/Handle.pm:55):
55:     @_ == 1 or croak "usage: new $class";
IO::Handle::new(/usr/lib/perl/5.10/IO/Handle.pm:56):
56:     my $io = gensym;
Symbol::gensym(/usr/share/perl/5.10/Symbol.pm:23):
23:     my $name = "GEN" . $genseq++;
Symbol::gensym(/usr/share/perl/5.10/Symbol.pm:24):
24:     my $ref = \*{$genpkg . $name};
Symbol::gensym(/usr/share/perl/5.10/Symbol.pm:24):
24:     my $ref = \*{$genpkg . $name};
Symbol::gensym(/usr/share/perl/5.10/Symbol.pm:25):
25:     delete $$genpkg{$name};
Symbol::gensym(/usr/share/perl/5.10/Symbol.pm:26):
26:     $ref;
IO::Handle::new(/usr/lib/perl/5.10/IO/Handle.pm:57):
57:     bless $io, $class;
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:40):
40:     if (@_) {
IO::File::new(/usr/lib/perl/5.10/IO/File.pm:41):
41:     $fh->open(@_)
42:         or return undef;
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:52):
52:     @_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])';
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:53):
53:     my ($fh, $file) = @_;
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:54):
54:     if (@_ > 2) {
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:55):
55:     my ($mode, $perms) = @_[2, 3];
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:56):
56:     if ($mode =~ /^\d+$/) {
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:57):
57:         defined $perms or $perms = 0666;
IO::File::open(/usr/lib/perl/5.10/IO/File.pm:58):
58:         return sysopen($fh, $file, $mode, $perms);
Unix::ConfigFile::lock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:175):
175:        return 0 unless defined($fh);
Unix::ConfigFile::new(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:104):
104:        my $this = shift;
Unix::ConfigFile::new(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:106):
106:        $this->unlock() or croak "Can't unlock file: $!";
Unix::ConfigFile::unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:184):
184:        my $this = shift;
Unix::ConfigFile::unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:193):
193:        return 1 if ($this->locking eq "none");
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:127):
127:        my $this = shift;
Unix::ConfigFile::locking(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:129):
129:        return $this->{locking} unless @_;
Unix::ConfigFile::unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:194):
194:        return 0 unless $this->{locked};
Carp::croak(/usr/share/perl/5.10/Carp.pm:44):
44: sub croak   { die  shortmess @_ }
Carp::shortmess(/usr/share/perl/5.10/Carp.pm:29):
29: sub shortmess { goto &shortmess_jmp }
Carp::shortmess_real(/usr/share/perl/5.10/Carp/Heavy.pm:51):
51:     local @CARP_NOT = caller();
Carp::shortmess_real(/usr/share/perl/5.10/Carp/Heavy.pm:52):
52:     shortmess_heavy(@_);
Carp::shortmess_heavy(/usr/share/perl/5.10/Carp/Heavy.pm:241):
241:      return longmess_heavy(@_) if $Verbose;

更新:

上面的脚本在我的本地机器上运行完美,而不是在服务器机器上。

【问题讨论】:

  • 你用什么用户执行脚本?

标签: perl perl-module


【解决方案1】:

显然,构造函数返回undef,而不是新创建的对象。下面是构造函数的一段源码(在ConfigFile.pm):

# Get a filehandle
my $fh = new IO::File $this->filename, $this->mode;
return undef unless defined($fh);
$this->fh($fh);

# Do file locking - this must happen before read is called or we could
# end up with stale data in memory
if ($this->mode eq "r") {
  $this->lock("shared") or return undef;
}
else {
  $this->lock() or return undef;
}

# Initialize object structure from the file
if (exists $opt{readopts}) {
  $this->read($this->fh, $opt{readopts}) or return undef;
}
else {
  $this->read($this->fh) or return undef;
}
return $this;

你可以自己追踪它,看看它在哪个分支。

【讨论】:

  • 这与我对 Perl 的理解相去甚远。我从 CPAN 中找到了上述代码并尝试运行,但遇到了该错误。你是说我应该在某处添加/修改 ConfigFile.pm?
  • 是的,你可以在ConfigFile.pm(这是构造函数所在的地方)打印跟踪消息,看看哪个条件失败了。
  • 确实没有必要编辑 ConfigFile.pm。使用 Perl 调试器跟踪程序的执行可能更容易——确保单步执行对 Unix::PasswdFile->new 的调用。
  • @davorg 可以更具体吗?我是 Perl 的初学者,对调试 perl 脚本一无所知。
  • @davorg & @Blagovest 请查看为 Unix::PasswdFile 添加的跟踪输出,看起来它在 ConfigFile.pm Unix::ConfigFile::unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:194): 194: return 0 unless $this-&gt;{locked}; 中的行失败了
【解决方案2】:

你应该使用

use strict;
use warnings;

总是。这样做,您可能会发现以前没有注意到的错误。

似乎$pw 未初始化,这意味着new 声明失败。但是,它似乎不太可能这样做,因为您应该有一个 /etc/passwd 文件,并且作为 root 您应该能够读取它。您可以通过以下方式轻松检查:

die "Failed to read PW" unless (defined $pw);

“johndoe”是现有用户吗?如果没有,我怀疑passwd 方法会失败。

ETA:由于跟踪显示锁定错误,可能文件正被另一个进程使用,因此无法锁定/解锁?

【讨论】:

  • 你是对的,我得到了“死”的信息。我该怎么办?由于 Unix::PasswdFile 是库文件,我不确定应该如何进一步移动。
  • 我在问题中添加了跟踪输出,请看。我不是流程失败的地方,但异常发生在 ConfigFile.pm Unix::ConfigFile::unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:194): 194: return 0 unless $this-&gt;{locked}; 中的这一行
  • @Rakesh 0 已定义,因此它不会触发 unless (defined $pw)。这不符合您关于未定义值的错误,也不符合 die 语句。
  • @Rakesh 嗯,好吧,没关系。您的问题在于 new 语句。您是否尝试过添加use strict; use warnings;?如果没有,请这样做。检查/etc/passwd,看看有没有问题。如果它为空或不存在或者是符号链接,我想这可能会导致一些问题。
  • @TLP 我确实添加了use strict; use warnings;,但徒劳无功。查看/etc/passwd 的所有权,它读取rw-r-r root:root,这意味着它应该能够被所有人读取并且只能被root 写入。顺便说一句,我正在由root 用户运行此脚本。相同的脚本作为root 用户在本地机器上运行完美。是否会有显式函数阻止 perl 读取此文件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 2012-08-24
  • 1970-01-01
  • 2015-08-01
  • 2011-04-15
  • 2016-12-22
  • 1970-01-01
相关资源
最近更新 更多