Erro SQLite 'tentativa de gravar um banco de dados somente leitura' durante a inserção?


124

Eu tenho um banco de dados SQLite que estou usando para um site. O problema é que, quando eu tento INSERT INTO, recebo umaPDOException

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

Eu fiz o SSH no servidor e verifiquei as permissões, e o banco de dados tem as permissões

-rw-rw-r--

Não conheço as permissões * nix, mas tenho certeza de que isso significa

  • Não é um diretório
  • O proprietário tem permissões de leitura / gravação (sou eu, de acordo com ls -l)
  • O grupo tem permissões de leitura / gravação
  • Todos os outros só têm permissões de leitura

Eu também procurei em todos os lugares que sabia usar o sqlite3programa e não encontrei nada relevante.

Como não sabia com que permissões o PDO está tentando abrir o banco de dados, fiz

chmod o+w supplies.db

Agora, eu recebo outro PDOException:

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

Mas isso ocorre apenas quando tento executar uma INSERTconsulta depois que o banco de dados é aberto.

Alguma idéia do que está acontecendo?


basicamente o httpd (apache> php> DOP) não é você, por isso não possui o arquivo, para que ele não tem permissões de gravação ... interessante ...
faísca

sudo chgrp www-data test.dbcom permissões adicionando funcionou para mim
Zippp

Respostas:


305

O problema, como se vê, é que o driver PDO SQLite exige que se você estiver indo para fazer uma operação de gravação ( INSERT, UPDATE, DELETE, DROP, etc), então a pasta do banco de dados reside em deve ter permissões de gravação, bem como o real arquivo de banco de dados.

Encontrei essas informações em um comentário na parte inferior da página do manual do driver DOP SQLite .


9
Além disso, o SELinux (se instalado) não deve ser aplicado. Levei um dia e meio para descobrir isso.
Steve V.

1
Hum, desculpe, mas agradeço, mas resolvi o problema no momento, o problema principal era que meu usuário de dados www não estava no grupo de dados www.
Dorian

5
Como eu sei, a pasta que contém deve ser gravável, porque ao gravar um arquivo de diário será criado e, portanto, o próprio banco de dados. Para ter o mesmo usuário que o servidor da web, tente copiar o conteúdo do arquivo para outro ad hoc criado.
Lcapra

4
Além disso, o arquivo db e o diretório em que reside devem pertencer a 'www-data' nas caixas linux.
Ansset

1
Atualmente, o sqlite3 pode ter 3 arquivos, os arquivos a .dbe a .db-shme .db-wal, é claro, o diretório pai dos três, que devem ser todos graváveis ​​para o usuário que está executando o programa.
Marcos Dione

17

Isso pode acontecer quando o proprietário do arquivo SQLite em si não é o mesmo que o usuário executando o script. Erros semelhantes podem ocorrer se todo o caminho do diretório (ou seja, cada diretório ao longo do caminho) não puder ser gravado.

Quem possui o arquivo SQLite? Vocês?

Para quem o script está sendo executado? Apache ou ninguém?


1
Eu possuo o arquivo SQLite, mas não sei como o script é executado. Como posso descobrir? (Lembre-se, ele está em um host compartilhado e eu tenho permissões limitadas) #
Austin Hyde

1
Ah, isso torna as coisas mais divertidas. Se você estiver em hospedagem compartilhada, há uma chance muito boa de que o script seja executado como "ninguém" ou "apache". Faça com que seu script crie um arquivo ( file_put_contents('./foo.txt', 'Hello, world');), que mostre a você como ele está sendo executado. Provavelmente, você precisará que o script crie o banco de dados SQLite. Isso pode ser um exercício divertido, se você já possui dados em seu arquivo atual ... #
Charles

Boa ideia, mas não. Quem quer que o PHP esteja executando como não possui privilégios de gravação, não pode criar o arquivo. Existe alguma maneira de o PHP recuperar o usuário que está sendo executado atualmente?
Austin Hyde

A única maneira parece ser através da extensão POSIX , que é ativada por padrão nos sistemas POSIX-y. No entanto, seu provedor de hospedagem pode ter R'd TFM e desativado.
Charles

Bem, eles fizeram TFM, tudo bem. posix_getuid()também não funciona.
Austin Hyde

6

Para mim, o problema era a imposição do SELinux, e não as permissões. O erro "banco de dados somente leitura" desapareceu assim que eu desabilitei a aplicação, seguindo a sugestão feita por Steve V. em um comentário sobre a resposta aceita.

echo 0 >/selinux/enforce

Ao executar este comando, tudo funcionou como planejado (CentOS 6.3).

O problema específico que encontrei foi durante a instalação do Graphite. Eu tinha verificado três vezes se o usuário do apache possuía e podia escrever no meu graphite.db e no diretório pai. Mas até eu "consertar" o SELinux, tudo o que consegui foi um rastreamento de pilha com o efeito de: DatabaseError: tentativa de escrever um banco de dados somente leitura


8
O SELinux é uma medida de segurança, portanto não deve ser desativado sem uma boa razão. Seria melhor descobrir por que o SELinux está bloqueando em primeiro lugar e configurá-lo corretamente, em vez de desativá-lo.
Jens Wegar

5

Isso pode ser causado pelo SELinux. Se você não deseja desabilitar o SELinux completamente, precisa configurar o diretório db fcontext como 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

Eu recebi esse erro quando tentei gravar em um banco de dados em um sistema Android.

Aparentemente, o sqlite3 não apenas precisa de permissões de gravação para o arquivo do banco de dados e o diretório que contém (como @ austin-hyde já disse em sua resposta), mas também a variável de ambiente TMPDIRdeve apontar para um diretório (possivelmente gravável).

No meu sistema Android, eu o defino TMPDIR="/data/local/tmp"e agora meu script é executado conforme o esperado :)

Editar:

Se você não puder definir variáveis ​​de ambiente, poderá usar um dos outros métodos listados aqui: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations comoPRAGMA temp_store_directory = 'directory-name';


2

Eu obtive o mesmo erro do IIS no Windows 7. Para corrigir esse erro, tive que adicionar permissões de controle total à conta IUSR para o arquivo de banco de dados sqlite. Você não precisa alterar as permissões se usar o sqlite no webmatrix em vez do IIS.


2

Em resumo, corrigi o problema colocando o arquivo de banco de dados (* .db) em uma subpasta.

  • A subpasta e o arquivo de banco de dados dentro dela devem ser membros do grupo www-data.
  • No grupo www-data, você deve ter o direito de gravar na subpasta e no arquivo do banco de dados.

0

Eu obtive isso no meu navegador quando mudei de http: // localhost para http://145.900.50.20 (onde 145.900.50.20 é o meu endereço IP local) e depois mudei de volta para localhost - era necessário permanecer com o Endereço IP uma vez que eu mudei para aquele uma vez


0

Eu usei:

eco exec ('whoami');

para descobrir quem está executando o script (por exemplo, nome de usuário) e, em seguida, concedeu ao usuário permissões para todo o diretório do aplicativo, como:

sudo chown -R: nome de usuário / var / www / html / myapp

Espero que isto seja útil a alguém.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.