Devel::Peek::Dump的STDERR输出未写入日志文件问题咨询
问题根因
Devel::Peek的Dump()函数是C语言实现的,默认直接写入系统底层的文件描述符2(原生STDERR),不走Perl层面的IO层映射。你用open(STDERR, ">>文件")只重定向了Perl层的STDERR句柄,没有修改底层文件描述符的指向,因此Dump()的输出会写入原始STDERR(通常是Web服务的全局错误日志),不会进入你指定的日志文件。你之前的print STDERR是Perl层函数,走重定向后的句柄,所以能正常写入。
解决方案
方案1:直接指定Dump输出句柄(最简单,适配Devel::Peek 1.06及以上版本)
Dump()支持第三个参数传入输出句柄,直接指定为你重定向后的STDERR即可:
use Devel::Peek; print STDERR "name AFTER encoded: \n"; # 第二个参数是变量dump的递归深度,默认1即可,第三个参数指定输出到Perl层STDERR Dump($add_common->{name}, 1, \*STDERR);
方案2:捕获Dump输出后手动写入日志
如果你的Devel::Peek版本较低不支持指定输出句柄,可以用Capture::Tiny捕获C层面的STDERR输出,再写入你的日志:
use Devel::Peek; use Capture::Tiny qw(capture_stderr); print STDERR "name AFTER encoded: \n"; # 捕获代码块内所有STDERR输出(包括C层面的输出) my $dump_content = capture_stderr { Dump($add_common->{name}); }; print STDERR $dump_content;
方案3:重定向底层文件描述符2
直接修改系统层面的文件描述符指向,让所有C/Perl层的STDERR输出都写入你的日志文件:
my $log_path = "/home/chambres/web/foo.org/public_html/cgi-bin/links/admin/stripe-booking.log"; open my $log_fh, ">>", $log_path or die $!; # 重定向Perl层STDERR open STDERR, ">&", $log_fh or die $!; # 重定向系统底层文件描述符2到日志文件 open STDERR, ">&=2" or die $!; # 关闭STDERR缓冲,避免输出遗漏 STDERR->autoflush(1);
完成上述重定向后,后续不管是Perl的print STDERR还是Dump()的输出都会正常写入指定日志。
内容的提问来源于stack exchange,提问作者Andrew Newby
相关产品推荐
相关产品推荐

