PHP LinuxWindowsmacOS

PHP: fwrite возвращает false, хотя каталог существует

  • Обновлено
  • Чтение ≈ 4 минуты

Краткий ответ

Почему fwrite возвращает false или записывает меньше байтов при существующем каталоге: права файла и процесса, режим fopen, свободные блоки, квота и ошибки файловой системы.

В этой статье
  1. Когда возникает ошибка
  2. Причины и признаки
  3. Пошаговая диагностика и устранение
  4. Проверяемый пример и команды
  5. Проверка исправления и действия при неудаче

#Когда возникает ошибка

Наличие каталога не гарантирует, что PHP может записать файл. fwrite() возвращает количество записанных байтов или false, а иногда число меньше размера данных. Причина может быть в режиме открытия потока, правах владельца PHP-FPM, заполненном разделе или квоте, недоступном сетевом хранилище, read-only-разделе и системных ограничениях.

#Причины и признаки

Возможная причинаКак узнатьЧто делать
Режим fopen или файл недоступенФайл открыт только для чтения, существует с чужими правами либо open_basedir ограничивает путь.Проверка fopen и предупреждения журнала показывают Permission denied, режим r или запрет доступа.Проверьте реальный путь, режим открытия и учётную запись PHP.
Нет места либо превышена квотаКаталог существует и может быть доступен для чтения, но запись не проходит.В журнале No space left on device / Disk quota exceeded; df -h показывает загрузку конкретного раздела.Освободите место штатно после сохранения важных данных или запросите квоту у администратора.
Короткая запись в потокНа сетевых или нестандартных потоках fwrite может записать меньше переданного объёма.Возвращается целое меньше strlen($data) или 0, даже без false.Проверяйте возвращённое число и останавливайтесь при отсутствии прогресса.

#Пошаговая диагностика и устранение

  1. Не запускайте повторную запись в важный файлЕсли ошибка возникла при записи счёта, выгрузки или архива, сделайте копию существующих данных и остановите автоматические повторные попытки. Повторное открытие в режиме w обнуляет существующий файл. Для диагностики выберите отдельную тестовую директорию и короткую строку без персональных данных.
  2. Проверьте, что сбой действительно на fwriteОткройте закрытый PHP-журнал и найдите предупреждение рядом с fopen()/fwrite(). В редакторе посмотрите переменные $handle и $path: не перепутан ли режим r с ab, открыт ли поток успешно, не было ли уже fclose(). При fopen() === false не вызывайте fwrite вообще — сначала устраните ошибку открытия.
  3. Получите абсолютный путь и пользователя веб-процессаВ тестовой копии логируйте __DIR__, разрешённый целевой путь и результат is_writable() для существующего файла и каталога, но не выводите их посетителю. Помните: php из терминала выполняется под вашим пользователем, а PHP-FPM сайта — часто под другим. Если в CLI запись проходит, а на сайте нет, попросите администратора проверить пользователя пула и доступные каталоги.
  4. Проверьте права и ограничения без опасной смены chmodВ терминале Linux используйте ls -ld /реальный/каталог и ls -l /реальный/каталог/файл, заменив путь, чтобы увидеть владельца и режим. Проверьте права на каждый родительский каталог; для записи нужен доступ к файлу и соответствующие разрешения для создания/замены. Не применяйте chmod 777 и не меняйте владельца всего сайта рекурсивно. На Windows проверьте права учётной записи веб-сервера и запрет записи в защищённые каталоги.
  5. Проверьте место и квоту именно целевого разделаНа Linux выполните df -h /реальный/каталог и при необходимости df -i /реальный/каталог. Даже если корневой диск свободен, отдельная точка монтирования может быть заполнена; квота пользователя также может ограничивать запись. Не удаляйте произвольные файлы и журналы: выясните, кто владелец данных, и согласуйте освобождение места.
  6. Изолируйте ошибку тестовой записьюСоздайте отдельный PHP-тест с путём к заранее созданной временной папке, доступной приложению. Откройте новый тестовый файл через fopen($path, "xb"), проверьте результат, затем сравните число записанных байтов с strlen($payload). Если вернулось false или 0 для непустой строки, прекратите повторять вызовы; зафиксируйте предупреждение и попросите администратора проверить файловую систему.
  7. Проверьте результат и аккуратно отмените диагностикуУбедитесь, что тестовый файл содержит ровно ожидаемые байты и fclose() завершился. Удалите только созданный вами тестовый файл через интерфейс файлового менеджера после проверки его имени. Если проблема решена сменой владельца или путей, восстановите исходные разрешения, если они были временными; затем повторите штатную операцию на копии данных до выхода в рабочий режим.

#Проверяемый пример и команды

PHP
Скопируйте в НОВЫЙ файл в отдельной тестовой папке с разрешённой записью и запустите один раз. Режим xb не обнулит существующий файл; при повторном запуске нужно выбрать новое имя. fflush проверяется, но надёжная долговременная запись на накопитель зависит и от системы.
<?php
$path = __DIR__ . '/write-check.tmp'; // используйте только отдельную тестовую папку
$payload = 'WHELP write test' . PHP_EOL;
$fh = fopen($path, 'xb'); // создать новый файл, не перезаписывать существующий
if ($fh === false) {
    throw new RuntimeException('Не удалось создать тестовый файл');
}
$written = fwrite($fh, $payload);
$flushed = fflush($fh);
fclose($fh);
if ($written === false || $written !== strlen($payload) || !$flushed) {
    throw new RuntimeException('Запись неполная или не завершена');
}
echo 'Записано байтов: ' . $written . PHP_EOL;
Linux · Терминал (Bash)Команда
Терминал Linux, подставьте существующий целевой каталог. Команды только читают состояние блока и числа файлов; не требуют sudo.
df -h /real/path
df -i /real/path
Linux · Терминал (Bash)Команда
Терминал Linux. Вторая команда применяется лишь если тестовый файл существует. Вывод показывает права и владельца.
ls -ld /real/path
ls -l /real/path/write-check.tmp

#Проверка исправления и действия при неудаче

Успех — fwrite возвращает количество байтов, равное длине непустой строки, тестовый файл содержит правильный текст, а приложение ведёт журнал об ошибках записи. Если сохраняется только частичная запись, проверяйте тип потока, сетевой ресурс, квоты и ограничения файловой системы.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.