Erreur SQLite 'tentative d'écriture d'une base de données en lecture seule' lors de l'insertion?

124

J'ai une base de données SQLite que j'utilise pour un site Web. Le problème est que lorsque j'essaye INSERT INTO, j'obtiens unPDOException

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

J'ai SSH sur le serveur et vérifié les autorisations, et la base de données a les autorisations

-rw-rw-r--

Je ne connais pas très bien les autorisations * nix, mais je suis presque sûr que cela signifie

  • Pas un annuaire
  • Le propriétaire a des autorisations de lecture / écriture (c'est moi, selon ls -l)
  • Le groupe dispose d'autorisations de lecture / écriture
  • Tout le monde n'a que des autorisations de lecture

J'ai également cherché partout où je savais comment utiliser le sqlite3programme et je n'ai rien trouvé de pertinent.

Parce que je ne savais pas avec quelles autorisations PDO essaie d'ouvrir la base de données, j'ai fait

chmod o+w supplies.db

Maintenant, j'en ai un autre PDOException:

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

Mais cela se produit UNIQUEMENT lorsque j'essaye d'exécuter une INSERTrequête après l' ouverture de la base de données.

Des idées sur ce qui se passe?

Austin Hyde
la source
fondamentalement, le httpd (apache> php> PDO) n'est pas vous, donc il ne possède pas le fichier, donc il n'a pas les autorisations d'écriture ... intéressant ...
SparK
sudo chgrp www-data test.dbavec l'ajout d'autorisations a fonctionné pour moi
Zippp

Réponses:

305

Le problème, il se trouve, est que le pilote PDO SQLite exige que si vous allez faire une opération d'écriture ( INSERT, UPDATE, DELETE, DROP, etc.), puis le dossier de la base de données réside dans doivent disposer des autorisations d'écriture, ainsi que la réelle fichier de base de données.

J'ai trouvé ces informations dans un commentaire tout en bas de la page de manuel du pilote PDO SQLite .

Austin Hyde
la source
9
De plus, SELinux (s'il est installé) ne doit pas être appliqué. Il m'a fallu un jour et demi pour comprendre celui-là.
Steve V.
1
Hum, désolé, mais je remercie que ce soit tout, mais cela résout le problème temporairement, le principal problème était que mon utilisateur www-data ne faisait pas partie du groupe www-data.
Dorian
5
Comme je le sais, le dossier contenant doit être accessible en écriture car lors de l'écriture, un fichier de journalisation sera créé et donc la base de données elle-même. Pour avoir le même utilisateur que le serveur Web, essayez de copier le contenu du fichier dans un autre ad hoc créé.
lcapra
4
De plus, le fichier db et le répertoire dans lequel il réside doivent appartenir à «www-data» sur les boîtiers Linux.
anisbet
1
À l' heure actuelle sqlite3 pourrait avoir 3 fichiers, les .db, un .db-shmet un .db-walfichier, et bien sûr le répertoire parent des trois, qui doit être tous inscriptibles pour l'utilisateur d' exécuter le programme.
Marcos Dione
17

Cela peut se produire lorsque le propriétaire du fichier SQLite lui-même n'est pas le même que l'utilisateur exécutant le script. Des erreurs similaires peuvent se produire si le chemin du répertoire complet (c'est-à-dire chaque répertoire en cours de route) ne peut pas être écrit.

À qui appartient le fichier SQLite? Tu?

À qui s'exécute le script? Apache ou personne?

Charles
la source
1
Je possède le fichier SQLite, mais je ne sais pas à qui le script s'exécute. Comment puis-je le savoir? (Gardez à l'esprit, ceci est sur un hôte partagé et j'ai des autorisations limitées)
Austin Hyde
1
Ah, ça rend les choses plus amusantes. Si vous êtes sur un hébergement mutualisé, il y a de très bonnes chances que le script s'exécute en tant que "personne" ou "apache". Demandez à votre script de créer un fichier ( file_put_contents('./foo.txt', 'Hello, world');), qui vous montrera sous qui il s'exécute. Il est fort probable que vous deviez demander au script de créer la base de données SQLite. Cela peut être un exercice divertissant si vous avez déjà des données dans votre fichier actuel ...
Charles
Bonne idée, mais non. Quiconque utilise PHP n'a pas de privilèges d'écriture, il ne peut donc pas créer le fichier. Existe-t-il de toute façon que PHP puisse récupérer l'utilisateur sous lequel il s'exécute actuellement?
Austin Hyde
Le seul moyen semble être via l'extension POSIX , qui est activée par défaut sur les systèmes POSIX-y. Votre fournisseur d'hébergement peut cependant avoir R'd TFM et l'a désactivé.
Charles
Eh bien, ils ont R'd TFM, d'accord. posix_getuid()ne fonctionne pas non plus.
Austin Hyde
6

Pour moi, le problème était l' application de SELinux plutôt que les autorisations. L'erreur "lecture seule de la base de données" a disparu une fois que j'ai désactivé l'application, suite à la suggestion faite par Steve V. dans un commentaire sur la réponse acceptée.

echo 0 >/selinux/enforce

Lors de l'exécution de cette commande, tout a fonctionné comme prévu (CentOS 6.3).

Le problème spécifique que j'avais rencontré était lors de la configuration de Graphite. J'avais vérifié trois fois que l'utilisateur apache possédait et pouvait écrire à la fois dans mon graphite.db et dans son répertoire parent. Mais jusqu'à ce que je "corrige" SELinux, tout ce que j'ai obtenu était une trace de pile à l'effet de: DatabaseError: tentative d'écrire une base de données en lecture seule

Noah Sussman
la source
8
SELinux est une mesure de sécurité, donc ne doit pas être désactivé sans une très bonne raison. Il serait préférable de comprendre pourquoi SELinux bloque en premier lieu et de le configurer correctement au lieu de le désactiver.
Jens Wegar
5

Cela peut être causé par SELinux. Si vous ne souhaitez pas désactiver complètement SELinux, vous devez définir le répertoire db fcontext sur httpd_sys_rw_content_t.

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/railsapp/db(/.*)?"
restorecon -v /var/www/railsapp/db
Andy Fraley
la source
4

J'ai eu cette erreur lorsque j'ai essayé d'écrire dans une base de données sur un système Android.

Apparemment, sqlite3 n'a pas seulement besoin d'autorisations d'écriture sur le fichier de base de données et le répertoire contenant (comme @ austin-hyde l'a déjà dit dans sa réponse), mais aussi la variable d'environnement TMPDIRdoit pointer vers un répertoire (éventuellement accessible en écriture).

Sur mon système Android, je l'ai configuré TMPDIR="/data/local/tmp"et maintenant mon script s'exécute comme prévu :)

Éditer:

Si vous ne pouvez pas définir de variables d'environnement, vous pouvez utiliser l'une des autres méthodes répertoriées ici: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations commePRAGMA temp_store_directory = 'directory-name';

Thilo
la source
2

J'ai eu la même erreur d'IIS sous Windows 7. Pour corriger cette erreur, j'ai dû ajouter des autorisations de contrôle complet au compte IUSR pour le fichier de base de données sqlite. Vous n'avez pas besoin de modifier les autorisations si vous utilisez sqlite sous webmatrix au lieu d'IIS.

l0pan
la source
2

En résumé, j'ai résolu le problème en plaçant le fichier de base de données (* .db) dans un sous-dossier.

  • Le sous-dossier et le fichier de base de données qu'il contient doivent être membres du groupe www-data.
  • Dans le groupe www-data, vous devez avoir le droit d'écrire dans le sous-dossier et le fichier de base de données.
Erkan Hürnalı
la source
0

Je l'ai eu dans mon navigateur lorsque j'ai changé d'utiliser http: // localhost à http://145.900.50.20 (où 145.900.50.20 est mon adresse IP locale), puis je suis revenu à localhost - il était nécessaire de rester avec le Adresse IP une fois que je l'ai changé une fois

kris
la source
0

J'ai utilisé:

echo exec ('whoami');

pour savoir qui exécute le script (par exemple, nom d'utilisateur), puis a donné à l'utilisateur des autorisations sur l'ensemble du répertoire de l'application, comme:

sudo chown -R: nom d'utilisateur / var / www / html / myapp

J'espère que cela aide quelqu'un là-bas.

shasi kanth
la source