Na czym polega problem z następującym kodem jako "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;
Ilekroć próbuję wykonać powyższy skrypt, pojawia się następujący błąd:
Nie można wywołać metody "encpass" na niezdefiniowanej wartości w /var/www/chpwd.pl wiersz 5
Potwierdzam plik /etc/passwd
nie jest pustym ani dowiązaniem symbolicznym, ma własność
rw-r - r-- root: root 1022 passwd
Użytkownik johndoe
istnieją w systemie.
Proszę pomóż. Dzięki.
Dane wyjściowe śledzenia (częściowe):
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;
AKTUALIZACJA:
Powyższy skrypt działa idealnie na mojej lokalnej maszynie, nie na maszynie serwerowej.
Odpowiedzi:
0 dla odpowiedzi № 1Powinieneś użyć
use strict;
use warnings;
Zawsze. Zrób to i możesz odkryć błędy, których wcześniej nie zauważyłeś.
Wygląda na to, że $pw
jest niezainicjowany, co oznaczałoby, że new
deklaracja nie powiodła się. Jednak wydaje się mało prawdopodobne, aby tak było, ponieważ powinieneś mieć /etc/passwd
plik, a jako root powinieneś być w stanie go przeczytać. Możesz to łatwo sprawdzić za pomocą:
die "Failed to read PW" unless (defined $pw);
Czy "johndoe" jest istniejącym użytkownikiem? Jeśli nie, podejrzewam metodę passwd
zawiedzie.
ETA: Ponieważ ślad pokazuje błąd z blokowaniem, być może plik jest używany przez inny proces, a zatem nie można go zablokować / odblokować?
1 dla odpowiedzi nr 2
Oczywiście, konstruktor wraca undef
zamiast nowo utworzonego obiektu. Oto fragment źródła konstruktora (w języku angielskim) 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;
Możesz sam to sprawdzić i zobaczyć, w której gałęzi się znajduje.