159 votes

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

J'ai une base de données SQLite que j'utilise pour un site web. Le problème est que lorsque j'essaie de INSERT INTO dedans, j'obtiens une PDOException

SQLSTATE[HY000]: Erreur générale: 8 tentative d'écriture dans une base de données en lecture seule

J'ai utilisé SSH pour accéder au serveur et vérifier les autorisations, et la base de données a les autorisations

-rw-rw-r--

Je ne suis pas très familier avec les permissions *nix, mais je suis assez sûr que cela signifie

  • Pas un répertoire
  • Le propriétaire a les permissions de lecture/écriture (c'est moi, selon ls -l)
  • Le groupe a les permissions de lecture/écriture
  • Tout le monde d'autre a seulement les permissions de lecture

J'ai aussi cherché partout où je savais avec le programme sqlite3, et je n'ai rien trouvé de pertinent.

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

chmod o+w supplies.db

Maintenant, j'obtiens une autre PDOException:

SQLSTATE[HY000]: Erreur générale: 14 impossible d'ouvrir le fichier de base de données

Mais cela se produit SEULEMENT lorsque j'essaie d'exécuter une requête INSERT après l'ouverture de la base de données.

Des idées sur ce qui se passe?

0 votes

Fondamentalement, le httpd (apache > php > PDO) n'est pas vous, donc il ne possède pas le fichier, donc il n'a pas les permissions d'écriture... intéressant...

0 votes

sudo chgrp www-data test.db avec l'ajout des autorisations a fonctionné pour moi

0 votes

Cette erreur est également affichée si vous essayez d'accéder à une base de données supprimée

396voto

Austin Hyde Points 8270

Le problème, en fait, est que le pilote PDO SQLite exige que si vous allez effectuer une opération d'écriture (INSERT,UPDATE,DELETE,DROP, etc), alors le dossier dans lequel se trouve la base de données doit avoir des autorisations d'écriture, ainsi que le fichier de base de données lui-même.

J'ai trouvé cette information dans un commentaire en bas de la page du manuel du pilote PDO SQLite.

12 votes

Aussi, SELinux (si installé) ne doit pas être en application. M'a pris une journée et demie pour comprendre cela.

1 votes

Hum, désolé, mais je pense que c'était ça, mais cela a juste résolu le problème temporairement, le problème principal était que mon utilisateur www-data n'était pas dans le groupe www-data.

8 votes

Comme je le sais, le dossier conteneur doit être inscriptible car lors de l'écriture d'un journal, un fichier 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 créé spécifiquement.

22voto

Charles Points 33585

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 survenir si le chemin complet du répertoire (c'est-à-dire chaque répertoire sur le chemin) ne peut pas être écrit.

Qui est le propriétaire du fichier SQLite? Toi?

Sur quel utilisateur s'exécute le script? Apache ou Nobody?

1 votes

Je possède le fichier SQLite, mais je ne sais pas sous quel nom le script s'exécute. Comment puis-je le savoir? (Gardez à l'esprit que cela se trouve sur un hôte partagé et que j'ai des autorisations limitées)

2 votes

Ah, cela rend les choses plus amusantes. Si vous êtes sur un hébergement partagé, il y a de fortes chances que le script s'exécute en tant que "personne" ou "apache". Faites en sorte que votre script crée un fichier (file_put_contents('./foo.txt', 'Hello, world');), qui vous montrera sous quel nom il s'exécute. Il est fort possible que vous ayez besoin que le script crée la base de données SQLite. Cela peut être un exercice amusant si vous avez déjà des données dans votre fichier actuel...

0 votes

Bonne idée, mais impossible. Quel que soit l'utilisateur sous lequel PHP s'exécute n'a pas les droits d'écriture, donc il ne peut pas créer le fichier. Y a-t-il un moyen pour PHP de récupérer l'utilisateur sous lequel il s'exécute actuellement?

7voto

Andy Fraley Points 461

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

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

7voto

Erkan Hürnalı Points 21

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

  • Le sous-dossier et le fichier de base de données à l'intérieur doivent faire partie 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.

####### Notes supplémentaires pour un problème similaire #####

J'ai donné des autorisations d'écriture à mon fichier de base de données sqlite pour les autres utilisateurs et groupes mais cela n'a pas fonctionné.

Le fichier est dans le répertoire racine de mon .NET Core WebApi.

Ça ressemblait à ça :

-rw-rw-rw-  1 root root  24576 Jan 28 16:03 librestore.db

Même si j'ai exécuté le service en tant que root, j'ai continué à recevoir l'erreur:

Erreur: Erreur SQLite 8: 'tentative d'écrire dans une base de données en lecture seule'.

J'ai également fait un chown sur le librestore.db pour www-data et j'ai toujours reçu la même erreur.

Finalement, j'ai déplacé au-dessus de mon répertoire webroot et donné aux autres l'accès en écriture à ce répertoire (LibreStore - la racine de mon WebApi) et ensuite ça a fonctionné.

Le répertoire web a un accès en écriture

Je ne suis pas sûr pourquoi j'ai dû donner l'accès en écriture au répertoire si le fichier spécifique avait déjà un accès en écriture, mais c'est la seule chose qui a fonctionné.

Mais une fois que j'ai fait ce changement, l'utilisateur www-data a pu accéder au fichier .db et les inserts ont réussi.

7voto

Noah Sussman Points 2512

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

echo 0 >/selinux/enforce

Après avoir exécuté 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é à plusieurs reprises 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 j'ai "corrigé" SELinux, tout ce que j'obtenais était une trace de pile indiquant : DatabaseError: tentative d'écriture dans une base de données en lecture seule

12 votes

SELinux est une mesure de sécurité, il ne doit donc pas être désactivé sans 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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X