我正在尝试从模块中的哈希获取键值:
Module.pm
...
my $logins_dump = "tmp/logins-output.txt";
system("cat /var/log/secure | grep -n -e 'Accepted password for' > $logins_dump");
open (my $fh, "<", $logins_dump) or die "Could not open file '$logins_dump': $!";
sub UserLogins {
my %user_logins;
while (my $array = <$fh>) {
if ($array =~ /Accepted\s+password\s+for\s+(\S+)/) {
$user_logins{$1}++;
}
}
return \%user_logins;
}
sub CheckUserLogins {
my $LoginCounter;
my $UsersToCheck = shift @_;
if (exists %{UserLogins()}{$UsersToCheck}){
$LoginCounter = %{UserLogins{$UsersToCheck}}; #How many logins?
}
else {
$LoginCounter = "0";
}
return \$LoginCounter;
}
Script.pl
$UserLoginCounter = Module::CheckUserLogins($UsersToPass);
我将用户名传递给脚本并检查用户名是否为哈希,如果是,我需要返回登录次数,我正在尝试使用$LoginCounter
。由于某种原因,脚本只返回0或undef。
答案 0 :(得分:2)
嗯,对于初学者 - 你有CheckUserLogins
而不是CheckLoginAttempts
。
假设这只是一个错字 - UserLogins
返回一个哈希引用 - 一个标量值。如果0
检查失败,您将获得exists
。
如果确实存在,那么你就是这样做的:
$LoginCounter = %{UserLogins{$UsersToCheck}};
哪个无效。您是否已启用strict
和warnings
?因为您正在尝试将哈希值分配给标量,这不会达到您想要的效果。
你可能意味着:
$LoginCounter = ${UserLogins()} -> {$UsersToCheck};
从UserLogins
取消引用该引用,然后查找一个键。
UserLogins
它会创建一个新的哈希,但你不要快退$fh
。
所以我建议:
use strict;
use warnings;
{
my %userlogins;
sub inituserlogins {
open( my $fh, "<", '/var/log/secure' )
or die "Could not open file: $!";
while ( my $array = <$fh> ) {
if ( $array =~ /Accepted\s+password\s+for\s+(\S+)/ ) {
$userlogins{$1}++;
}
}
close($fh);
}
sub CheckUserLogins {
my ($UsersToCheck) = @_;
inituserlogins() unless %userlogins;
return $userlogins{$UsersToCheck} ? $userlogins{$UsersToCheck} : 0;
}
}
答案 1 :(得分:1)
您不得在词汇标识符中使用大写字母,因为Perl会为包名称等全局标识符保留它们
其中一个主要问题是您正在使用
exists %{UserLogins()}{$UsersToCheck}
应该是
exists UserLogins()->{$UsersToCheck}
或
exists ${UserLogins()}{$UsersToCheck}
你有use strict
和use warnings
,你应该有吗?
另一个问题是,每次拨打UserLogins
时,您都会阅读整个文件。这意味着第二次和稍后调用CheckUserLogins
(调用UserLogins
)将找不到任何内容,因为已到达文件末尾
您应该调用您的suibroutine user_logins
并将其称为一次,将结果存储为标量变量。该程序显示了如何
use strict;
use warnings;
use v5.14; # For state variables
sub user_logins {
open my $fh, '<', '/var/log/secure' or die $!;
my %user_logins;
while ( <$fh> ) {
if ( /Accepted\s+password\s+for\s+(\S+)/ ) {
++$user_logins{$1};
}
}
\%user_logins;
}
sub check_user_logins {
my ($users_to_check) = @_;
state $user_logins = user_logins();
$user_logins->{$users_to_check} // 0;
}