Nginx 基础杂记

Nginx 基础杂记

实践是最好的复习方式,书中所学的东西很快的投入应用。得到的远超过理论本身

再硅谷百年史中有一句话,大意是这样:

硅谷并不一定是新技术产生的地方,但是新的技术得以在这片土地得到快速的传播,和应用,技术的本身得到快速迭代,展现出了无尽的生命力。

上周,一个基础的Nginx入门, 这周很多地方都有用上都能用上。幸哉

正文

CGI的配置

这部分,简单的记录一个的基于 Nginx 的一个 CGI 服务器的配置过程。

Nginx 的编译安装

这部分在 Linux 的环境下,拥有了一个 GNU 的完整编译链的话,可以很容易的直接

1
./configure

使用 AUTOCONF 和 AUTOMAKE 直接生成和当前系统环境下的 配置的 Makefile 。

1
2
make 
make install

这两个命令,直接对 Nginx 进行编译安装。得到的文件在

1
2
/usr/local/nginx/
$nginx_root/conf # 这个里面是它的配置文件所在的地方

uWSGI 编译安装

uWSGI 官方提供了一键安装的操作,用起来oneClick :

1
curl http://uwsgi.it/install | bash -s default /tmp/uwsgi

后面是编译输出的路径。这样一个回车键就可以

/tmp/uwsgi 下面的就是我们编译的bin文件

Nginx CGI 的配置

Nginx 可以根据不同的配置文件,以进程为单位启动多个。

1
./nginx [-t # 检查配置文件] [-c 指定配置文件路径]

这里需要注意的是 ,nginx 的配置文件默认在 /usr/local/conf。所以这里,我们可以把配置文件夹拷贝到当前目录,之后使用 c 参数进行指定就好


下面这部分是 Nginx 的配置,直接在预设的幕布就配置中进行修改就好,这里贴出配置文件:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#user  nobody;
worker_processes 1;

error_log logs/error.log; # 这里可以配置 log 所记录的日志级别
#error_log logs/error.log notice;
#error_log logs/error.log info;

pid logs/nginx.pid; # Pid 文件,用于保存当前服务进程的PID

events {
worker_connections 1024;
}

http {
include mime.types; # 多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions)
default_type application/octet-stream; # 这里设置类型

#access_log logs/access.log main; # 访问日志

sendfile on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;

server { # 一个虚拟服务器的定义
listen 8000;
server_name localhost;
charset utf-8; # 设置页面编码
#access_log logs/host.access.log main; # 当前虚拟服务器的访问日志

location / { # 根路由配置
root html; # 注意,如果在编译的时候没有指定 root
# 这里的 html 是相对路径在 /usr/local/nginx/html/
index index.html index.htm;
}

# error_page 404 /404.html;
# redirect server error pages to the static page /50x.html

error_page 500 502 503 504 /50x.html; # 定向错误码,到路由
location = /50x.html { # 精确匹配路由
root html; # 在 /html 里面找到 50x.html (alias 和 root)
}

location /cgi-bin { # 这里就是一个 CGI 的路由配置了
include uwsgi_params; # 引入 uwsgi 的所有可用参数
uwsgi_modifier1 9;
uwsgi_pass 127.0.0.1:9000; # CGI 请求传入本地监听 的9000 端口
# 交给 uWSGI 执行
}

}

可见,在Nginx 里的主要的配置内容,是直接 使用 uWSGI 监听的端口, 进行命令传递,至此Nginx 的配置部分就好了,这里的重点,就是在与对应 路由的配置,

uWSGI 配置

在 uWSGI 直接使用 ./ 便可以将服务,运行起来。不过会出一堆挺吓人的警告。具体是其没有进行正确的配置。启动命令:

1
sudo -u root ./uwsgi ./uwsgi.ini

这里有一点是:uWSGI 服务,用于相应 WEB 请求,所以安全考虑,这里应该有严格的权限控制。使用

sudo -u nobody 指定用户来启动 CGI 服务,这样可以控制CGI 脚本的权限,避免出现风险。不过这里由于需要对部分文件进行读写, 所以图方便使用了root。

uWSGI 的配置文件如下

1
2
3
4
5
6
7
8
9
10
11
[uwsgi]
processes = 4 # 指定worker数,是uWSGI 的worker
master = true # 这个配置重要,启用 master_process 不然将会工作在单线程模式
# 而且,只可以运行在前台
socket = 127.0.0.1:9000 # 连接类型,以及监听端口
chdir = /data/_dir/nginx/cgi-bin # CGI 脚本们的路径
cgi=/cgi-bin=/data/_dir/nginx/cgi-bin
cgi-helper=.py=python # 对不同的文件类型指定不同的解释器

daemonize = /data/_dir/nginx/uwsgi/uwsgi.log # 后台运行的日志
pidfile = /data/_dir/nginx/uwsgi/uwsgi.pid # PID 文件

对上面的配置文件做了简单的解释,有了这样的配置文件之后,一个 基于 Nginx 的服务就已经搭建起来了。

CGI 脚本

CGI 脚本们存在于 cgi-bin 这个目录下,如果有 web 对CGI 的路由进行了访问,那么这个http 请求将会被下发到 CGI 服务(uwsgi) 之后,它创建解释器进程,对我们的 脚本进行执行,并最终接收返回结果,传递回前端。

这里列出几个简单的脚本

  • shell

    1
    2
    3
    4
    #!/bin/bash
    echo "Content-Type:text/html"
    echo "" # 空行分隔
    echo "hello world!"
  • Python

    1
    2
    3
    4
    #!/usr/bin/env python
    print("Content-type: text/html\n\n")
    print() # 空行分隔
    print("<h1>Hello World</h1>")

又是教科书式的 helloworld。 这里我们就直接使用输出函数,对html 内容进行输入,最终他将返回到前端。


带上参数

对于 CGI 请求,当然是可以带上了参数,这里只 说 GET 这种请求方式

使用 cgi 模块,可以很容易的提取参数

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# CGI处理模块
import cgi, cgitb
# 创建 FieldStorage 的实例化
form = cgi.FieldStorage()
# 获取数据
context = form.getvalue('keyword')

print "Content-type: text/html\n\n"
print() # 空行分隔
print("<h1>Hello World</h1>")
print("<h2>context</h2>")

小结

Q: Uwsgi 只能前台运行的问题

在配置中 没有指定 Master_process 所以工作在单线程调试模式,./uwsgi 的过程中,发现其只能在前台以单进程的模式运行。在中发现是配置文件中,没有指定Master_process 的数量

所以导致,其是在单进程情况下运行在前台,多半这个为调试模式下的状态,单进程


Q: uwsgi 错误invalid request block size

这个其实不算问题,是自己在调试过程中发现的。使用:

1
curl "127.0.0.1:9000" -V

因为 curl 是发送的 http 的请求,uwsgi 默认绑定的是 socket。

实际上这个和 UWSGI 的绑定的协议有关。在测试时请求的 uwsgi.ini 配置文件里面内容把socket=:8000替换成http=:8000,可以切换 所绑定的协议


Q: PID 文件使用

在 nginx 和 Uwsgi 的配置文件中,添加 PID 的参数,可以是的其在运行的时候生成 PID 文件

这样可以快速方便的给相关的进程发信号,进行重启或者是终止

1
Kill -HUP `cat ./xxx.pid`

一个简单的下载页面

这里是 Nginx 的另一组配置文件,实现的是开放一个页面可以进行文件俩蓝和下载

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
27
28
29
30
31
32
33
34
35
36
37
38
39
http {
include mime.types; # 多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions)
default_type application/octet-stream; # 这里设置类型
#access_log logs/access.log main; # 访问日志
sendfile on;
keepalive_timeout 65;
#gzip on;

server {
listen 80;
charset utf-8;

location / {
root html;
index index.html index.htm;
}

location /confs { # 路由
alias /data/_dir/nginx/www/mon_conf;
autoindex on; #开启索引功能
autoindex_localtime on; # 显示本机时间而非 GMT 时间
auth_basic "Enter your name and password";
# 指定验证文件
auth_basic_user_file /data/_dir/nginx/www/mon_conf/.htpasswd;
index index.html index.htm;
}

location /query {
rewrite ^ /cgi-bin/query.py last; # 这里的路由重写
}

location /cgi-bin {
internal; # 内部访问,外部访问时 404
include uwsgi_params;
uwsgi_modifier1 9;
uwsgi_pass 127.0.0.1:9000;
}
}
}

页面的登入认证

由于这里可以直接进行文件访问,所以添加了页面的登陆验证

1
2
3
auth_basic "Enter your name and password";
# 指定验证文件
auth_basic_user_file /data/_dir/nginx/www/mon_conf/.htpasswd;

这里简单的测试, admin:1234 (MD5) 得到密文

admin:$apr1$PqhZgBDT$pAwEYVAKKXdHIXxqvbEYU/


URL 的重写

URL 的重写,这里实现的是隐式的重定向。就是我们的页面发生跳转,但是URL 不发生变化。

这里使用 nginx 的 rewrite 模块实现相关功能。具体配置如下:

1
2
3
4
5
6
7
8
9
10
location /query {	
rewrite ^ /cgi-bin/query.py last; # 这里的路由重写
}

location /cgi-bin {
internal; # 内部访问,外部访问时 404
include uwsgi_params;
uwsgi_modifier1 9;
uwsgi_pass 127.0.0.1:9000;
}

下面的CGI 部分和之前是没有什么区别,不过值得注意的是 , 这里的internal 的修饰。说明这刚路由路径,不可以从外部进行访问。

所以在 这里进行了重定向 rewrite ^ /cgi-bin/query.py last; 对 query 进行重写,相对的就是对重写后的地方进行访问。

rewrite 的标识

不写last和break - 那么流程就是依次执行这些rewrite

  1. rewrite break - url重写后,直接使用当前资源,不再执行location里余下的语句,完成本次请求,地址栏url不变
  2. rewrite last - url重写后,马上发起一个新的请求,再次进入server块,重试location匹配,超过10次匹配不到报500错误,地址栏url不变
  3. rewrite redirect – 返回302临时重定向,地址栏显示重定向后的url,爬虫不会更新url(因为是临时)
  4. rewrite permanent – 返回301永久重定向, 地址栏显示重定向后的url,爬虫更新url

一些总结

502 和 504

  • 502 Bad Gateway
    504 Gateway time-out
    503 Service Unavailable

正如其 英译过来,

  • Bad Geteway 一般发生在当前的HTTP请求,在进行 CGI 分发的时候,发生错误,比如 :9000 端口连接失败。或者 CGI 服务没有启动
    Gateway time-out Nginx 在进行任务分发之后,超过预定时间,没有得到 CGI 服务器的 echo,可能是 CGI 服务的进程阻塞
    Service Unavailable 由 CGI 服务直接返回,无法处理任务的请求,一般是流量太大导致的问题

参考内容

-------------本文结束感谢您的阅读-------------
Thanks anyway!