经过近两天的努力,我终于解决了这个问题。我希望这个解决方案能够帮助到其他遇到类似问题的Flask/uwsgi用户。
我面临了两个主要问题。
1)找出守护进程问题的最佳方法显然是使用日志文件和更清晰的结构。
sudo vim /etc/init/uwsgi.conf
将守护脚本更改为以下内容:
# file: /etc/init/uwsgi.conf
description "uWSGI server"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /home/ubuntu/uwsgi-1.9.12/uwsgi -c /myproject/uwsgi.ini
vim /myproject/uwsgi.ini
[uwsgi]
socket = /tmp/uwsgi.sock
master = true
enable-threads = true
processes = 5
chdir= /myproject/F11/Engineering
module=F11:app
virtualenv = /myproject/myproject-env/
uid = www-data
gid = www-data
logto = /myproject/error.log
这是更清洁的设置守护进程的方式。请注意最后一行如何设置日志文件。最初,我将日志文件设置为/var/log/uwsgi/error.log
。经过大量的尝试和调试,我意识到守护进程以www-data
身份运行,因此无法访问/var/log/uwsgi/error.log
,因为该文件是由root:root
拥有的。这使得uwsgi默默地失败了。
我发现只需将日志文件指向我的/myproject
,在那里守护进程可以保证作为www-data
拥有访问权限。还要记得将整个项目都授予www-data
访问权限,否则守护进程将因为内部服务器错误消息
而失败。-->
sudo chown www-data:www-data -R /myproject/
重新启动uwsgi守护进程:
sudo service uwsgi restart
2) 现在你有三个日志文件需要留意:
tail -f /var/log/upstart/uwsgi.log
--> 显示守护进程启动时的问题
tail -f /var/log/nginx/error.log
--> 显示访问 wsgi 时权限问题,通常是因为 /tmp/uwsgi.sock
文件属于 root
而不是 www-data
。在这种情况下,只需删除 sock 文件 sudo rm /tmp/uwsgi.sock
tail -f /myproject/error.log
--> 显示应用程序中 uwsgi 抛出的错误
这些日志文件的组合帮助我发现我的 Flask 应用程序中还存在 Flask-Babel 的错误导入方式,这种方式会回退到系统的区域设置来确定日期时间格式。
File "/myproject/F11/Engineering/f11_app/templates/show_records.html", line 25, in block "body"
<td>{{ record.record_date|format_date }}</td>
File "./f11_app/filters.py", line 7, in format_date
day = babel_dates.format_date(value, "EE")
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 459, in format_date
return pattern.apply(date, locale)
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 702, in apply
return self % DateTimeFormat(datetime, locale)
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 699, in __mod__
return self.format % other
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 734, in __getitem__
return self.format_weekday(char, num)
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 821, in format_weekday
return get_day_names(width, context, self.locale)[weekday]
File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 69, in get_day_names
return Locale.parse(locale).days[context][width]
AttributeError: 'NoneType' object has no attribute 'days'
这是我使用Flask过滤器的方式:
import babel.dates as babel_dates
@app.template_filter('format_date')
def format_date(value):
day = babel_dates.format_date(value, "EE")
return '{0} {1}'.format(day.upper(), affix(value.day))
最奇怪的是,这段代码在开发环境中完美运行(!)。即使从命令行以root进程运行uwsgi也可以正常工作。但是当www-data守护程序运行时就失败了。这一定与如何设置区域设置有关,Flask-Babel正在尝试回退。
当我像这样更改导入时,最终在守护进程中也能正常工作:
from flask.ext.babel import format_date
@app.template_filter('format_date1')
def format_date1(value):
day = format_date(value, "EE")
return '{0} {1}'.format(day.upper(), affix(value.day))
因此,在使用Eclipse / Aptana Studio尝试为代码中的类选择正确的命名空间时要小心。否则可能会变得非常糟糕。
自2天前以来,它已经在亚马逊Ec2(Ubuntu 12.04)上完美地作为uwsgi守护进程工作。希望这种经验可以帮助同样是Python开发人员的同行。