刘泉皓

没有最强的法术,只有最强的法师。

nginx学习(2)——小试一把

29 May 2018 » memory

在上一篇博客,我们已经拿到了编译好的nginx程序,并放到了一个单独的目录,现在可以开始玩一下了。

首先先看看它的帮助:

liuxu:test$ pwd
/home/liuxu/learn/nginx/test
liuxu:test$ ls -l
total 4616
-rwxr-xr-x 1 liuxu liuxu 4726472 5月  28 15:59 nginx
liuxu:test$ ./nginx --help
nginx: invalid option: "-"
liuxu:test$ ./nginx -h
nginx version: nginx/1.14.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]
Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/nginx/)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

意思很清楚,-?-h显示帮助,-v显示版本,-V显示版本和配置选项,-t测试配置文件,-T测试并打印出配置文件,-q无错误显示的方式测试文件,-s发送个nginx主进程一个信号,-p设置工作目录,-c设置配置文件,-g设置全局变量。

好了,那我就直接执行nginx看看是啥情况:

liuxu:test$ ./nginx 
nginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (2: No such file or directory)
2018/05/29 10:21:35 [emerg] 24851#0: open() "/usr/local/nginx/conf/nginx.conf" failed (2: No such file or directory)

噢吼,报错了,说无法打开/usr/local/nginx/logs/error.log/usr/local/nginx/conf/nginx.conf,当然无法打开,根本就没那两个文件。第一个文件是nginx错误日志,第二个是nginx配置文件,看来它们两个是nginx默认必须需要的文件。

大家应该还记得,前面我们编译nginx成功时最后的输出,nginx的默认配置相关信息:

Configuration summary
  + using PCRE library: ../pcre-8.41
  + OpenSSL library is not used
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

nginx的默认配置目录(工作目录)是“nginx configuration prefix: "/usr/local/nginx/conf”,默认配置文件是“nginx configuration file: "/usr/local/nginx/conf/nginx.conf"”,默认错误日志是“nginx error log file: "/usr/local/nginx/logs/error.log"”。

为了对系统做最小化改变,我喜欢将nginx所有的东西都放在nginx程序当前目录test中,所以我用nginx带上-p来执行一下。

liuxu:test$ ./nginx -p .
nginx: [alert] could not open error log file: open() "./logs/error.log" failed (2: No such file or directory)
2018/05/29 10:24:39 [emerg] 24987#0: open() "./conf/nginx.conf" failed (2: No such file or directory)

错误很相似,.这个点的意思是当前目录,-p .就是设置nginx的工作目录为当前目录。这里nginx已经在当前目录找那两个文件了,那我就新建那两个文件吧。

liuxu:test$ mkdir logs
liuxu:test$ touch logs/error.log
liuxu:test$ mkdir conf
liuxu:test$ touch conf/nginx.conf
liuxu:test$ pwd
/home/liuxu/learn/nginx/test
liuxu:test$ tree
.
├── conf
│   └── nginx.conf
├── logs
│   └── error.log
└── nginx

2 directories, 3 files

liuxu:test$ ./nginx -p .
nginx: [emerg] no "events" section in configuration

哈哈,之前那个错误没有了,不过有了新的错误,好吧。。这个错误意思是在配置文件里没有找到events相关配置,看来我们的./conf/nginx.conf里面需要有events相关的配置。怎么配置呢,一般这个时候我们应该去看文档了,里面找了events配置,好了,我们来配置一下。

liuxu:test$ cat ./conf/nginx.conf
events{
}

这里我配置了一个空的events配置,然后启动一下看看:

liuxu:test$ ./nginx -p .
liuxu:test$ ps aux | grep nginx
liuxu    25913  0.0  0.0  14156   248 ?        Ss   10:39   0:00 nginx: master process ./nginx -p .
liuxu    25914  0.0  0.0  14304  1244 ?        S    10:39   0:00 nginx: worker process
liuxu    25917  0.0  0.0  21536  1016 pts/0    S+   10:39   0:00 grep --color=auto nginx

哈哈,启动成功了,可以看见2个nginx进程,最下面一个是grep的进程,跟nginx无关。看看第一个nginx:master是nginx主进程,第二个nginx:worker是子进程,也是工作进程。这里就该讲讲nginx的工作方式了。

nginx has one master process and several worker processes. The main purpose of the master process is to read and evaluate configuration, and maintain worker processes. Worker processes do actual processing of requests. nginx employs event-based model and OS-dependent mechanisms to efficiently distribute requests among worker processes. The number of worker processes is defined in the configuration file and may be fixed for a given configuration or automatically adjusted to the number of available CPU cores (see worker_processes).

nginx工作方式为主从模式,就像前面ps输出,一个master主进程,一个worker子进程,默认什么都不配置就是这两个进程。主进程就是./nginx后启动的进程,它会读取检测配置文件,设置好所有需要的环境,然后新建worker子进程,最后一直监听信号。我们可以用./nginx -s xxx发送信号给nginx主进程,nginx主进程接收到信号后,可以重新读取配置文件、重启子进程、关闭所有进程这些操作。worker子进程是真正的工作进程,用来接收http等请求的,也会接收master主进程的信号。

既然这样,我们来看看nginx是不是这么监听的:

liuxu:test$ ps aux | grep nginx
liuxu    25913  0.0  0.0  14156  1836 ?        Ss   10:39   0:00 nginx: master process ./nginx -p .
liuxu    26867  0.0  0.0  14528  1500 ?        S    10:59   0:00 nginx: worker process
liuxu    27217  0.0  0.0  21536  1060 pts/0    S+   11:07   0:00 grep --color=auto nginx
liuxu:test$ ss -anp | head -n1
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
liuxu:test$ ss -anp | grep nginx | pt-align
u_str ESTAB 0 0 * 2489865 * 2489866 users:(("nginx",pid=25913,fd=4))
u_str ESTAB 0 0 * 2489866 * 2489865 users:(("nginx",pid=26867,fd=7),("nginx",pid=25913,fd=7))

看看,master主进程的pid是25913,work子进程的pid是26867,从后面ss的输出来看,第一行是master,第二行是worker,第二行的进程信息中,指明父进程pid(ppid:parent pid)是25913。但是发现worker根本没有监听任何端口,这是因为我们配置文件里面根本没有任何配置监听端口相关信息。好了,那么我们开始配置了监听一下http看看。

一样,我们去看看文档,文档开头是这篇文档的目录,既然我们显示是需要配置了启动一个http,那么就先看看nginx配置文件怎么配置吧:

Configuration File’s Structure nginx consists of modules which are controlled by directives specified in the configuration file. Directives are divided into simple directives and block directives. A simple directive consists of the name and parameters separated by spaces and ends with a semicolon (;). A block directive has the same structure as a simple directive, but instead of the semicolon it ends with a set of additional instructions surrounded by braces ({ and }). If a block directive can have other directives inside braces, it is called a context (examples: events, http, server, and location). Directives placed in the configuration file outside of any contexts are considered to be in the main context. The events and http directives reside in the main context, server in http, and location in server. The rest of a line after the # sign is considered a comment.

nginx配置分普通配置和block配置,普通配置就是简单的一行,用“;”分号结束。block配置用大括号括起来,就像刚才的events一样,它厘米还可以包含其他普通配置和block配置,一层包一层。如果一个配置不在任何block里面,那么它就是全局配置,它会作用到所有block里面,如果block里配置了和全局配置一模一样的配置,那么以block里面的配置为标准。当然,配置并不是可以乱配置的,有的配置只能配置到固定的地方,例如有的配置只能放在前面的events{}里面。

下面我们就配置一个简单的http配置吧。

liuxu:test$ cat ./conf/nginx.conf
events{
}

http {
    server {
        location / {
            root html;
        }
    }
}

看看这个配置,前面的events不变,新添加了一个http配置,这个配置的意思是使用http模块,这样我们就可以对nginx做http请求了。http里面有一个server配置,它的意思是配置一台服务器,一个http下面可以有很多server,就可以实现一个nginx进程下开多个网站。server里面有一个location配置,这个意思就是,在这个服务器里,配置一个网站链接导航,当有人访问这个链接的时候,执行这个导航内部的命令。这里配置的是location /,它的意思是访问网站根域名,例如https://www.liuquanhao.com/,就会执行它的内部命令。这里需要说一下,如果你访问https://www.liuquanhao.com,浏览器会自动不全域名为https://www.liuquanhao.com/,后面多了一个/,就会访问网站的根目录。这里nginx里就配置了一个/,表示网站根目录。然后location里面是root html,意思是在当前目录找一个html目录,然后根据“https://www.liuquanhao.com/xxx”后面的xxx找到相对应的文件,例如如果访问https://www.liuquanhao.com/test.html,就会在当前html目录里找test.html,如果找到了就直接返回,如果没找到就返回404错误。

那么我们就来新建目录吧:

liuxu:test$ mkdir html
liuxu:test$ echo "www.liuquanhao.com" > html/test.html
liuxu:test$ tree
.
├── client_body_temp
├── conf
│   └── nginx.conf
├── fastcgi_temp
├── html
│   └── test.html
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── nginx
├── proxy_temp
├── scgi_temp
└── uwsgi_temp

8 directories, 6 files
liuxu:test$ cat html/test.html
www.liuquanhao.com

看看,在nginx统计目录新建了一个html目录,里面有一个test.html,内容是“www.liuquanhao.com“。我们还发现有其他东西,不是我们自己建立的目录。第一个client_body_temp是用来存放请求里携带的临时文件。fastcgi_temp是fastcgi的临时目录,例如php,logs/access.log是访问成功时记录日志的地方。logs/nginx.pid是nginx生成的主进程的pid存放位置。proxy_temp代理临时文件,nginx可以用来做代理。scgi_temp是scgi的临时目录。uwsgi_temp是uwsgi_temp的临时目录。相关cgi可以看看这个文章

好了,言归正传,既然我们配置文件配置好了,好就重新加载配置文件吧:

liuxu:test$ ./nginx -p . -s reload
liuxu:test$ ps aux | grep nginx
liuxu    25913  0.0  0.0  14300  2300 ?        Ss   10:39   0:00 nginx: master process ./nginx -p .
liuxu    29989  0.0  0.0  14488  1308 ?        S    11:54   0:00 nginx: worker process
liuxu    30100  0.0  0.0  21536  1040 pts/0    S+   11:58   0:00 grep --color=auto nginx
liuxu:test$ ss -anp | grep nginx
u_str ESTAB 0 0   *            2510750              users:(("nginx",pid=29989,fd=5),("nginx",pid=25913,fd=5))
u_str ESTAB 0 0   *            2510749              users:(("nginx",pid=25913,fd=3))
tcp LISTEN  0 128 0.0.0.0:8000 0.0.0.0:* users:(("nginx",pid=29989,fd=8),("nginx",pid=25913,fd=8))

看看,最下面的worker监听了本机的8000端口。

还可以用这个命令,只不过现在比较新的系统netstat默认都不安装了:

liuxu:test$ sudo netstat -lnptu | grep nginx
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      25913/nginx: master

我们没有配置任何与端口有关的东西,看上去nginx默认将8000作为了默认端口。这里说说为啥nginx默认没有用80端口,这是因为linux下的程序如果要用1024以内的端口需要root权限,但一般情况下我们都是以普通用户登陆系统的,所以为了避免需要多余的权限,很多程序默认使用大于1024端口,例如jekyll默认使用4000端口。

好了,现在可以用浏览器访问本机的8000端口看看:

img1

img2

img3

哈哈,成功了!

这里验证一下前面说的访问https://www.liuquanhao.com或自动访问https://www.liuquanhao.com/,可以看见浏览器栏里没有/,但请求的却是/

img4

基本配置就到这里,那就先关闭nginx吧,休息一下再继续玩:

liuxu:test$ ./nginx -p . -s stop
liuxu:test$ ps aux | grep nginx
liuxu    30747  0.0  0.0  21536  1048 pts/0    S+   12:07   0:00 grep --color=auto nginx

知识共享许可协议    鄂ICP备 15002452号-5    鄂公网安备 42088102000048号