ข้อผิดพลาด 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 (หากติดตั้ง) ใช้เวลาหนึ่งวันครึ่งในการคิดออก
Steve V.

1
ฮึ่มขอโทษ แต่ฉันขอบคุณที่เป็นเช่นนั้น แต่มันก็ช่วยแก้ปัญหาได้ในชั่วขณะปัญหาหลักคือผู้ใช้ www-data ของฉันไม่ได้อยู่ในกลุ่ม www-data
Dorian

5
ดังที่ฉันทราบโฟลเดอร์ที่มีจะต้องสามารถเขียนได้เนื่องจากเมื่อเขียนไฟล์เจอร์นัลจะถูกสร้างขึ้นและฐานข้อมูลเอง หากต้องการมีผู้ใช้คนเดียวกับเว็บเซิร์ฟเวอร์ให้ลองคัดลอกเนื้อหาของไฟล์ไปยังเฉพาะกิจที่สร้างขึ้น
lcapra

4
นอกจากนี้ไฟล์ db และไดเร็กทอรีที่อยู่ในนั้นจะต้องเป็นของ 'www-data' บนกล่อง linux
anisbet

1
ปัจจุบัน sqlite3 อาจมี 3 ไฟล์คือ.dba .db-shmและ.db-walไฟล์และแน่นอนไดเร็กทอรีหลักของทั้งสามซึ่งจะต้องเขียนได้ทั้งหมดสำหรับผู้ใช้ที่รันโปรแกรม
Marcos Dione

17

สิ่งนี้สามารถเกิดขึ้นได้เมื่อเจ้าของไฟล์ SQLite ไม่เหมือนกับผู้ใช้ที่รันสคริปต์ ข้อผิดพลาดที่คล้ายกันนี้อาจเกิดขึ้นได้หากไม่สามารถเขียนพา ธ ไดเร็กทอรีทั้งหมด (หมายถึงแต่ละไดเร็กทอรีไปพร้อมกัน)

ใครเป็นเจ้าของไฟล์ SQLite คุณ?

สคริปต์ทำงานเป็นใคร Apache หรือไม่มีใคร?


1
ฉันเป็นเจ้าของไฟล์ SQLite แต่ไม่รู้ว่าสคริปต์ทำงานเป็นใคร ฉันจะรู้ได้อย่างไร (โปรดทราบว่านี่เป็นโฮสต์ที่ใช้ร่วมกันและฉันมีสิทธิ์ จำกัด )
Austin Hyde

1
อาทำให้เรื่องสนุกขึ้น หากคุณใช้โฮสติ้งที่ใช้ร่วมกันมีโอกาสดีมากที่สคริปต์จะทำงานเป็น "ไม่มีใคร" หรือ "apache" ให้สคริปต์ของคุณสร้างไฟล์ ( file_put_contents('./foo.txt', 'Hello, world');) ซึ่งจะแสดงให้คุณเห็นว่ากำลังทำงานเป็นใคร มีโอกาสที่คุณจะต้องให้สคริปต์สร้างฐานข้อมูล SQLite นี่อาจเป็นการออกกำลังกายเพื่อความบันเทิงหากคุณมีข้อมูลอยู่แล้วในไฟล์ปัจจุบันของคุณ ...
Charles

ความคิดที่ดี แต่ไม่ต้องไป ใครก็ตามที่ PHP ทำงานโดยไม่มีสิทธิ์ในการเขียนจึงไม่สามารถสร้างไฟล์ได้ อย่างไรก็ตาม PHP สามารถดึงข้อมูลผู้ใช้ที่กำลังทำงานอยู่ในขณะนี้ได้หรือไม่?
Austin Hyde

วิธีเดียวที่ดูเหมือนจะเป็นผ่านส่วนขยาย POSIXซึ่งเปิดใช้งานโดยค่าเริ่มต้นบนระบบ POSIX-y ผู้ให้บริการโฮสติ้งของคุณอาจมีR'd TFMและปิดการใช้งาน
Charles

พวกเขา R'd TFM เอาล่ะ posix_getuid()ไม่ได้ผลเช่นกัน
Austin Hyde

6

สำหรับฉันปัญหาคือการบังคับใช้ SELinuxแทนที่จะเป็นสิทธิ์ ข้อผิดพลาด "ฐานข้อมูลอ่านอย่างเดียว" หายไปเมื่อฉันปิดใช้งานการบังคับใช้ตามคำแนะนำของ Steve V. ในความคิดเห็นเกี่ยวกับคำตอบที่ยอมรับ

echo 0 >/selinux/enforce

เมื่อรันคำสั่งนี้ทุกอย่างทำงานตามที่ตั้งใจไว้ (CentOS 6.3)

ปัญหาเฉพาะที่ฉันพบคือระหว่างการตั้งค่า Graphite ฉันตรวจสอบสามครั้งแล้วว่าผู้ใช้ apache เป็นเจ้าของและสามารถเขียนไปยังทั้ง graphite.db และไดเร็กทอรีหลักของฉัน แต่จนกว่าฉันจะ "แก้ไข" SELinux สิ่งที่ฉันได้คือการติดตามสแต็กของผลกระทบของ: DatabaseError: พยายามเขียนฐานข้อมูลแบบอ่านอย่างเดียว


8
SELinux เป็นมาตรการรักษาความปลอดภัยดังนั้นไม่ควรปิดใช้งานโดยไม่มีเหตุผลที่ดีมาก จะเป็นการดีกว่าถ้าจะหาสาเหตุที่ SELinux บล็อกตั้งแต่แรกและกำหนดค่าให้ถูกต้องแทนที่จะปิดใช้งาน
Jens Wegar

5

อาจเกิดจาก SELinux หากคุณไม่ต้องการปิดใช้งาน SELinux โดยสมบูรณ์คุณต้องตั้งค่า fcontext ไดเร็กทอรี db เป็น 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#tem Contemporary_file_storage_locations เช่นPRAGMA temp_store_directory = 'directory-name';


2

ฉันได้รับข้อผิดพลาดเดียวกันจาก IIS ภายใต้ windows 7 ในการแก้ไขข้อผิดพลาดนี้ฉันต้องเพิ่มสิทธิ์การควบคุมทั้งหมดในบัญชี IUSR สำหรับไฟล์ฐานข้อมูล sqlite คุณไม่จำเป็นต้องเปลี่ยนสิทธิ์หากคุณใช้ sqlite ภายใต้ webmatrix แทน IIS


2

โดยสรุปฉันได้แก้ไขปัญหาโดยการใส่ไฟล์ฐานข้อมูล (* .db) ในโฟลเดอร์ย่อย

  • โฟลเดอร์ย่อยและไฟล์ฐานข้อมูลภายในต้องเป็นสมาชิกของกลุ่ม www-data
  • ในกลุ่ม www-data คุณต้องมีสิทธิ์เขียนลงในโฟลเดอร์ย่อยและไฟล์ฐานข้อมูล

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

หวังว่านี่จะช่วยใครบางคนได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.