函数 file() 只读取 PHP 中的部分内容 7.4.27

Function file() reads only part of contents in PHP 7.4.27

我们的专用服务器(Windows 服务器)上有一个复杂的 Web 界面,它有很少的控制台进程,后台有 PHP 应用程序 运行 并进行各种数据处理。其中一些写入日志文件

@ file_put_contents( $logsFileNamePath, $fileContents, FILE_APPEND | LOCK_EX );

并且有一个控制台进程分析这些日志文件并寻找潜在的问题,它执行下面的代码(它可以在其他控制台进程写入日志文件的同时发生):

$logContent = file( $filePath );
$logContent = array_reverse( $logContent );
//... analyze the content

这多年来一直运行良好,直到最近 PHP 从 7.4.20 升级到 7.4.27,有时突然间分析日志文件的进程得到 内容来自某个行中间 截断 的日志文件。我怀疑新版本的 PHP 中存在一些内部错误,导致了这个……也许文件锁定不再有效?看起来像! 你们中有人最近遇到过类似的问题吗?你知道如何处理这个吗?谢谢

从 .20 到 .27 的补丁更新不应包括任何向后兼容性中断,因此您在这里的体验几乎可以肯定只是感觉。

LOCK_EX是咨询,不必推崇,file()不看。很明显,您的 reader 在作者完成之前正在阅读。如果你想让 reader 尊重锁,你也必须在 reader 中使用相同的锁定机制(即 fopen()flock()):

$fp = fopen('/path/to/file', 'r');
flock($fp, LOCK_EX); // this will block until the writer is done
while ($line = fgets($fp)) {
    // process $line
}
fclose($fp);

您也可以简单地更新编写器,以便它写入一个临时文件,然后在完成后重命名它:

file_put_contents('/path/to/file.temp', $contents);
rename('/path/to/file.temp', '/path/to/file');

然后更新您的 reader 以预期文件偶尔会丢失:

if (!file_exists('/path/to/file')) {
    throw new Exception('Nothing to do.');
}