【问题标题】:Check if the file is in a open state in Perl在 Perl 中检查文件是否处于打开状态
【发布时间】:2021-05-20 11:19:58
【问题描述】:

我有一个 24 X 7 运行的 Perl 守护进程,它正在运行类似这样的东西

my_program.pl > /logs/user/data.out

my_program.pl只有在应用程序出错时才会写入data.out文件,否则不会写入。

现在我是一个应用程序,它进行清理并检查文件是否在 /logs/user/ 下 2 天前它会删除文件并且在删除时没有任何错误。

但是这样做的结果是文件被删除并处于打开状态,这导致服务器上的磁盘空间问题。

现在我要做的是检查我的清理程序,如果文件已打开,请不要删除它,但我无法将其识别为清理应用程序,我只有文件名和路径。

我尝试了以下链接中给出的建议,但没有任何帮助。

How do you check if a file is open using Perl? How can I check if a filehandle is open in Perl?

您能否建议我们如何在 Perl 中处理这种情况

【问题讨论】:

  • 您的意思是要在输出文件上运行lsof
  • 我也厌倦了使用它,但我没有得到结果

标签: perl


【解决方案1】:

我认为与其重定向到文件,不如将消息发送到 syslogd(或其他)并让其处理所有细节,从而获得更好的结果。那些东西知道如何正确地清理和旋转文件。

【讨论】:

    【解决方案2】:

    问题不在 Perl 的控制范围内;您正在使用 shell 的重定向将 STDOUT 重定向到文件,因此从 Perl 的角度来看,写入将转到 STDOUT;它没有设置重定向。

    在您的 Perl 程序中,您可以询问 -t STDOUT 是否已将 STDOUT 重定向到文件或者它是否是终端。但这并不能真正捕捉到该文件是否已打开。

    一种可行的方法是测试lsof /logs/user/data.outlsof 是一个 shell 实用程序,而不是 Perl 函数,因此您需要使用反引号、qx 或类似名称来运行它。这将提供谁对该文件拥有声明的输出,包括 PID。因此,使用lsof,您可以确定文件是否已打开以及是谁打开的。如果打开了多个实体,您也会看到它(例如,尝试lsof /dev/null;很多实体都会打开它)。

    如果lsof 没有返回文件的输出,那是因为没有人打开它。

    但请记住,如果重定向是在脚本本身的外部设置的,那么通过硬编码该文件名来假设重定向永远不会改变是很脆弱的。根据用户与运行脚本的用户匹配的用户名进行 lsof 可能会更好,然后找到符合预期的文件。

    lsof -u [UID or USERNAME] 命令将仅列出特定用户打开的文件。您可以将其与 $< 结合起来针对运行脚本的用户运行:

    my $lsof_output = `lsof -u $< $path`;
    

    然后检查由同一 pid 打开的文件的输出:$$

    为了完整起见,我将提到 CPAN 上有一个名为 Unix::Lsof 的 Perl 模块,它为您处理通过 lsof 输出进行解析的细节。

    【讨论】:

    • 能否请您解释一下“根据用户与运行脚本的用户匹配的用户名,lsof 可能会更好,”我在 Perl 中不太擅长
    • lsof 不是 Perl 命令,它是一个 shell 实用程序。
    • @choroba 正确。我会确保在编辑中指出这一点。
    • 不过,我应该提一下,代码有一定程度的异味,需要知道脚本外的 shell 重定向目标是否仍然打开并可供编写。似乎是一个应该在不同层次上解决的问题。如果所有选项都是错误的选项,那么人们就必须质疑导致这种情况的路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 2015-11-28
    • 2011-03-13
    • 2020-03-02
    • 2012-06-04
    • 1970-01-01
    • 2012-06-23
    相关资源
    最近更新 更多