将子程序写入日志文件

问题描述 投票:0回答:3

我想将子程序测试写入日志文件,例如:

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";

效果很好,但脚本长度很大。使用普通子程序,有什么办法可以实现这一点吗?

perl
3个回答
5
投票

您的代码存在几个问题。

  1. 您确定拥有(并且想要)对

    /usr/bin/
    的写入权限吗?

  2. 您永远不会调用您的

    log()
    test()
    子例程。没有人会自动呼叫他们中的任何一个。

  3. 名称

    log
    与内置
    log
    函数冲突。因此,您要么必须使用前缀与符号
    &log()
    (这很丑陋)来调用它,要么重命名它。

  4. 您的

    test()
    子仅具有隐式返回值。而是明确返回
    $date
    的值。

  5. 您正在使用已弃用的 2 参数版本的

    open
    ,使用裸字全局文件句柄。请使用带有词法文件句柄的 3-arg 版本:
    open my $log_fh, '>>', $logfile


4
投票

一些提示:

  • 始终在脚本顶部添加
    use strict;
    use warnings;
  • 由于您正在处理读写文件,因此还应该添加
    use autodie;
    。如果您无法打开文件或无法写入打开的文件,这将自动终止您的程序。
  • 当 Perl 无需调用操作系统命令就可以完全执行您想要的操作时,请不要使用操作系统命令。
  • 子例程通常接受参数并返回某种类型的值。在您的情况下,让您的
    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,请使用其中一本书籍。


-1
投票

对于那些无法使用模块并需要快速日志记录功能的人,因为我们通常没有时间或无法安装模块,尤其是在遗留应用程序中。

仅使用基本 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 都是有效的。

© www.soinside.com 2019 - 2024. All rights reserved.