当程序意外停止时,如何自动删除使用File :: Temp创建的文件?

时间:2012-11-15 19:51:00

标签: perl

我正在使用File :: Temp创建临时文件。程序正常退出时,我的临时文件会自动删除。我期望当我的程序用ctrl + c停止时会发生同样的情况。它不是。

这是一个简单的程序,展示了我的问题。

理想的行为就是这个。我怎样才能实现它?我在Linux上。

    关闭文件句柄时,
  • 临时文件不会被删除(ok)
  • 当程序正常退出时,
  • 临时文件被删除(确定)
  • 当程序以ctrl + c(不工作)退出时,
  • 临时文件被删除

#!/usr/bin/perl -l

use warnings; use strict;
use File::Temp qw(tempfile tmpfile);

my $fh = File::Temp->new;
close $fh;

-f "$fh" || die "$fh does not exist"; 
print "hit enter and the file will be deleted";
print "hit ctrl+c and it won't";
print "verify with ls $fh after program exits";
readline STDIN;

编辑1

我测试了tempfile的行为。它似乎证实Linux支持我正在寻找的东西(将文件标记为临时/取消链接打开文件)。我似乎已经以某种方式理想化了File :: Temp。

# program will die because os deletes tmpfile after close
my $fh = tempfile;
close $fh;
stat $fh || die;
readline STDIN;

5 个答案:

答案 0 :(得分:2)

您是否尝试过清理代码和END阻止?

答案 1 :(得分:2)

要使Control_C键盘中断运行END块,您需要添加信号处理程序。比较以下行为:

perl -E 'END{say "END"};<STDIN>'

使用:

perl -E '$SIG{INT}=sub{die};END{say "END"};<STDIN>'

来自perlmod

An END code block is executed as late as possible, that is, after perl has
finished running the program and just before the interpreter is being exited,
even if it is exiting as a result of a die() function. (But not if it's
morphing into another program via exec, or being blown out of the water by a
signal--you have to trap that yourself (if you can).) 

答案 2 :(得分:1)

我查看了源代码。我甚至检查了最新版本(写作时为0.22)。我不想在设计中使用File :: Temp。

创建对象时,使用数组上下文创建临时文件:

sub new {
  ...
  # Open the file and retain file handle and file name
  my ($fh, $path) = tempfile( @template, %args );

在数组上下文中创建临时文件意味着文件永远不会自动取消链接(即使在支持它的平台上)。该文件被标记为延迟取消链接,这意味着它将在程序正常退出时被删除。

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创建了一个END块,因此根本不需要做什么:

use sigtrap qw(die normal-signals error-signals);

如果不考虑可移植性并且平台支持自动文件清理,那么使用tempfile就可以了(在标量上下文中)。

以下评论很好地解释了这种设计背后的基本原理:

  

我们必须在打开文件时指出临时性。 一般而言   我们只想要一个真正的临时文件,如果我们只返回   filehandle - 如果用户想要他们可能不想要的文件名   文件一关闭就会消失(这可能很重要   如果他们希望子进程使用该文件)

答案 3 :(得分:0)

你真的需要文件名吗?如果没有,请使用

my $fh = tempfile();

答案 4 :(得分:0)

我正在寻找类似的东西,我想我找到了一个相当不错的小解决方案。

它没有什么从根本上说是新的,但可能比安装自己的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.