Errore SQLite "tentativo di scrivere un database in sola lettura" durante l'inserimento?


124

Ho un database SQLite che sto usando per un sito web. Il problema è che quando ci provo INSERT INTO, ottengo unPDOException

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

Sono entrato in SSH nel server e ho controllato i permessi, e il database ha i permessi

-rw-rw-r--

Non ho molta familiarità con i permessi * nix, ma sono abbastanza sicuro che questo significhi

  • Non una directory
  • Il proprietario ha autorizzazioni di lettura / scrittura (sono io, secondo ls -l)
  • Il gruppo dispone delle autorizzazioni di lettura / scrittura
  • Tutti gli altri hanno solo i permessi di lettura

Ho anche cercato ovunque sapessi di utilizzare il sqlite3programma e non ho trovato nulla di rilevante.

Poiché non sapevo con quali autorizzazioni PDO sta tentando di aprire il database, l'ho fatto

chmod o+w supplies.db

Ora ne ottengo un altro PDOException:

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

Ma si verifica SOLO quando provo a eseguire una INSERTquery dopo che il database è aperto.

Qualche idea su cosa sta succedendo?


fondamentalmente httpd (apache> php> PDO) non sei tu, quindi non possiede il file, quindi non ha i permessi di scrittura ... interessante ...
SparK

sudo chgrp www-data test.dbcon l'aggiunta delle autorizzazioni ha funzionato per me
Zippp

Risposte:


305

Il problema, come si scopre, è che il driver PDO SQLite richiede che, se avete intenzione di fare un'operazione di scrittura ( INSERT, UPDATE, DELETE, DROP, ecc), quindi la cartella del database risiede in devono avere i permessi di scrittura, così come l'attuale file di database.

Ho trovato queste informazioni in un commento in fondo alla pagina del manuale del driver SQLite di PDO .


9
Inoltre, SELinux (se installato) non deve essere imposto. Mi ci è voluto un giorno e mezzo per capirlo.
Steve V.

1
Hum, scusa, ma ringrazio che sia stato, ma risolve il problema solo temporaneamente, il problema principale era che il mio utente www-data non era nel gruppo www-data.
Dorian

5
Come so, la cartella contenente deve essere scrivibile perché in fase di scrittura verrà creato un file di journaling e quindi il db stesso. Per avere lo stesso utente del webserver, prova a copiare il contenuto del file in un altro creato ad hoc.
lcapra

4
Anche il file db e la directory in cui risiede devono essere di proprietà di "www-data" sulle macchine Linux.
anisbet

1
Attualmente sqlite3 potrebbe avere 3 file, the .db, ae .db-shma .db-walfile, e ovviamente la directory padre dei tre, che deve essere tutti scrivibili per l'utente che esegue il programma.
Marcos Dione,

17

Ciò può accadere quando il proprietario del file SQLite stesso non è lo stesso dell'utente che esegue lo script. Errori simili possono verificarsi se l'intero percorso della directory (ovvero ogni directory lungo il percorso) non può essere scritto.

Chi possiede il file SQLite? Tu?

Con chi viene eseguito lo script? Apache o nessuno?


1
Possiedo il file SQLite, ma non so con chi viene eseguito lo script. Come posso scoprirlo? (Tieni presente che questo è su un host condiviso e ho autorizzazioni limitate)
Austin Hyde

1
Ah, questo rende le cose più divertenti. Se sei su un hosting condiviso, ci sono ottime possibilità che lo script venga eseguito come "nessuno" o "apache". Fai in modo che il tuo script crei un file ( file_put_contents('./foo.txt', 'Hello, world');), che ti mostrerà con chi è in esecuzione. È probabile che sia necessario che lo script crei il database SQLite. Questo può essere un esercizio divertente se hai già dei dati nel tuo file corrente ...
Charles

Buona idea, ma no. Chiunque sia in esecuzione come PHP non dispone dei privilegi di scrittura, quindi non può creare il file. Esiste comunque PHP in grado di recuperare quale utente è attualmente in esecuzione?
Austin Hyde

L'unico modo sembra essere attraverso l'estensione POSIX , che è abilitata di default sui sistemi POSIX-y. Il tuo provider di hosting potrebbe avere R'd TFM e disabilitarlo, però.
Charles

Bene, hanno ricevuto TFM, va bene. posix_getuid()non funziona neanche.
Austin Hyde

6

Per me il problema era l' applicazione di SELinux piuttosto che i permessi. L'errore di "sola lettura del database" è scomparso una volta disabilitata l'applicazione, seguendo il suggerimento di Steve V. in un commento sulla risposta accettata.

echo 0 >/selinux/enforce

Dopo aver eseguito questo comando, tutto ha funzionato come previsto (CentOS 6.3).

Il problema specifico che avevo riscontrato era durante l'installazione di Graphite. Avevo controllato tre volte che l'utente apache possedesse e potesse scrivere sia sul mio graphite.db che sulla sua directory padre. Ma fino a quando non ho "corretto" SELinux, tutto ciò che ho ottenuto è stata una traccia dello stack con l'effetto di: DatabaseError: tentativo di scrivere un database di sola lettura


8
SELinux è una misura di sicurezza, quindi non dovrebbe essere disabilitato senza una buona ragione. Sarebbe meglio capire perché SELinux sta bloccando in primo luogo e configurarlo correttamente invece di disabilitarlo.
Jens Wegar

5

Questo può essere causato da SELinux. Se non vuoi disabilitare completamente SELinux, devi impostare la directory db fcontext su 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

Ho ricevuto questo errore quando ho provato a scrivere su un database su un sistema Android.

Apparentemente sqlite3 non solo ha bisogno dei permessi di scrittura sul file del database e sulla directory contenente (come ha già detto @ austin-hyde nella sua risposta) ma anche la variabile d'ambiente TMPDIRdeve puntare a una directory (possibilmente scrivibile).

Sul mio sistema Android l'ho impostato TMPDIR="/data/local/tmp"e ora il mio script viene eseguito come previsto :)

Modificare:

Se non puoi impostare le variabili d'ambiente puoi usare uno degli altri metodi elencati qui: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations comePRAGMA temp_store_directory = 'directory-name';


2

Ho ricevuto lo stesso errore da IIS in Windows 7. Per correggere questo errore ho dovuto aggiungere autorizzazioni di controllo completo all'account IUSR per il file di database sqlite. Non è necessario modificare le autorizzazioni se si utilizza sqlite in webmatrix invece di IIS.


2

In sintesi, ho risolto il problema inserendo il file di database (* .db) in una sottocartella.

  • La sottocartella e il file di database al suo interno devono essere membri del gruppo www-data.
  • Nel gruppo www-data, devi avere il diritto di scrivere nella sottocartella e nel file del database.

0

L'ho ottenuto nel mio browser quando sono passato dall'utilizzo di http: // localhost a http://145.900.50.20 (dove 145.900.50.20 è il mio indirizzo IP locale) e poi sono tornato a localhost: era necessario rimanere con il Indirizzo IP una volta cambiato in quello una volta


0

Ero solito:

echo exec ('whoami');

per scoprire chi sta eseguendo lo script (ad esempio nome utente), quindi ha concesso all'utente le autorizzazioni per l'intera directory dell'applicazione, come:

sudo chown -R: nomeutente / var / www / html / miaapp

Spero che questo aiuti qualcuno là fuori.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.