file_put_contents将数据附加到另一个进程正在写入的文件上

时间:2016-12-16 11:09:03

标签: php unix php-5.6 file-locking

我有

$bytesCount = file_put_contents( "somefile.log", "some text\n", FILE_APPEND | LOCK_EX );

如果另一个流程在somefile.log上写**,会发生什么?

file_put_contents是否因运行时错误而失败?

如果失败了$bytesCount === false

或者它是否暂停脚本直到文件解锁然后执行写操作?

(**)或更一般地说,另一个进程对文件具有独占锁定

[我在*nix平台上使用php 5.6 ]

2 个答案:

答案 0 :(得分:1)

file_put_contents尝试在锁定文件上写入时等待文件解锁,然后执行写入并返回写入的字节数。

<强>证明:

我写了一个简单的双脚本测试:

第一个脚本写入一个100MB的文件(在USB2连接的慢速驱动器上);

第二个脚本将一个短字符串附加到同一个文件中。

两个脚本的核心是这四行:

echo Milliseconds() . ": Start writing file on file\n";
$bytesCount = file_put_contents( "/Volumes/myHD/somefile.txt", $buffer, FILE_APPEND | LOCK_EX );
var_export( $bytesCount );
echo "\n" . Milliseconds() . ": Done writing on file\n";

其中Milliseconds()是一个以毫秒为单位返回当前unix时间戳的函数。

在第一个脚本$buffer中是一个100MB字符串,在第二个脚本中$buffer = "MORE-DATA\n";

运行第一个脚本并快速启动第二个脚本会产生此输出:

脚本1:

$ php test1.php
1481892766645: Start writing file on file
100000000
1481892769680: Done writing on file
$

脚本2:

$ php test2.php
1481892766831: Start writing file on locked file
10
1481892769909: Done writing file on locked file
$

请注意:

  • 第二个脚本尝试在第一个脚本完成后写入186毫秒但在第二个脚本完成写入之前写入。所以第二个脚本实际上访问了一个锁定的文件。

  • 第二个脚本在第一个脚本之后229毫秒延迟写作

在两个脚本终止执行后检查结果:

$ stat -f%z /Volumes/myHD/somefile.txt 
100000010
$

写入10MB + 10个字节

$ tail -c 20 /Volumes/myHD/somefile.txt
0123456789MORE-DATA 
$

第二个脚本实际上在文件末尾添加了字符串

答案 1 :(得分:0)

很明显,只有在你进行一次写操作时才能使用它,如果你多次写入同一个文件,你应该用fopen和fwrite自己处理它,当你写完文件时fclose

以下基准:

file_put_contents(),用于1,000,000次写入 - 平均3个基准:

真正的0m3.932s 用户0m2.487s sys 0m1.437s

fopen()用于1,000,000次写入的fwrite(),fclose() - 平均3个基准:

真正的0m2.265s 用户0m1.819s sys 0m0.445s

对于使用ftp时的覆盖,这很有帮助:

/* create a stream context telling PHP to overwrite the file */ 
$options = array('ftp' => array('overwrite' => true)); 
$stream = stream_context_create($options);

http://php.net/manual/en/function.file-put-contents.php