Kesalahan SQLite 'mencoba menulis database hanya-baca' selama penyisipan?

124

Saya memiliki database SQLite yang saya gunakan untuk situs web. Masalahnya adalah ketika saya mencobanya INSERT INTO, saya mendapatkan filePDOException

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

Saya SSH ke server dan memeriksa izin, dan database memiliki izin

-rw-rw-r--

Saya tidak begitu paham dengan izin * nix, tapi saya cukup yakin artinya

  • Bukan direktori
  • Pemilik memiliki izin baca / tulis (itu saya, menurut ls -l)
  • Grup memiliki izin baca / tulis
  • Semua orang hanya memiliki izin membaca

Saya juga mencari ke mana pun saya tahu untuk menggunakan sqlite3program ini, dan tidak menemukan sesuatu yang relevan.

Karena saya tidak tahu dengan izin apa PDO mencoba membuka database, saya tahu

chmod o+w supplies.db

Sekarang, saya mendapatkan yang lain PDOException:

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

Tapi itu HANYA terjadi ketika saya mencoba mengeksekusi INSERTquery setelah database terbuka.

Ada ide tentang apa yang sedang terjadi?

Austin Hyde
sumber
pada dasarnya httpd (apache> php> PDO) bukan Anda, jadi tidak memiliki file tersebut, jadi tidak memiliki izin tulis ... menarik ...
SparK
sudo chgrp www-data test.dbdengan menambahkan izin bekerja untuk saya
Zippp

Jawaban:

305

Masalahnya, ternyata, adalah bahwa driver PDO SQLite mengharuskan bahwa jika Anda akan melakukan operasi write ( INSERT, UPDATE, DELETE, DROP, dll), maka folder database berada di harus memiliki hak akses tulis, serta aktual file database.

Saya menemukan informasi ini dalam komentar di bagian paling bawah halaman manual driver PDO SQLite .

Austin Hyde
sumber
9
Selain itu, SELinux (jika diinstal) tidak boleh dijalankan. Butuh waktu satu setengah hari untuk memikirkannya.
Steve V.
1
Hum, maaf, tapi saya berterima kasih, tapi itu hanya menyelesaikan masalah sementara, masalah utamanya adalah pengguna www-data saya tidak ada di grup www-data.
Dorian
5
Seperti yang saya tahu, folder yang berisi harus bisa ditulisi karena ketika menulis file journal akan dibuat dan db itu sendiri. Untuk memiliki pengguna yang sama dengan server web, coba salin konten file ke ad hoc lain yang dibuat.
lcapra
4
Juga file db dan direktori tempatnya harus dimiliki oleh 'www-data' pada kotak linux.
anisbet
1
Saat ini sqlite3 mungkin memiliki 3 file, the .db, a .db-shmdan .db-walfile, dan tentu saja direktori induk dari ketiganya, yang semuanya harus dapat ditulis oleh pengguna yang menjalankan program.
Marcos Dione
17

Ini bisa terjadi jika pemilik file SQLite itu sendiri tidak sama dengan pengguna yang menjalankan skrip. Kesalahan serupa dapat terjadi jika seluruh jalur direktori (artinya setiap direktori di sepanjang jalan) tidak dapat ditulis.

Siapa pemilik file SQLite? Kamu?

Siapakah skrip yang dijalankan? Apache atau Tidak Ada?

Charles
sumber
1
Saya memiliki file SQLite, tetapi saya tidak tahu untuk siapa skrip tersebut dijalankan. Bagaimana saya bisa mengetahuinya? (Ingat, ini ada di host bersama dan saya memiliki izin terbatas)
Austin Hyde
1
Ah, itu membuat segalanya lebih menyenangkan. Jika Anda menggunakan shared hosting, kemungkinan besar skrip dijalankan sebagai "tidak ada" atau "apache". Minta skrip Anda membuat file ( file_put_contents('./foo.txt', 'Hello, world');), yang akan menunjukkan kepada Anda siapa yang menjalankannya. Kemungkinannya adalah Anda harus memiliki skrip untuk membuat database SQLite. Ini mungkin latihan yang menghibur jika Anda sudah memiliki data dalam file Anda saat ini ...
Charles
Ide bagus, tapi jangan pergi. Siapa pun yang menjalankan PHP tidak memiliki hak menulis, sehingga tidak dapat membuat file. Apakah tetap ada PHP dapat mengambil pengguna apa yang saat ini dijalankan?
Austin Hyde
Satu-satunya cara tampaknya adalah melalui ekstensi POSIX , yang diaktifkan secara default pada sistem POSIX-y. Penyedia hosting Anda mungkin memiliki TFM R'd dan menonaktifkannya.
Charles
Yah, mereka R'd TFM, oke. posix_getuid()tidak berhasil juga.
Austin Hyde
6

Bagi saya masalahnya adalah penegakan SELinux daripada izin. Kesalahan "database hanya baca" hilang setelah saya menonaktifkan penegakan, mengikuti saran yang dibuat oleh Steve V. dalam komentar pada jawaban yang diterima.

echo 0 >/selinux/enforce

Setelah menjalankan perintah ini, semuanya bekerja sebagaimana mestinya (CentOS 6.3).

Masalah khusus yang saya temui adalah selama penyiapan Graphite. Saya telah memeriksa tiga kali bahwa pengguna apache dimiliki dan dapat menulis ke graphite.db saya dan direktori induknya. Tetapi sampai saya "memperbaiki" SELinux, yang saya dapatkan hanyalah pelacakan tumpukan yang menyebabkan: DatabaseError: mencoba menulis database hanya-baca

Noah Sussman
sumber
8
SELinux adalah ukuran keamanan, jadi tidak boleh dinonaktifkan tanpa alasan yang kuat. Akan lebih baik untuk mencari tahu mengapa SELinux memblokir di tempat pertama dan mengkonfigurasinya dengan benar daripada menonaktifkannya.
Jens Wegar
5

Ini dapat disebabkan oleh SELinux. Jika Anda tidak ingin menonaktifkan SELinux sepenuhnya, Anda perlu menyetel direktori db fcontext ke 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
sumber
4

Saya mendapat kesalahan ini ketika saya mencoba menulis ke database di sistem Android.

Rupanya sqlite3 tidak hanya membutuhkan izin menulis ke file database dan direktori yang berisi (seperti yang sudah dikatakan @ austin-hyde dalam jawabannya) tetapi juga variabel lingkungan TMPDIR harus mengarah ke direktori (mungkin dapat ditulis).

Di sistem Android saya, saya menyetelnya ke TMPDIR="/data/local/tmp" dan sekarang skrip saya berjalan seperti yang diharapkan :)

Edit:

Jika Anda tidak dapat mengatur variabel lingkungan, Anda dapat menggunakan salah satu metode lain yang tercantum di sini: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations likePRAGMA temp_store_directory = 'directory-name';

Thilo
sumber
2

Saya mendapat kesalahan yang sama dari IIS di bawah windows 7. Untuk memperbaiki kesalahan ini saya harus menambahkan izin kontrol penuh ke akun IUSR untuk file database sqlite. Anda tidak perlu mengubah izin jika Anda menggunakan sqlite di bawah matriks web, bukan IIS.

l0pan
sumber
2

Singkatnya, saya telah memperbaiki masalah dengan meletakkan file database (* .db) dalam subfolder.

  • Subfolder dan file database di dalamnya harus menjadi anggota grup www-data.
  • Di grup www-data, Anda harus memiliki hak untuk menulis ke subfolder dan file database.
Erkan Hürnalı
sumber
0

Saya mendapatkan ini di browser saya ketika saya mengubah dari menggunakan http: // localhost ke http://145.900.50.20 (di mana 145.900.50.20 adalah alamat IP lokal saya) dan kemudian mengubahnya kembali ke localhost - itu perlu untuk tetap dengan Alamat IP setelah saya mengubahnya sekali

keris
sumber
0

Saya menggunakan:

echo exec ('whoami');

untuk mengetahui siapa yang menjalankan skrip (katakanlah nama pengguna), dan kemudian berikan izin pengguna ke seluruh direktori aplikasi, seperti:

sudo chown -R: nama pengguna / var / www / html / myapp

Semoga ini bisa membantu seseorang di luar sana.

shasi kanth
sumber