gpt4 book ai didi

multithreading - 如何使用 Log4perl 在多线程 Perl 应用程序中轮换日志文件

转载 作者:行者123 更新时间:2023-12-03 00:47:20 25 4
gpt4 key购买 nike

下面是我尝试使用 log4perl 在多线程应用程序中旋转日志文件的示例代码。但除非它是多线程应用程序,否则它工作正常。日志不会旋转并且日志文件的大小会增加。谁能指导我哪里出错了?

use strict;
use warnings;
use Log::Log4perl;
use POSIX;
use threads;
use threads::shared;

my @InputFiles;

my $InputDirectory=$ARGV[0];
my $LogName=$ARGV[1];
opendir(DIR,$InputDirectory) or die "could not open the input directory";
@InputFiles=readdir(DIR);
close(DIR);
my $file;

#logger_configuration
my $log_conf ="
log4perl.rootLogger = DEBUG, LOG1

log4perl.appender.LOG1 = Log::Dispatch::FileRotate
log4perl.appender.LOG1.filename = $LogName
log4perl.appender.LOG1.mode = append
log4perl.appender.LOG1.autoflush = 1
log4perl.appender.LOG1.size = 10000
log4perl.appender.LOG1.max = 20
log4perl.appender.LOG1.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.LOG1.layout.ConversionPattern = \%d{yyyy-MM-dd HH:mm:ss}|\%P|\%m|\%n
";

#loading the configuration file
Log::Log4perl::init(\$log_conf);

#creating logger instance
my $logger = Log::Log4perl->get_logger();

my $thread_count=5;
my $file_total= scalar @InputFiles;
#print STDERR "$file_total\n";

#dividing total files among the no of given threads
my $div = $file_total/$thread_count;
$div = ceil($div);
my $start = 0;
my $end = $div;
my @threads;
for (my $count = 1; $count <=$thread_count ; $count++)
{
my $thread = threads->new(\&process,$start,$end);
push(@threads,$thread);
$start = $end;
$end = $end + $div;
if ($end > $file_total)
{
$end = $file_total;
}
}

foreach (@threads)
{
$_->join;
}

sub process
{
my $lstart = shift;
my $lend = shift;
my $id = threads->tid();
for (my $index = $lstart; $index < $lend; ++$index)
{
$logger->info($InputFiles[$index]);
}
}

最佳答案

好吧,从根本上来说,你的问题是这样的 - 你的“记录器”是在线程启动之前创建的。这意味着所有线程都将具有相同的文件句柄。

这本质上会给您带来问题,除非您有某种文件 IO 仲裁机制。将您的线程视为单独的程序,所有线程都尝试打开并写入同一个文件 - 您可以看到它可能会变得多么困惑。

我建议您需要做的是为记录器创建另一个线程,并通过诸如Thread::Queue之类的东西发送IO

use Thread::Queue;
my $log_q = Thread::Queue -> new();

sub logger_thread {
#init logger here

while ( my $log_item = $log_q -> dequeue() ) {
$logger -> info ( $log_item );
}
}

my $log_thread = threads -> create ( \&logger_thread );

然后将 $logger -> info (....) 替换为:

$log_q -> enqueue($message_to_log);

然后,一旦您加入了所有“进程”线程(例如您现在),请关闭记录器线程:

$log_q -> end();
$log_thread -> join();

这将导致每个线程对日志消息进行排队,一旦它们完成(并加入),您就关闭队列,以便记录器知道它已“完成” - 因此一旦队列为空并且可以退出,就会退出加入了。

多线程文件IO很乱,所以最好尽量避免。

关于multithreading - 如何使用 Log4perl 在多线程 Perl 应用程序中轮换日志文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27252437/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com