gpt4 book ai didi

perl - AnyEvent 文件写入加上 logrotate 导致意外的文件大小

转载 作者:行者123 更新时间:2023-12-01 00:51:30 24 4
gpt4 key购买 nike

我有一个脚本,可以使用 AnyEvent 频繁地写入文件。我编写了以下示例来说明我面临的问题。

#!/usr/bin/perl

use strict;
use warnings;

use AnyEvent;
use AnyEvent::Handle;

my $outputFile = 'out_test.log';
open my $out, ">>", $outputFile or die "Can't open output\n";

my $data = "test string"x50000 . "\n";

my $out_ready = AnyEvent->condvar;
my $out_hdl; $out_hdl = AnyEvent::Handle->new(
fh => $out,
on_error => sub {
my ($hdl, $fatal, $msg) = @_;
AE::log error => $msg;
$hdl->destroy;
$out_ready->send;
}
);

my $timer = AnyEvent->timer(
after => 0,
interval => 5,
cb => sub {
$out_hdl->push_write($data);
}
);

$out_ready->recv;

这很有效,但文件大小会在一段时间后变得巨大。我们使用 logrotate 解决此类问题,因此我创建了以下 logrotate 配置文件。
/path/to/out_test.log {
size 2M
copytruncate
rotate 4
}

这也很好用,只要上面的输出文件超过 2M,就会轮换到 out_test.log.1。但是,当out_test.log在轮换后立即写入时,文件大小与轮换后的日志文件相同。这种行为和我所经历的在这里解释: https://serverfault.com/a/221343

虽然我理解这个问题,但我不知道如何解决我提供的示例 Perl 代码中的问题。

我不必通过 logrotate 实现日志轮换,但它会是首选。如果在脚本中实现很简单,我可以这样做,但是如果我可以使上面的示例与 logrotate 一起运行就好了。任何帮助或意见表示赞赏。谢谢!

编辑

根据下面的答案,我能够按照 Marc Lehmann 的建议,使用提供的monkeypatch ikegami 以及利用 native perl I/O 来解决问题。我的示例代码看起来像这样并且运行良好。此外,这消除了 logrotate 中对 copytruncate 指令的要求。
#!/usr/bin/perl

use strict;
use warnings;

use AnyEvent;
use AnyEvent::Handle;

my $outputFile = 'out_test.log';
open my $out, ">>", $outputFile or die "Can't open output\n";

my $data = "test string"x50000 . "\n";

my $cv = AnyEvent::condvar();
my $timer = AnyEvent->timer(
after => 0,
interval => 5,
cb => sub {
open my $out, ">>", $outputFile or die "Can't open output\n";
print $out $data;
close $out;
}
);

$cv->recv;

最佳答案

ikegamis 的回答非常具有误导性 - 您的代码包含一个错误,即使用 AnyEvent::Handle 进行文件 I/O,这是未记录且不受支持的行为。池上认为对非法文件句柄使用 AnyEvent::Handle 结果的“错误”。

虽然您可以尝试依赖未记录的行为和monkeypatch 的东西并希望它能够神奇地工作,但只要您将 AnyEvent::Handle 用于非流文件句柄,您可能会继续遇到问题,因此我会建议修复实际的错误。

如果您想进行基于事件的文件 I/O,那么您应该查看 AnyEvent::IO(并安装合适的后端,例如 IO::AIO)。否则,您应该使用普通的 perl I/O 函数(内置函数、IO::类等)来访问文件。

更新:AnyEvent::Handle 对文件不起作用的更深层原因是它最终没有意义,因为非阻塞 I/O 的概念不适用于文件,因此使用 AnyEvent::句柄只会增加开销。

关于perl - AnyEvent 文件写入加上 logrotate 导致意外的文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31080723/

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