什么时候需要在Perl中“END{close STDOUT}”?

什么时候需要在Perl中“END{close STDOUT}”?,perl,Perl,在中,我在END块中发现了STDOUT的显式关闭 END { close STDOUT } 我知道结局和结局,但我不明白为什么需要它 开始搜索时,可在以下位置找到: 例如,您可以使用它来 确保您的筛选程序已成功运行 在不填充的情况下完成输出 磁盘: 反正我也不明白( 有人能解释一下吗(可能有一些代码示例): 为什么以及何时需要它 我的perl过滤器如何以及在什么情况下填充磁盘等等 当事情在没有它的情况下出错时 等等 许多系统都实现“乐观”文件操作。我的意思是,例如,在数据实际写入文件之前,或

在中,我在END块中发现了STDOUT的显式关闭

END { close STDOUT }
我知道结局和结局,但我不明白为什么需要它

开始搜索时,可在以下位置找到:

例如,您可以使用它来 确保您的筛选程序已成功运行 在不填充的情况下完成输出 磁盘:

反正我也不明白(

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

  • 为什么以及何时需要它
  • 我的perl过滤器如何以及在什么情况下填充磁盘等等
  • 当事情在没有它的情况下出错时
  • 等等

许多系统都实现“乐观”文件操作。我的意思是,例如,在数据实际写入文件之前,或者甚至在磁盘上保留足够的空间以便写入成功之前,调用应该向文件中添加一些数据的可以成功返回

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

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

如果
STDOUT
filehandle连接到文件,则所有这些都可能发生在该文件句柄上,例如,如果您的脚本以以下方式运行:

perl script.pl > output.txt
如果要输出的数据很重要,并且需要知道是否所有数据都正确写入,则可以使用引用的语句来检测问题。例如,在第二个代码段中,如果
close
报告错误,则脚本显式调用
die
;在
使用autodie
下运行,这是自动的如果
close
失败,则ally调用
die


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

我认为Mat错了

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

现在,这在退出时仍然会发生,但是调用
close
可以处理刷新缓冲区时遇到的任何错误


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

@jm666:tchrist样板文件的一部分(这是从哪里来的)是否使用autodie;来处理error@jm666,我刚刚尝试用perl编写一个完整的磁盘。Bash在关闭文件时不会给出错误,并且返回零错误代码(成功),而对文件的写入还没有完成!所以shell不是我在这里所依赖的。添加
END
子句使perl本身发出正确的警告,并通过
die
ing宣布失败。@jm666:
close STDOUT
的目的不是关闭流,这在perl进程退出时无论如何都会发生关键是,如果
close
失败,则进程将退出,并显示一个非零状态代码,表示失败。这是由
使用autodie
带来的,或者在您的另一个示例中由
close STDOUT | | die
完成的。并非每个脚本都需要它。许多脚本只是将随机信息消息写入STDOUT,而不是care是否连接到任何东西。仅当写入该文件描述符的数据很重要时才需要它,这当然不总是如此。我保护
END{close STDOUT}
的唯一时间是当它连接到管道时。即使如此,有时我也会使用
$SIG{pipe}=sub{exit 0}
通常情况下,过滤程序无法检测到标准输出的故障是一个缺陷。我有时会延迟atexit处理程序的安装,如
eval qq{END{close STDOUT}
或使用
END{eval{close STDOUT}保护它不受
autodie
的影响
。但是当你让STDOUT进入管道时,根据
打开(STDOUT,“| less”)
,你最好等待它,否则你的父母会在孩子之前退出,把输出搞砸。默认情况下,假设你需要它。是的-明白。我的意思是,将数据保存到内核的I/O缓冲区(它们将保存在下一次“同步”中)(由更新守护进程或启动(在OS X上))
perl script.pl > output.txt