я имею
$bytesCount = file_put_contents( "somefile.log", "some text\n", FILE_APPEND | LOCK_EX );
Что произойдет, если другой процесс пишет ** на somefile.log
?
Есть ли file_put_contents
терпит неудачу с ошибкой во время выполнения?
Если не с $bytesCount === false
Или он приостанавливает выполнение сценария до тех пор, пока файл не будет разблокирован, а затем выполняет операцию записи?
(**) или, в более общем случае, другой процесс имеет эксклюзивную блокировку файла
*nix
платформа с php 5.6 ]
когда file_put_contents
попытки записи в заблокированный файл ждет, пока файл не будет разблокирован, затем выполняет запись и возвращает количество записанных байтов.
Доказательство:
Я написал простой тест с двумя сценариями:
первый сценарий записывает файл размером 100 МБ (на медленном диске с 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
строка 100 МБ, во втором скрипте $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
$
10 МБ + 10 байт было написано
$ tail -c 20 /Volumes/myHD/somefile.txt
0123456789MORE-DATA
$
Второй скрипт фактически добавил строку в конец файла
Должно быть очевидно, что это следует использовать, только если вы делаете одну запись, если вы пишете несколько раз в один и тот же файл, вы должны обрабатывать его самостоятельно с помощью fopen и fwrite, fclose, когда вы закончите писать.
Тест ниже:
file_put_contents () для 1 000 000 записей — в среднем 3 теста:
реальный 0m3.932s
пользователь 0m2.487s
sys 0m1.437s
fopen () fwrite () для 1 000 000 операций записи, fclose () — среднее из трех тестов:
реальный 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);