The value of knowledge lies not in possession, but in share.

0%

云服务器部署Python Web环境(Nginx+Spawn-fcgi+web.py)

Web.py是一款轻量级的python web开发框架,其简单、高效、学习门槛低,特别适合作为Python Web开发的入门框架,并可以为云服务器中相关应用提供便捷接口。

本教程在云服务器上安装了WSGI (Web Server Gateway Interface )接口 及 Http Sever (如 Apache、Nginx等)。

Python Web环境 -> Web.py + Nginx + Spawn-fcgi

注:本教程在Python3.6版本运行,安装可参考:Python3.x的安装及相关设置

更新了:云服务器部署Python Web环境(Flask+Nginx+Gunicorn+Supervisor),后面的工作将主要会基于Flask进行开展。

安装Web.py

Ubuntu下可使用下述命令:

1
sudo pip install web.py

通用安装方法:

  1. 下载 地址 http://webpy.org/static/web.py-0.37.tar.gz

  2. 随便解压到一个路径(安装后就不需要了)

  3. 安装命令

    1
    python setup.py install
  4. 本地测试web.py,新建hello.py内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    # 导入web.py
    import web

    # 添加URL:“/”(即首页)通过index类进行处理
    urls = (
    '/', 'index'
    )

    # 创建一个上方声明的URL列表对应的application,application会在这个文件的全局命名空间中查找对应类
    app = web.application(urls, globals())

    # 创建usls中映射的类
    class index:
    def GET(self):
    return "Hello, world!"

    if __name__ == "__main__":
    app.run() # 启动应用

    运行该代码:

    1
    python hello.py

    打开浏览器,访问xx.xx.xx.xx:8080(其中xx.xx.xx.xx更换为云服务器的公网IP),显示结果为:

    Hello, World!

    注:默认端口为8080 可以通过python hello.py 8000来设定启动端口。

安装Nginx

  1. Ubuntu下可使用下述命令:

    1
    sudo apt-get install nginx

    安装好的文件位置:

    /usr/sbin/nginx:主程序

    /etc/nginx:存放配置文件

    /usr/share/nginx:存放静态文件

    /var/log/nginx:存放日志

    其实从上面的根目录文件夹可以知道,Linux系统的配置文件一般放在/etc,日志一般放在/var/log,运行的程序一般放在/usr/sbin或者/usr/bin。

    如果要更清楚Nginx的具体配置项,可以打开/etc/nginx/nginx.conf

    对于其他Linux系统可参照官网链接:https://www.nginx.com/resources/wiki/start/topics/tutorials/install/

  2. 启动Nginx:

    1
    2
    # 启动Nginx
    sudo /etc/init.d/nginx start

    其他相关命令:

    1
    2
    3
    4
    # 关闭Nginx
    sudo /etc/init.d/nginx stop
    # 重启Nginx
    sudo /etc/init.d/nginx restart
  3. 访问xx.xx.xx.xx(其中xx.xx.xx.xx更换为云服务器的公网IP),显示结果为:

    Welcome to nginx!

    If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

    For online documentation and support please refer to nginx.org.
    Commercial support is available at nginx.com.

    Thank you for using nginx.

安装Spawn-fcgi 及 Flup

  1. 安装Spawn-fcgi

    1
    sudo apt-get install spawn-fcgi
  2. 安装Flup

    1
    pip install flup
  3. 配置 nginx.conf 支持 fastcgi

    1
    2
    # 编辑配置文件
    vim /etc/nginx/nginx.conf

    http内如下之处:

    1
    2
    3
    4
    http
    {
    server{}
    }

    添加以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    server{
    listen 80;
    server_name xx.xx.xx.xx; # 其中xx.xx.xx.xx更换为云服务器的公网IP
    index index.html index.php;

    location /hello {
    root /opt/webpy-test; # 应用webpy-test所在的目录
    include fastcgi_params; # 包含默认的fastcgi参数
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9001; # 把请求通过fastcgi传送给本机的9001端口
    }

    location /static/ { # 配置静态文件的访问
    if (-f $request_filename) { # 如果请求文件名是一个文件
    rewrite ^/static/(.*)$ /static/$1 break; # 直接跳转到对应的资源,中断fastcgi的传输
    }
    }
    #location /helloword {
    # root /opt/webpy-test2; # 应用webpy-test2所在的目录
    # include fastcgi_params; # 包含默认的fastcgi参数
    # fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
    # fastcgi_param PATH_INFO $fastcgi_script_name;
    # fastcgi_pass 127.0.0.1:9002; # 把请求通过fastcgi传送给本机的9002端口
    #}
    }

    特别注意:【此处尤为重要,一开始始终无法正常显示,我花费了一下午的时间才解决相关问题】

    • 在云服务器控制界面添加80端口;
    • 80端口添加至防火墙:sudo ufw allow 80
    • 在云服务器控制界面添加9001端口,并将其添加至防火墙;
    • 其他同上……

修改源代码

如果想要使用Nginx,则必须添加以下代码:

web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)

  1. 新建程序index.py为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    import web

    urls = ("/.*", "hello")
    app = web.application(urls, globals())

    class hello:
    def GET(self):
    return 'Hello, world!'

    if __name__ == "__main__":
    web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr) # Neew added
    app.run()
  2. 设置代码可执行权限:

    1
    chmod +x index.py

启动应用

  1. 启动一个Spawn-fcgi进程:

    1
    2
    3
    # 启动进程
    spawn-fcgi -d /path/to/www -f /path/to/www/index.py -a 127.0.0.1 -p 9001
    # 我的是:spawn-fcgi -d /opt/webpy-test -f /opt/webpy-test/index.py -a 127.0.0.1 -p 9001
    1
    2
    3
    # 关闭进程
    kill `pgrep -f "python /path/to/www/index.py"`
    # 我的是:kill `pgrep -f "python /opt/webpy-test/index.py"`

    其中/path/to/www为程序所在路径。

    -f 指定调用FastCGI的web文件,web程序的入口文件,即code.py文件
    -d 指定web程序的主目录,即code.py所在的目录
    -a 绑定到地址 addr
    -p 绑定到端口 port
    -F 指定产生的 FastCGI 的进程数
    -P 指定产生的进程的 PID 文件路径
    -u 和 -g FastCGI 使用什么身份运行

    注:可以随意填写地址和端口信息,但是一定需要和Nginx配置文件相匹配。

  2. 启动Nginx

    1
    2
    # 启动Nginx
    sudo /etc/init.d/nginx start
  3. 查看9001端口是否存在

    1
    netstat -ano |grep 9001

    若存在则显示:

    tcp 0 0 127.0.0.1:9001 0.0.0.0:* LISTEN off (0.00/0/0)

  4. 访问xx.xx.xx.xx/hello(其中xx.xx.xx.xx云服务器的公网IP),显示结果为:

    Hello, world!

Debug

  1. 运行python hello.py yourip:8080

    报错socket.error: No socket could be created

    该情况往往是因为端口被占用,是因为我之前配置Java Web环境占用了8080端口。

    解决方法:

    1)关闭相应程序,释放8080端口

    2)在云服务器开放新的端口,供web.py使用

  2. 运行spawn-fcgi -d /opt/webpy-test -f /opt/webpy-test/index.py -a 127.0.0.1 -p 9001

    提示spawn-fcgi: child exited with: 126

    因为index.py脚本缺少执行权限

    解决办法:

    通过chmod +x index.py添加执行权限。

  3. 运行spawn-fcgi -d /opt/webpy-test -f /opt/webpy-test/index.py -a 127.0.0.1 -p 9001

    提示spawn-fcgi: child exited with: 2

    解决办法:

    index.py的开头中添加#!/usr/bin/env python

  4. 运行spawn-fcgi -d /opt/webpy-test -f /opt/webpy-test/index.py -a 127.0.0.1 -p 9001

    提示spawn-fcgi: child exited with: 1

    应该是index.py脚本有错误

    解决办法:

    先对该脚本进行debug。

  5. 启动Nginx时

    1
    2
    3
    # 报错
    [....] Restarting nginx (via systemctl): nginx.serviceJob for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
    failed!

    通过执行systemctl status nginx.service提示:

    1
    2
    Apr 01 19:12:38 iZuf636nqxmkad2s6umlm3Z nginx[15377]: nginx: [emerg] "server" directive is not allowed here in /etc/nginx/nginx.conf
    Apr 01 19:12:38 iZuf636nqxmkad2s6umlm3Z nginx[15377]: nginx: configuration file /etc/nginx/nginx.conf test failed

    解决方法:

    一般是修改nginx.conf时出了问题,请严格参照 上文中的3.3

  6. 运行时报错ImportError: No module named _dummy_thread

    基本确定是python2.7中没有_thread模块的原因,推荐安装Python3.6。

  7. pip3 安装web.py报错

    通过下述命令进行安装:

    1
    pip3 install web.py==0.40.dev0

参考文献

  1. Webpy + Nginx with FastCGI搭建Web.py
  2. nginx[+spawn-fcgi]+flup+webpy服务搭建

🍭支持一根棒棒糖吧!