2011-06-14 90 views
1

什麼是用下面的代碼爲「根」用戶的問題:Perl錯誤:無法在未定義的值上調用方法「encpass」 - 爲什麼?

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; 

每當我試着執行上面的腳本,我得到以下錯誤:

Can't call method "encpass" on an undefined value at /var/www/chpwd.pl line 5

我確認文件/etc/passwd不是空的或符號鏈接,它擁有

rw-r--r-- root:root 1022 passwd

用戶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; 

UPDATE:

以上腳本的運行完全在我的本地機器上沒有服務器的機器。

+0

你用什麼用戶來執行腳本? – 2011-06-14 08:32:40

+0

@Blagovest作爲root用戶 – 2011-06-14 08:34:02

回答

0

您應該使用

use strict; 
use warnings; 

始終。做到這一點,你可能會發現你以前沒有注意到的錯誤。

看起來$pw未初始化,這意味着new聲明失敗。但是,它似乎不太可能,因爲您應該有一個/etc/passwd文件,並且作爲root用戶應該可以讀取它。您可以通過以下方式輕鬆檢查:

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

「johndoe」是現有用戶嗎?如果不是,我懷疑方法passwd會失敗。

ETA:由於跟蹤顯示鎖定錯誤,可能該文件正在被另一個進程使用,因此無法鎖定/解鎖?

+0

你是對的,我得到了「die」消息。我該怎麼辦?因爲,Unix :: PasswdFile是庫文件,我不知道應該如何進一步移動。 – 2011-06-14 10:13:27

+0

我已經在問題中添加了跟蹤輸出,請參閱。我不是流程失敗的地方,但是在ConfigFile.pm的這一行發生異常'Unix :: ConfigFile :: unlock(/usr/local/share/perl/5.10.1/Unix/ConfigFile.pm:194 ): 194:\t return 0除非$ this - > {locked};' – 2011-06-14 10:37:58

+0

@Rakesh'0被定義,所以它不會觸發'除非(定義$ pw)'。這不符合你關於未定義值的錯誤,也不符合'die'聲明。 – TLP 2011-06-14 13:32:40

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; 

您可以跟蹤它自己,看看在哪個分支不言而喻。

+0

這遠不是我對Perl的理解。我從CPAN上找到了上面的代碼並試圖運行,但是面對那個錯誤。你是說我應該在某處添加/修改ConfigFile.pm? – 2011-06-14 08:52:55

+1

是的,您可以在'ConfigFile.pm'(這是構造函數所在的位置)打印跟蹤消息,並查看失敗的條件。 – 2011-06-14 08:54:53

+1

真的不需要編輯ConfigFile.pm。使用Perl調試器來跟蹤程序的執行可能更容易 - 確保進入對Unix :: PasswdFile-> new的調用。 – 2011-06-14 08:57:52

相關問題