我想将子程序测试写入日志文件,例如:
my ($logfile, $logpath);
$logpath = '/usr/bin';
$logfile = "$logpath/log.txt";
open (LOG,">>","$logfile") || die ("Error : can't open log file");
sub test
{
print "Hi\n";
my $date = `date`;
}
sub logFunc
{
print LOG "Writing log files\n";
print LOG test(); # we cannot do like this :)
}
logFunc();
假设有 15 个以上的子例程。要将每个子例程中的命令写入日志文件,我必须编写:
print LOG "[Command]\n";
效果很好,但脚本长度很大。使用普通子程序,有什么办法可以实现这一点吗?
您的代码存在几个问题。
您确定拥有(并且想要)对
/usr/bin/
的写入权限吗?您永远不会调用您的
log()
或 test()
子例程。没有人会自动呼叫他们中的任何一个。名称
log
与内置 log
函数冲突。因此,您要么必须使用前缀与符号 &log()
(这很丑陋)来调用它,要么重命名它。您的
test()
子仅具有隐式返回值。而是明确返回 $date
的值。您正在使用已弃用的 2 参数版本的
open
,使用裸字全局文件句柄。请使用带有词法文件句柄的 3-arg 版本:open my $log_fh, '>>', $logfile
。一些提示:
use strict;
和 use warnings;
。 use autodie;
。如果您无法打开文件或无法写入打开的文件,这将自动终止您的程序。test
子例程返回一些内容以写入日志。或者,仅创建一个写入日志的日志子例程,并让您的测试子例程调用它。我在这里反转你的子程序调用。我创建了一个
write_to_log
子例程来处理我的子例程调用。我的 write_to_log
添加日期/时间戳并写入该日期/时间戳和我的消息。我的各种子程序现在只需为我调用 write_to_log
。
注意我的所有子例程都返回某种值。
say
命令(以及 print
)在成功时返回非零值,在失败时返回 0
。我可以用它来测试我对子例程的调用是否有效。
use strict;
use warnings;
use autodie;
use features qw(say); #Allows you to use `say` instead of `print:
my $log_file = "/usr/bin/log.txt"; #You have write permission to this directory?
open my $log_fh, ">", $log_file;
my test ( $log_fh ) or die qq(Can't write to the log); #Pass the file handle to log
my test2 ( $log_fh ) or die qq(Can't write to the log);
close $log_fh;
sub test {
return write_to_log ( $log_fh, "Hello World!" );
}
sub test2 {
return write_to_log ( $log_fh, "Goodbye World!" );
}
sub write_to_log {
my $file_handle = shift;
my $message = shift;
use Time::Piece;
my $time = localtime->cdate;
return say {$file_handle} "$time: $message";
}
这里有一个网页,其中列出了学习现代 Perl 的好书以及在这些书中要查找的内容。如果您开始学习 Perl,请使用其中一本书籍。
对于那些无法使用模块并需要快速日志记录功能的人,因为我们通常没有时间或无法安装模块,尤其是在遗留应用程序中。
仅使用基本 Perl 命令的简单函数:
#Print based on loglevel
sub log {
#Loglevels hashmap - do not modify
my %LOG_LEVELS=( "CRITICAL"=>-1, "ERROR"=>1, "WARNING" =>2 , "INFO"=> 3, "DEBUG"=> 4);
#get current log level in the script and desired loglevel for this message
my $desiredlevel=uc($_[0]);
my $currentlevel=uc($loglevel);
#If invalid level assume its a debug message
if ($LOG_LEVELS{$desiredlevel}+0 == 0){
$desiredlevel="DEBUG";
}
printf("[$desiredlevel] $_[1]\n") if $LOG_LEVELS{$currentlevel}+0 >= $LOG_LEVELS{$desiredlevel}+0;
}
使用此功能:
在本例中设置日志级别,我将 cmd arg 传递给它
my $loglevel="INFO"; #default
#parse command-line vars
foreach $arg (@ARGV){
chomp($arg);
($key,$val) = split(/=/,$arg,2);
if ($key eq "url"){ $url = $val; }
if ($key eq "loglevel"){ $loglevel = $val; }
}
然后使用级别和消息调用函数
&log("INFO", "Calling script to generate result");
$result=`blahblah`;
if (index($result,"OK") == -1) {
&log("ERROR", "Generate role FAILED with status $result");
}
else
{
&log("DEBUG", "Sucessfully created ".$result);
}
它不能处理所有情况,但您可以轻松地在 LOG_LEVELS 数组中添加具有更高/更低数字的更多级别。
需要添加更多验证,但已经处理不同的情况:INFO info inFO 都是有效的。