Perl 当程序意外停止时,如何自动删除使用File::Temp创建的文件?
我正在使用File::temp创建临时文件。程序正常退出时,我的临时文件会自动删除。当我的程序用ctrl+c停止时,我也希望发生同样的情况。事实并非如此 这里有一个简单的程序来演示我的问题 期望的行为是这样的。我怎样才能做到呢?我在Linux上Perl 当程序意外停止时,如何自动删除使用File::Temp创建的文件?,perl,Perl,我正在使用File::temp创建临时文件。程序正常退出时,我的临时文件会自动删除。当我的程序用ctrl+c停止时,我也希望发生同样的情况。事实并非如此 这里有一个简单的程序来演示我的问题 期望的行为是这样的。我怎样才能做到呢?我在Linux上 关闭文件句柄时不会删除临时文件(确定) 程序正常退出时删除临时文件(确定) 当程序以ctrl+c(不工作)退出时,临时文件被删除 编辑1 我测试了tempfile的行为。它似乎证实了Linux支持我正在寻找的东西(将文件标记为临时文件/取消链接打开
- 关闭文件句柄时不会删除临时文件(确定)
- 程序正常退出时删除临时文件(确定)
- 当程序以ctrl+c(不工作)退出时,临时文件被删除
# program will die because os deletes tmpfile after close
my $fh = tempfile;
close $fh;
stat $fh || die;
readline STDIN;
你真的需要文件名吗?如果没有,请使用
my $fh = tempfile();
您是否尝试将清理代码放入和结束块?要使控制键盘中断运行您的
结束块,您需要添加一个信号处理程序。比较以下各项的行为:
perl -E 'END{say "END"};<STDIN>'
我看了源代码。我甚至检查了最新的版本(在撰写本文时为0.22)。我想对File::Temp执行的操作是设计不允许的
创建对象时,将使用数组上下文创建临时文件,如下所示:
sub new {
...
# Open the file and retain file handle and file name
my ($fh, $path) = tempfile( @template, %args );
在数组上下文中创建tempfile意味着该文件永远不会自动取消链接(即使在支持它的平台上)。该文件被标记为延迟取消链接,这意味着当程序正常退出时,它将被删除
sub tempfile {
...
_deferred_unlink($fh, $path, 0) if $options{"UNLINK"};
# Return
if (wantarray()) {
if ($options{'OPEN'}) {
return ($fh, $path);
} else {
return (undef, $path);
}
} else {
# Unlink the file. It is up to unlink0 to decide what to do with
# this (whether to unlink now or to defer until later)
unlink0($fh, $path) or croak "Error unlinking file $path using unlink0";
# Return just the filehandle.
return $fh;
}
如果我想继续使用File::Temp,我需要设置一个信号处理程序,以便在程序中止时强制清理。如果需要考虑可移植性,我还应该设置一个sig处理程序,因为在某些平台上提供的只是延迟取消链接。很好的一点是,File::Temp创建了一个结束块,因此根本没有什么要做的:
use sigtrap qw(die normal-signals error-signals);
如果不考虑可移植性,并且平台支持自动文件清理,那么使用tempfile是可以的(在标量上下文中)
以下评论很好地解释了该设计背后的基本原理:
当我们打开文件时,我们必须指出临时性一般
我们只需要一个真正的临时文件,如果我们只返回
filehandle-如果用户想要他们可能不想要的文件名
一旦他们关闭该文件,该文件将立即消失(这可能很重要)
如果他们希望子进程使用该文件)
我在寻找类似的东西,我想我找到了一个相当好的小解决方案
从根本上讲,这并不是什么新鲜事,但可能比安装自己的END
块等更简单:
use sigtrap qw(die INT); # ensures DESTROY methods are run on Ctrl-C
my $temp = File::Temp->new(UNLINK => 1);
my $filename = $temp->filename;
# When $temp goes out of scope, the file will be
# deleted, and $filename will be invalid.
# Further, a Ctrl-C will cause $temp->DESTROY to be invoked,
# which will also delete the temp file.
@ikegami:他在LinuxI上,我并不绝对需要它,但它非常适合我当前的实现。稍后,我在临时文件中重定向了许多系统命令。使用文件名似乎比使用句柄更容易。是否确实在使用ctrl+c中止脚本时调用结束块?我做了一个快速测试,发现它不是:perl-e'END{print“END\n”}readline STDIN'我对一个尽可能透明的解决方案感兴趣,特别是我的操作系统支持自动清理临时文件。信号处理程序是最可移植的解决方案,它允许我不更改程序。
sub tempfile {
...
_deferred_unlink($fh, $path, 0) if $options{"UNLINK"};
# Return
if (wantarray()) {
if ($options{'OPEN'}) {
return ($fh, $path);
} else {
return (undef, $path);
}
} else {
# Unlink the file. It is up to unlink0 to decide what to do with
# this (whether to unlink now or to defer until later)
unlink0($fh, $path) or croak "Error unlinking file $path using unlink0";
# Return just the filehandle.
return $fh;
}
use sigtrap qw(die normal-signals error-signals);
use sigtrap qw(die INT); # ensures DESTROY methods are run on Ctrl-C
my $temp = File::Temp->new(UNLINK => 1);
my $filename = $temp->filename;
# When $temp goes out of scope, the file will be
# deleted, and $filename will be invalid.
# Further, a Ctrl-C will cause $temp->DESTROY to be invoked,
# which will also delete the temp file.