我正在基于sqlite3和python在raspberry pi上开发一个小项目。其中一个脚本从传感器读取数据并将其写入数据库(sensor_update.py),另一个(cgi脚本,hello.py)读取数据库中的最后一个条目并将其打印在网站上。 问题是脚本无法正确地从数据库写入和读取。我将数据库和脚本的所有权设置为www-data,但是当我尝试执行数据库写入脚本时,我收到以下错误:
Traceback (most recent call last):
File "sensor_update.py", line 35, in <module>
log_temperature(temp)
File "sensor_update.py", line 15, in log_temperature
curs.execute("INSERT INTO temps values(datetime('now'), (?))", (temp,))
sqlite3.OperationalError: attempt to write a readonly database
我已经知道这很可能意味着权限不对。但是ls -l给出的输出应该表明我做的一切都是正确的:
pi@raspberrypi:/usr/lib/cgi-bin $ ls -l
total 20
-rwxr-xr-x 1 www-data www-data 744 Jan 16 20:54 hello.py
-rwxr-xr-x 1 www-data www-data 475 Jan 16 20:40 hello.py.backup
-rwxr-xr-x 1 www-data www-data 163 Jan 3 22:40 hello.py.save
-rwxr-xr-x 1 www-data www-data 197 Jan 3 22:40 hello.py.save.1
-rwxr-xr-x 1 www-data www-data 698 Jan 16 21:11 sensor_update.py
pi@raspberrypi:/var/www $ ls -l
total 12
drwxr-xr-x 2 root root 4096 Jan 11 08:31 html
-rwxr-xr-x 1 www-data www-data 8192 Jan 16 21:11 log.db
此外,cron作业似乎不适用于sensor_update.py脚本。当命令以sudo开头时,两个程序都会产生预期的输出 Sensor_update.py代码:
#!/usr/bin/env python
import Adafruit_BMP.BMP085 as BMP085
import os
import datetime
import sqlite3
dbname = '/var/www/log.db'
# store the temperature in the database
def log_temperature(temp):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
temp = str(temp)
curs.execute("INSERT INTO temps values(datetime('now'), (?))", (temp,))
# commit the changes
conn.commit()
conn.close()
def display_data():
conn=sqlite3.connect(dbname)
curs=conn.cursor()
for row in curs.execute("SELECT * FROM temps"):
print str(row[0])+" "+str(row[1])
conn.close()
sensor = BMP085.BMP085()
temp=sensor.read_temperature()
log_temperature(temp)
display_data()
hello.py代码(cgi脚本):
#!/usr/bin/env python
import Adafruit_BMP.BMP085 as BMP085
import cgi
import cgitb
import sqlite3
cgitb.enable()
dbname = '/var/www/log.db'
def get_data():
conn=sqlite3.connect(dbname)
curs=conn.cursor()
curs.execute("SELECT * FROM temps ORDER BY timestamp DESC LIMIT 1")
result = curs.fetchone()
return result
if __name__ == "__main__":
result=get_data()
print result
一块apache2日志:
[Tue Jan 16 21:55:10.812282 2018] [cgi:error] [pid 964] [client ---:52835] Premature end of script headers: hello.py
答案 0 :(得分:0)
SQLite需要在与数据库相同的目录中创建“journal”文件以支持ACID事务,因此它需要对数据库所在目录以及数据库本身的写访问权。
/var/www
可能归root
所有,而不是www-data
(您没有使用ls -al
,但看到html
目录归{ {1}},我假设www-data
也是如此。 SQLite无法创建日志,因此它以只读模式打开以防止可能的损坏。
更改/var/www
的权限或将数据库放在打开数据库的进程具有写访问权限的文件夹中。