2016-09-21 87 views
1

我正在嘗試部署我在Apache服務器上構建的Flask Web應用程序。 我在rasberry pi 3上使用rasbian(Jessie)OS。 應用程序運行完美的燒瓶內置開發Web服務器,但nomatther我做什麼我還沒有設法將它部署在APACH,這是我做了什麼:使用mod_wsgi在apach上部署燒瓶

sudo apt-get update 
sudo apt-get -y install python3 ipython3 python3-flask 
sudo apt-get -y install apache2 
sudo apt-get -y install libapache2-mod-wsgi-py3 

conf文件是:/etc/apach2/sites-available/arduinoweb.conf

<VirtualHost *> 
ServerName 10.0.0.20 

WSGIDaemonProcess arduinoweb user=pi group=pi threads=5 
WSGIScriptAlias//var/www/ArduinoWeb/arduinoweb.wsgi 

<Directory /var/www/ArduinoWeb/ArduinoWeb> 
WSGIProcessGroup arduinoweb 
WSGIApplicationGroup %{GLOBAL} 
WSGIScriptReloading On 
Require all granted 
</Directory> 

Alias /static /var/www/ArduinoWeb/ArduinoWeb/static 
<Directory /var/www/ArduinoWeb/ArduinoWeb/static/> 
Require all granted 
</Directory> 

Alias /temp /var/www/ArduinoWeb/ArduinoWeb/temp 
<Directory /var/www/ArduinoWeb/ArduinoWeb/temp/> 
Require all granted 
</Directory> 

Alias /templates /var/www/ArduinoWeb/ArduinoWeb/templates 
<Directory /var/www/ArduinoWeb/ArduinoWeb/templates/> 
Require all granted 
</Directory> 

ErrorLog ${APACHE_LOG_DIR}/error.log 
LogLevel warn 
CustomLog ${APACHE_LOG_DIR}/access.log combined 


</VirtualHost> 
~ 

在/var/www/Arduinoweb/arduinoweb.wsgi的WSGI腳本文件:

阿帕奇
import sys 

if sys.version_info[0]<3:  # require python3 
    raise Exception("Python3 required! Current (wrong) version: '%s'" % sys.version_info) 

sys.path.insert(0, '/var/www/Arduinoweb/Arduinoweb') 

from app import app as application 

錯誤日誌:

[Wed Sep 21 21:46:22.669633 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Target WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi' cannot be loaded as Python module. 
[Wed Sep 21 21:46:22.669971 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Exception occurred processing WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi'. 
[Wed Sep 21 21:46:22.670196 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] Traceback (most recent call last): 
[Wed Sep 21 21:46:22.671185 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] File "/var/www/ArduinoWeb/arduinoweb.wsgi", line 8, in <module> 
[Wed Sep 21 21:46:22.671238 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819]  from app import app as application 
[Wed Sep 21 21:46:22.671406 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] ImportError: No module named 'app' 

我不明白爲什麼找不到應用程序。

這是Python文件/var/www/Arduinoweb/Arduinoweb/app.py

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from flask import request, redirect, url_for, render_template, jsonify 
from socket import * 
from time import time 
from threading import Timer 
from datetime import datetime 
import fileinput 

app = Flask(__name__) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:[email protected]/arduinoweb' 
app.debug = True 
db = SQLAlchemy(app) 

class User(db.Model): 

    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    email = db.Column(db.String(120), unique=True) 

    def __init__(self, username, email): 
     self.username = username 
     self.email = email 
    def __repr__(self): 
     return '<user %r>' % self.username 


class Temp(db.Model): 
     __tablename__ = "Temp" 
     id = db.Column("id", db.Integer, primary_key=True) 
     Temp = db.Column("Temp", db.Integer) 
     Date = db.Column("Date", db.Date) 
     Time = db.Column("Time", db.Time) 
     DateTime = db.Column("DateTime", db.String) 

     def __init__(self, Temp, Date=None, Time=None, DateTime=None): 
       self.Temp = Temp 
       if Date is None: 
         Date = str(datetime.now()).split('.')[0] 
       self.Date = Date 
       if Time is None: 
         Time = str(datetime.now()).split('.')[0] 
       self.Time = Time 
       if DateTime is None: 
         DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1] 
       self.DateTime = DateTime 

class EC(db.Model): 
     __tablename__ = "EC" 
     id = db.Column("id", db.Integer, primary_key=True) 
     EC = db.Column("EC", db.Float) 
     Date = db.Column("Date", db.Date) 
     Time = db.Column("Time", db.Time) 
     DateTime = db.Column("DateTime", db.String) 

     def __init__(self, EC, Date=None, Time=None, DateTime=None): 
       self.EC = EC 
       if Date is None: 
         Date = str(datetime.now()).split('.')[0] 
       self.Date = Date 
       if Time is None: 
         Time = str(datetime.now()).split('.')[0] 
       self.Time = Time 
       if DateTime is None: 
         DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1] 
       self.DateTime = DateTime 

class PH(db.Model): 
     __tablename__ = "PH" 
     id = db.Column("id", db.Integer, primary_key=True) 
     PH = db.Column("PH", db.Float) 
     Date = db.Column("Date", db.Date) 
     Time = db.Column("Time", db.Time) 
     DateTime = db.Column("DateTime", db.String) 

     def __init__(self, PH, Date=None, Time=None, DateTime=None): 
       self.PH = PH 
       if Date is None: 
         Date = str(datetime.now()).split('.')[0] 
       self.Date = Date 
       if Time is None: 
         Time = str(datetime.now()).split('.')[0] 
       self.Time = Time 
       if DateTime is None: 
         DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1] 
       self.DateTime = DateTime 

class Humidity(db.Model): 
     __tablename__ = "Humidity" 
     id = db.Column("id", db.Integer, primary_key=True) 
     Humidity = db.Column("Humidity", db.Integer) 
     Date = db.Column("Date", db.Date) 
     Time = db.Column("Time", db.Time) 
     DateTime = db.Column("DateTime", db.String) 

     def __init__(self, Humidity, Date=None, Time=None, DateTime=None): 
       self.Humidity = Humidity 
       if Date is None: 
         Date = str(datetime.now()).split('.')[0] 
       self.Date = Date 
       if Time is None: 
         Time = str(datetime.now()).split('.')[0] 
       self.Time = Time 
       if DateTime is None: 
         DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1] 
       self.DateTime = DateTime 

class HumidityRoots(db.Model): 
     __tablename__ = "HumidityRoots" 
     id = db.Column("id", db.Integer, primary_key=True) 
     HumidityRoots = db.Column("HumidityRoots", db.Integer) 
     Date = db.Column("Date", db.Date) 
     Time = db.Column("Time", db.Time) 
     DateTime = db.Column("DateTime", db.String) 

     def __init__(self, HumidityRoots, Date=None, Time=None, DateTime=None): 
       self.HumidityRoots = HumidityRoots 
       if Date is None: 
         Date = str(datetime.now()).split('.')[0] 
       self.Date = Date 
       if Time is None: 
         Time = str(datetime.now()).split('.')[0] 
       self.Time = Time 
       if DateTime is None: 
         DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1] 
       self.DateTime = DateTime 


@app.route('/Sensors') 
def sensors_function(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("GETSENSORS".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 



@app.route('/OutputsState') 
def outputs_state_function(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("GETOUTPUTSSTATE".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 

@app.route('/WebModeState') 
def web_mode_state_function(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("GETWEBMODE".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 

@app.route('/PLCState') 
def plcstatefunction(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("GETPLCSTATE".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 

@app.route('/IrrigateOnOff') 
def irrigate_on_off_function(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("IRRIGATEOnOff".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 

@app.route('/SprinklersOnOff') 
def sprinklers_on_off_function(): 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto("SprinklersOnOff".encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return rec_data 

@app.route('/SetDateTime' , methods=['POST']) 
def set_date_time_function(): 
     completeAnswer = "%s:%s:%s:%s:%s:%s:%s:%s" % ("SETDATETIME", request.form.get('dOw'), request.form.get('SetDate'), request.form.get('SetMonth'), request.form.get('SetYear'), request.form.get('SetHour'), request.form.get('SetMinute'), request.form.get('SetSeconds')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetIrrigation' , methods=['POST']) 
def set_irrigation_function(): 
     completeAnswer = "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % ("SETIRRIGATION",request.form.get('SetIrrigationMode'), request.form.get('SetHumidityRangeMin'), request.form.get('SetHumidityRangeMax'), request.form.get('SetHour1'), request.form.get('SetHour1OnTime'), request.form.get('SetHour1OffTime'), request.form.get('SetHour2'), request.form.get('SetHour2OnTime'), request.form.get('SetHour2OffTime'), request.form.get('SetHour3'), request.form.get('SetHour3OnTime'), request.form.get('SetHour3OffTime'), request.form.get('SetHour4'), request.form.get('SetHour4OnTime'), request.form.get('SetHour4OffTime')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetEC' , methods=['POST']) 
def set_EC_function(): 
     completeAnswer = "%s:%s:%s:%s:%s" % ("SETEC", request.form.get('SetECRangeMin'), request.form.get('SetECRangeMax'), request.form.get('SetDoseEC'), request.form.get('SetECDelay')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetPH' , methods=['POST']) 
def set_PH_function(): 
     completeAnswer = "%s:%s:%s:%s:%s:%s" % ("SETPH", request.form.get('SetPHRangeMin'), request.form.get('SetPHRangeMax'), request.form.get('SetDosePHUp'), request.form.get('SetDosePHDown'), request.form.get('SetPHDelay')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetWaterTemp' , methods=['POST']) 
def set_water_temp_function(): 
     completeAnswer = "%s:%s:%s" % ("SETWATERTEMP", request.form.get('SetWaterTempRangeMin'), request.form.get('SetWaterTempRangeMax')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetSprinklers' , methods=['POST']) 
def set_sprinklers_function(): 
     completeAnswer = "%s:%s:%s:%s:%s" % ("SETSPRINKLERS", request.form.get('SetSprinklersBeginEndHoursBegin'), request.form.get('SetSprinklersBeginEndHoursEnd'), request.form.get('SetSprinklersOnTime'), request.form.get('SetSprinklersOffTime')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 

@app.route('/SetAlerts' , methods=['POST']) 
def set_alerts_function(): 
     completeAnswer = "%s:%s:%s:%s:%s:%s" % ("SETALERTS", request.form.get('SetIrrigationThresholdAlert'), request.form.get('ECAlertOffset'), request.form.get('PHAlertOffset'), request.form.get('ResetCounterState'), request.form.get('AlertsState')) 
     address= ('192.168.0.196', 5000) #define server IP and port 
     client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket 
     client_socket.settimeout(1) #Only wait 1 second for a response 
     client_socket.sendto(completeAnswer.encode(), address) #Send the data request 
     rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino 
     return "ok" 




@app.route('/') 
def index(): 
     return render_template('index.html') 

@app.route('/Charts') 
def charts(): 
     return render_template('charts.html') 

@app.route('/livechart') 
def live_chart(): 
     return render_template('livechart.html') 

@app.route('/TempQuery' , methods=['POST']) 
def temp_query(): 
     answerDate = request.form.get('date') 
     answerSensor = request.form.get('sensor') 
     datafile = 'temp/TempByDateDbFile.txt' 
     if answerSensor == 'Temp': 
       DbTemp = Temp.query.filter_by(Date = answerDate).all() 
       ## create the file from db 
       file = open(datafile, 'w') 
       for item in DbTemp: 
         file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Temp) + '},' + '\n') 
       file.close() 
     elif answerSensor == 'EC': 
       DbTemp = EC.query.filter_by(Date = answerDate).all() 
       ## create the file from db 
       file = open(datafile, 'w') 
       for item in DbTemp: 
         file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.EC) + '},' + '\n') 
       file.close() 
     elif answerSensor == 'PH': 
       DbTemp = PH.query.filter_by(Date = answerDate).all() 
       ## create the file from db 
       file = open(datafile, 'w') 
       for item in DbTemp: 
         file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.PH) + '},' + '\n') 
       file.close() 
     elif answerSensor == 'Humidity': 
       DbTemp = Humidity.query.filter_by(Date = answerDate).all() 
       ## create the file from db 
       file = open(datafile, 'w') 
       for item in DbTemp: 
         file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Humidity) + '},' + '\n') 
       file.close() 
     elif answerSensor == 'HumidityRoots': 
       DbTemp = HumidityRoots.query.filter_by(Date = answerDate).all() 
       ## create the file from db 
       file = open(datafile, 'w') 
       for item in DbTemp: 
         file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.HumidityRoots) + '},' + '\n') 
       file.close() 
     ##replace "-" in "," 
     f = open(datafile,'r') 
     filedata = f.read() 
     f.close() 
     newdata = filedata.replace("-",", ") 
     f = open(datafile,'w') 
     f.write(newdata) 
     f.close() 
     return 'OK' 

@app.route('/RenderTempChart' , methods=['POST' , 'GET']) 
def render_temp_chart(): 
     datafile = 'temp/TempByDateDbFile.txt' 
     with open(datafile, 'r') as myfile: 
       file = myfile.read() 
     return render_template('DbTemp.html', file = file) 

@app.route('/Control' , methods=['POST' , 'GET']) 
def control(): 
     return render_template('control.html') 
""" 
def update_data(interval): # store in DB all sensors real time data 
     Timer(interval, update_data, [interval]).start() 
     SensorsAnswer = sensors_function().split() 
     addTemp = Temp(int(SensorsAnswer[2])) 
     addEC = EC(float(SensorsAnswer[0])) 
     addPH = PH(float(SensorsAnswer[1])) 
     addHumidity = Humidity(int(SensorsAnswer[3])) 
     addHumidityRoots = HumidityRoots(int(SensorsAnswer[5])) 
     db.session.add(addTemp) 
     db.session.add(addEC) 
     db.session.add(addPH) 
     db.session.add(addHumidity) 
     db.session.add(addHumidityRoots) 
     db.session.commit() 

update_data(300) # Store data in DB every x seconds 
""" 
if __name__ == "__main__": 
     app.run() 

它不是一個簡單的像這樣的代碼(同樣的錯誤),即使工作:

from flask import Flask 

app = Flask(__name__) 

@app.route("/") 
def hello(): 
    return "Hello world!" 

if __name__ == "__main__": 
    app.run() 

我使用python 3.4.2。我沒有在虛擬環境中使用它。

的文件夾結構:

app.py/var/www/Arduinoweb/Arduinoweb/app.py arduinoweb.wsgi/var/www/Arduinoweb/arduinoweb.wsgi

我使虛擬主機arduinoweb.conf並重新啓動apach2服務。

+0

你有沒有SElinux運行? – seanmus

+0

你在你所需的目錄中有'__init __。py'嗎? – seanmus

+0

如果應用程序在簡單的燒瓶開發服務器中工作可能是一種缺少__init__.py的方式? –

回答

1

一開始,這樣的:

<Directory /var/www/ArduinoWeb/ArduinoWeb> 
WSGIProcessGroup arduinoweb 
WSGIApplicationGroup %{GLOBAL} 
WSGIScriptReloading On 
Require all granted 
</Directory> 

應該是:

<Directory /var/www/ArduinoWeb> 
WSGIProcessGroup arduinoweb 
WSGIApplicationGroup %{GLOBAL} 
Require all granted 
</Directory> 

技術上這是錯誤會導致兩個問題。

第一個是Apache甚至不應該讓你使用那個WSGI腳本,因爲它沒有權限。看起來就像你的Apache配置中的其他地方一樣,當它不應該真正存在時,它可以廣泛訪問你的文件系統。

我也放棄了重新加載選項作爲默認設置,無論如何也不需要。

第二個是WSGI腳本不會在守護進程組的上下文中運行。這意味着代碼會以嵌入模式加載,並以Apache用戶身份運行。如果您的文件的權限是隻有pi用戶可以讀取它們,那麼它將無法訪問app模塊。

SeverName作爲IP地址通常也是錯誤的。如果它正在工作,那麼它只會這樣做,因爲這是Apache配置中的第一個VirtualHost,所以當Apache無法正確命名基本虛擬主機匹配時,默認使用它。

無論如何,看看是否有幫助,否則提供運行的輸出:

ls -las /var/www/ArduinoWeb /var/www/ArduinoWeb/ArduinoWeb 

所以可以查閱一下所有權/目錄的權限/文件。

+0

嘗試你寫的,同樣的錯誤,我檢查了所有權/權限,一切都很好 –

+0

所以你假設你明白什麼所有權/許可是正確的? :-)希望看到他們驗證。您是否曾經檢查過SELinux是否被其他人詢問啓用?通常,如果在'/ var/www''下,即使啓用了SELinux,Apache也不應該訪問它。 –

+0

4 drwxrwxrwx 6 pi pi 4096 Sep 24 11:36。 4 drwxrwxrwx 3 pi pi 4096 Sep 24 11:04 .. 4 -rwxrwxrwx 1 pi pi 148 Sep 21 20:43 app2.py 16 -rwxrwxrwx 1 pi pi 15405 Sep 24 11:36 app.py 4 drwxr- XR-×2 WWW的數據WWW的數據4096年09月24 11:04 __pycache__ 4 drwxrwxrwx 4 PI PI 4096 09月10 19:18靜態 4 drwxrwxrwx 2 PI PI 4096 09月10 19:18臨時 4 drwxrwxrwx 2 PI PI 4096 9月10日19:18模板 –

1

感謝您的幫助..最終它似乎只是在wsgi腳本路徑中輸入錯誤:「/ var/www/ArduinoWeb/ArduinoWeb」而不是「/ var/www/Arduinoweb/Arduinoweb」。

現在它似乎工作正常。謝謝!!