Помилка SQLite "спроба записати базу даних лише для читання" під час вставки?


124

У мене є база даних SQLite, яку я використовую для веб-сайту. Проблема полягає в тому, що коли я спробую INSERT INTOце, я отримуюPDOException

SQLSTATE[HY000]: General error: 8 attempt to write a readonly database

Я SSH зайшов у сервер і перевірив дозволи, а база даних має дозволи

-rw-rw-r--

Я не такий знайомий з дозволами * nix, але я впевнений, що це означає

  • Не каталог
  • Власник дозволу на читання / запис (це я, згідно ls -l)
  • Група має дозволи на читання / запис
  • Усі інші мають лише дозволи на читання

Я також шукав всюди, де я знав, як користуватися sqlite3програмою, і не знайшов нічого актуального.

Оскільки я не знав, з якими дозволами PDO намагається відкрити базу даних, я це зробив

chmod o+w supplies.db

Тепер я отримую ще PDOException:

SQLSTATE[HY000]: General error: 14 unable to open database file

Але це ТІЛЬКИ виникає, коли я намагаюся виконати INSERTзапит після відкриття бази даних.

Будь-які ідеї щодо того, що відбувається?


в основному httpd (apache> php> PDO) - це не ти, тому він не володіє файлом, тому у нього немає дозволів на запис ... цікаво ...
SparK

sudo chgrp www-data test.dbз додаванням дозволів працював на мене
Zippp

Відповіді:


305

Проблема, як з'ясовується, є те , що драйвер PDO SQLite вимагає , що якщо ви збираєтеся робити операцію запису ( INSERT, UPDATE, DELETE, DROPі т.д.), то папка бази даних постійно знаходиться в повинен мати права на запис, а також фактичне файл бази даних.

Цю інформацію я знайшов у коментарі в самому дні сторінки керівництва драйверів PDO SQLite .


9
Крім того, SELinux (якщо він встановлений) не повинен бути примусовим. Мені потрібно було півтора дня, щоб зрозуміти це.
Стів В.

1
Хум, вибачте, але я вдячний, що це було, але це просто вирішує проблему тимчасово, головним питанням було те, що мій користувач www-даних не був у групі даних www.
Доріан

5
Як я знаю, папка, що містить, повинна бути написана для запису, тому що при написанні журнального файлу буде створено файл журналу, і так сам db. Щоб користувач був таким самим користувачем, як веб-сервер, спробуйте скопіювати вміст файлу в інший створений ad hoc.
lcapra

4
Також db-файл та каталог, у якому він перебуває, повинні бути власниками "www-data" на вікнах linux.
анісбет

1
В даний час sqlite3 може мати 3 файли, .dba, a .db-shmі .db-walфайли, і звичайно батьківський каталог із трьох, який повинен бути доступним для запису користувача, який запускає програму.
Маркос Діона

17

Це може статися, коли власник файлу SQLite сам не такий, як користувач, що запускає скрипт. Подібні помилки можуть виникнути, якщо не вдасться записати весь шлях до каталогу (маючи на увазі кожен каталог по дорозі).

Кому належить файл SQLite? Ти?

Для кого працює сценарій? Апач чи ніхто?


1
Я є власником файлу SQLite, але я не знаю, як працює сценарій. Як я можу це дізнатися? (Майте на увазі, це на спільному хості, і у мене обмежені дозволи)
Austin Hyde

1
А, це робить речі веселішими. Якщо ви перебуваєте на спільному хостингу, є дуже хороший шанс, що сценарій працює як "ніхто" або "апаш". Попросіть ваш сценарій створити файл ( file_put_contents('./foo.txt', 'Hello, world');), який покаже вам, як він працює. Швидше за все, вам потрібно буде мати сценарій для створення бази даних SQLite. Це може бути захоплюючою вправою, якщо у вас уже є дані у вашому поточному файлі ...
Чарльз,

Гарна ідея, але нікуди. Хто не працює у PHP, не має прав на запис, тому не може створити файл. Чи все-таки PHP може отримати того користувача, яким він зараз працює?
Остін Гайд

Здається, єдиний спосіб - через розширення POSIX , яке за умовчанням увімкнено для систем POSIX-y. Можливо, ваш хостинг-провайдер має R'd TFM і відключив його.
Чарльз

Ну, вони R'd TFM, добре. posix_getuid()теж не працює.
Остін Гайд

6

Для мене проблема полягала в застосуванні SELinux, а не дозволах. Помилка "лише для читання в базі даних" усунулася, коли я відключив примусове виконання, слідуючи пропозиціям Стіва В. у коментарі до прийнятої відповіді.

echo 0 >/selinux/enforce

Після запуску цієї команди все працювало за призначенням (CentOS 6.3).

Конкретна проблема, з якою я стикався, була під час налаштування Graphite. Я тричі перевіряв, що користувач apache володіє і може писати як на мій graphite.db, так і в його батьківський каталог. Але поки я не "виправив" SELinux, все, що я отримав, - це стеження сліду до ефекту: DatabaseError: спроба написати лише базу даних для читання


8
SELinux є заходом безпеки, тому його не можна відключати без дуже вагомих причин. Було б краще розібратися, чому SELinux блокується в першу чергу і правильно налаштувати її, а не вимикати її.
Єнс Вегар

5

Це може бути викликано SELinux. Якщо ви не хочете повністю відключити SELinux, вам потрібно встановити для db каталогу fcontext httpd_sys_rw_content_t.

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/railsapp/db(/.*)?"
restorecon -v /var/www/railsapp/db

4

Я отримав цю помилку, коли спробував записати в базу даних на системі Android.

Мабуть, sqlite3 потребує не лише дозволу на запис у файл бази даних та у каталог, що містить (як @ austin-hyde вже говорив у своїй відповіді), але й змінна середовище TMPDIRмає вказувати на (можливо, доступний для запису) каталог.

У моїй системі Android я його встановив, TMPDIR="/data/local/tmp"і тепер мій сценарій працює так, як очікувалося :)

Редагувати:

Якщо ви не можете встановити змінні середовища, ви можете скористатися одним із інших перелічених тут методів: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations, якPRAGMA temp_store_directory = 'directory-name';


2

Я отримав таку саму помилку від IIS під Windows 7. Щоб виправити цю помилку, мені довелося додати дозволи на повний контроль до облікового запису IUSR для файлу бази даних sqlite. Вам не потрібно змінювати дозволи, якщо ви використовуєте sqlite під webmatrix замість IIS.


2

Підсумовуючи, я вирішив проблему, помістивши файл бази даних (* .db) у підпапку.

  • Підпапка та файл бази даних у ній повинні бути учасниками групи даних www.
  • У групі даних www ви повинні мати право запису в підпапку та файл бази даних.

0

Я отримав це у своєму браузері, коли я перейшов з http: // localhost на http://145.900.50.20 (де 145.900.50.20 - моя локальна IP-адреса), а потім повернувся на localhost - потрібно було залишитися з IP-адреса, як тільки я один раз змінила цю


0

Я використав:

echo exec ('whoami');

щоб дізнатися, хто запускає скрипт (скажіть ім’я користувача), а потім надав користувачеві дозволи на весь каталог додатків, наприклад:

sudo chown -R: ім'я користувача / var / www / html / myapp

Сподіваюся, це допомагає комусь там.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.