你什么时候需要在Perl中“结束{关闭STDOUT}”?

时间:2011-06-12 10:01:06

标签: perl

tchrists broilerplate我发现在END块中明确关闭了STDOUT。

END { close STDOUT }

我知道结束并关闭,但我想知道为什么需要它。

开始搜索时,可在以下perlfaq8中找到:

  

例如,您可以使用它来制作   确保你的过滤程序设法成功   完成输出而不填满   磁盘:

END {
    close(STDOUT) || die "stdout close failed: $!";
}

无论如何都不明白。 :(

有人可以解释(可能有一些代码示例):

  • 为何以及何时需要
  • 我的perl过滤器如何以及在什么情况下可以填满磁盘等等。
  • 没有它时出现问题......
  • 等??

2 个答案:

答案 0 :(得分:15)

许多系统实施“乐观”文件操作。这意味着调用例如print应该将一些数据添加到文件可以在数据实际写入文件之前成功返回,或者甚至在磁盘上保留足够的空间以便写入成功之前

在这些情况下,如果磁盘几乎已满,则所有打印都可以显示成功,但是当需要关闭文件并将其刷新到磁盘时,系统会意识到没有剩余空间。关闭文件时会出现错误。

此错误表示您认为保存的所有输出实际上可能根本没有保存(或部分保存)。如果这很重要,您的程序需要报告错误(或尝试纠正这种情况,或......)。

所有这些都可以在STDOUT文件句柄上发生,如果它连接到文件,例如如果您的脚本以:

运行
perl script.pl > output.txt

如果您输出的数据很重要,并且您需要知道所有数据是否确实写得正确,那么您可以使用您引用的语句来检测问题。例如,在第二个代码段中,如果die报告错误,则脚本会显式调用close; tchrist's boilerplateuse autodie下运行,如果die失败,则自动调用close

(这不能保证数据永久存储在磁盘上,其他因素也会在那里发挥作用,但这是一个很好的错误指示。即如果关闭失败,你知道你有问题。)

答案 1 :(得分:4)

我认为Mat错了。

Perl和系统都有缓冲区。 close导致 Perl的缓冲区被刷新到系统。它不一定会导致系统的缓冲区像Mat声称的那样写入磁盘。这就是fsync所做的。

现在,无论如何这都会在退出时发生,但是调用close可以让你有机会处理冲洗缓冲区时遇到的任何错误。

close做的另一件事是报告系统尝试将其缓冲区刷新到磁盘时的早期错误。