检查文件是否在 Perl 中处于打开状态

Check if the file is in a open state in Perl

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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