SQLite LinuxDockerPHP

SQLite read-only после переноса на сервер — проверить каталог, владельца и WAL

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

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

После переноса SQLite-файла на Linux-сервер SELECT может работать, а INSERT/UPDATE — возвращать «attempt to write a readonly database» или SQLITE_READONLY_DIRECTORY. SQLite для записи часто нужны права не только на сам файл, но и на содержащий его каталог — для создания файлов журнала, -wal или -shm. Права нужно проверять от имени процесса PHP-FPM, Python либо службы, а не от собственного административного пользователя.

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

#Что происходит и когда возникает

После переноса SQLite-файла на Linux-сервер SELECT может работать, а INSERT/UPDATE — возвращать «attempt to write a readonly database» или SQLITE_READONLY_DIRECTORY. SQLite для записи часто нужны права не только на сам файл, но и на содержащий его каталог — для создания файлов журнала, -wal или -shm. Права нужно проверять от имени процесса PHP-FPM, Python либо службы, а не от собственного административного пользователя.

#Возможные причины: как различить

Возможная причинаКак узнатьЧто делать
Файл принадлежит другой учётной записиАрхив или копирование сохранили владельца, который не совпадает с пользователем службы.ls -l показывает владельца, не имеющего отношения к учётной записи веб-приложения.Дать минимально необходимые права назначенному пользователю после согласования.
Нет прав записи на каталогSQLite не удаётся создать журнал или файл -shm; ошибка может возникнуть при наличии прав на .db.ls -ld показывает каталог, недоступный на запись для службы.Исправить доступ к конкретному каталогу, а не ко всей системе.
Соединение открыто в режиме read-onlyСтрока подключения содержит mode=ro/immutable=1 либо приложение монтирует каталог только для чтения.Режим открытия прямо задан в коде или конфигурации.Исправить режим только для службы, которой разрешена запись.

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

  1. Не меняйте права до проверки назначения файлаПосле переноса сохраните полный путь к SQLite-файлу и сообщение об ошибке. Выясните, какой процесс должен записывать: PHP-FPM конкретного сайта, пользователь службы или отдельный контейнер. Если приложение только читает данные, read-only может быть намеренной защитой — в таком случае права менять не нужно.
  2. Проверьте режим открытия в приложенииНайдите строку подключения в настройках (не публикуя пароли): sqlite:///путь, URI file:...?...mode=ro, опции immutable и режим монтирования контейнера. Если явно указан mode=ro, запись невозможна независимо от chmod. Исправляйте конфигурацию только после подтверждения, что процесс действительно должен выполнять запись.
  3. Убедитесь, что используется нужный файлОткройте штатную SQL-консоль приложения и выполните PRAGMA database_list;. Если main указывает на тестовую копию или неожиданный относительный путь, исправьте путь в настройках и проверьте снова. Не создавайте второй файл под похожим именем.
  4. Проверьте файл и родительский каталог в LinuxНа сервере откройте терминал под учётной записью с разрешением на диагностику. Выполните ls -ld для каталога и ls -l для файла базы. Сравните владельца и группу с фактической учётной записью службы. Команды только показывают права и не требуют root, если каталоги доступны на просмотр. Если пути закрыты, обратитесь к администратору.
  5. Учтите WAL и прочие служебные файлыЕсли PRAGMA journal_mode возвращает wal, SQLite может создавать -wal и -shm в каталоге. Проверьте свободное место и права доступа к ним без ручного удаления. В режиме только чтения SQLite версии 3.22+ иногда может читать WAL при особых условиях, но это не означает возможность записывать.
  6. Исправьте доступ точечно через администратораПосле резервной копии администратор должен выделить отдельный каталог данных вне общедоступной директории, назначить необходимого владельца/группу и минимальные права на конкретный каталог и файл. Не используйте chmod 777 и chown -R на большом дереве. На хостинге или с SELinux/AppArmor отдельно проверьте применяемые политики и журнал отказов.
  7. Проверьте запись безопасным штатным действиемПосле изменения разрешений выполните предусмотренную приложением тестовую операцию в тестовой базе и проверьте результат чтением; для рабочей базы используйте только безопасное штатное действие, которое можно отменить. Если ошибка осталась, верните исходные права из зафиксированного состояния и обратитесь к администратору с путём, правами и ошибкой.

#Команды и проверочные примеры

Linux · Терминал (Bash)Команда
Примеры путей. Замените /srv/app/data и app.db реальными путями после проверки. Команды только читают метаданные.
ls -ld /srv/app/data
ls -l /srv/app/data/app.db
SQLКоманда
В SQL-клиенте конкретного приложения. Без знака равенства PRAGMA journal_mode только читает состояние.
PRAGMA database_list;
PRAGMA journal_mode;

#Как проверить результат

INSERT/UPDATE в специально выделенной тестовой базе проходят без SQLITE_READONLY, контрольная запись читается после открытия нового соединения, а служба не получила доступ к чужим каталогам. В рабочем приложении подтвердите исправление штатным действием.

#Если не помогло

При продолжающемся отказе проверьте доступ к родительским каталогам по всей цепочке, контекст SELinux/AppArmor, режим монтирования тома и квоту диска. Не пытайтесь исправить права единым chmod -R; подготовьте диагностические данные для администратора.

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

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