准备写一系列nginx教程,从基础编译配置开始,到源码解析。之前陆陆续续学了点nginx相关的知识,源码也学过一点,但是没有系统学习,所以这次要系统学习一下。

目前先以备忘录的方式写,没有什么结构,根据自己的学习方式来以日记的方式完成,这个可以在后面有结构学习的时候知道我当时是怎么学习怎么想的。就像数学公式,一个公式并不是凭空出现的,而是有灵感和不断的实验尝试得到的。

写本类文档,我会先自己学习测试,会遇到无数失败,最后成功后删去多余的操作记录下来,让文档显得精炼真实。文章中会有“应该”这样的词,表示我的猜测,但不一定是正确的,需要以后学习源码时确认。好了,下面开始学习nginx。



首先说一下我的环境,我的系统是ubuntu18.04,所以如果你是windows,那么编译安装方面你可能需要自己查询相关教程,但是后面配置相关应该是可以参考本文档的。

首先从nginx官网下载最新的源码包

img1

liuxu:nginx$ pwd
/home/liuxu/learn/nginx
liuxu:nginx$ ls -l
-rw-r--r-- 1 liuxu liuxu 1016272 4月  17 23:35 nginx-1.14.0.tar.gz

然后我们解压源码:

liuxu:nginx$ tar -xvf nginx-1.14.0.tar.gz
liuxu:nginx$ ls -l
drwxr-xr-x 8 liuxu liuxu    4096 4月  17 23:22 nginx-1.14.0
-rw-r--r-- 1 liuxu liuxu 1016272 4月  17 23:35 nginx-1.14.0.tar.gz

好了,源码我们拿到了,先看看源码里面有啥:

liuxu:nginx$ tree -L 2 nginx-1.14.0/
nginx-1.14.0/
├── auto
│   ├── cc
│   ├── define
│   ├── endianness
│   ├── feature
│   ├── have
│   ├── have_headers
│   ├── headers
│   ├── include
│   ├── init
│   ├── install
│   ├── lib
│   ├── make
│   ├── module
│   ├── modules
│   ├── nohave
│   ├── options
│   ├── os
│   ├── sources
│   ├── stubs
│   ├── summary
│   ├── threads
│   ├── types
│   └── unix
├── CHANGES
├── CHANGES.ru
├── conf
│   ├── fastcgi.conf
│   ├── fastcgi_params
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── nginx.conf
│   ├── scgi_params
│   ├── uwsgi_params
│   └── win-utf
├── configure
├── contrib
│   ├── geo2nginx.pl
│   ├── README
│   ├── unicode2nginx
│   └── vim
├── html
│   ├── 50x.html
│   └── index.html
├── LICENSE
├── man
│   └── nginx.8
├── README
└── src
    ├── core
    ├── event
    ├── http
    ├── mail
    ├── misc
    ├── os
    └── stream

19 directories, 38 files

从这个输出看,auto里应该是编译时自动执行的东西,CHANGESCHANGES.ru是此版本代码和上一版本有啥改变,conf里应该是nginx的配置文件,configure就是所有代码基本会有的自动生成Makefile的工具啦,contrib里是一些工具,例如那个vim里就是vim外观配置文件,html里是nginx默认的html页面,LICENSE是开源代码的使用协议,man里是可由linuxman命令输出的帮助内容,README就是在使用该源码应该先看看的文件,src里就是nginx源码了。

先看一下README文件是正确的操作:

liuxu:nginx-1.14.0$ cat README 

Documentation is available at http://nginx.org

恩。。告诉我们文档得去nginx官网。

好吧,那就去官网看文档,看看怎么安装。

img2

看看这个文档,安装、编译、配置、管理啥都有,那个“nginx for Windows”是windows用户们可以参考的文档。

从安装文档看,有直接通过yum或apt配置源后直接安装的方式,也可以自己手动编译,我们这里就看怎么手动编译安装。

编译安装文档里面先给了所有编译参数的解释,最后给了一个编译安装的例子。看着这么多编译选项,其实学习起来很简单,除了前面十来个特殊选项,后面的全部都是“–with-…”和“–without-…”,因为nginx从源码到逻辑功能都是模块化的,所以编译时需要用“–with-…”选择需要的模块来编译进nginx。nginx也有默认需要编译的模块,如果不需要这些默认的,可以用“–without-…”去掉。

既然是从零开始学nginx,那么就不要任何编译参数编译吧,ubuntu用户可能需要先安装编译工具:

liuxu:nginx-1.14.0$ sudo apt install build-essential

然后我们开始编译nginx:

liuxu:nginx-1.14.0$ pwd
/home/liuxu/learn/nginx/nginx-1.14.0
liuxu:nginx-1.14.0$ ls
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  README  src
liuxu:nginx-1.14.0$ ./configure 
checking for OS
 + Linux 4.15.0-20-generic x86_64
checking for C compiler ... found
 + using GNU C compiler
 + gcc version: 7.3.0 (Ubuntu 7.3.0-16ubuntu3) 
checking for gcc -pipe switch ... found
...
...
checking for sysconf(_SC_NPROCESSORS_ONLN) ... found
checking for sysconf(_SC_LEVEL1_DCACHE_LINESIZE) ... found
checking for openat(), fstatat() ... found
checking for getaddrinfo() ... found
checking for PCRE library ... not found
checking for PCRE library in /usr/local/ ... not found
checking for PCRE library in /usr/include/pcre/ ... not found
checking for PCRE library in /usr/pkg/ ... not found
checking for PCRE library in /opt/local/ ... not found

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.

好吧,出错了,看看“error”前后的输出,是PCRE library没有,可以用--without-http_rewrite_module去掉http_write_module,这个参数就是--without-...里面的,从这个可以知道http_rewrite_module是nginx默认会安装的模块,它依赖PCRE library。但是系统里没找到,所有如果需要这个模块的话,就需要用后面的参数--with-pcre=<path>,为了保证nginx的默认选项,我们选方案二,加入pcre包。

在文档里看看这个选项:

--with-pcre=path
sets the path to the sources of the PCRE library. The library distribution (version 4.48.41) needs to be downloaded from the PCRE site and extracted. The rest is done by nginxs ./configure and make. The library is required for regular expressions support in the location directive and for the ngx_http_rewrite_module module.

这个选项用户设置PCRE library目录位置,它的版本需要是4.4-8.41,加入这个选项后再用./configure重新编译即可。这个包是给ngx_http_rewrite_module模块的正则表达式给予支持。

我们现在来现在这个包,PCRE library官网里找到下载目录并下载,可以看见,有很多版本,但既然nginx文档说需要的版本是4.4-8.41,那就下载pcre-8.41.tar.bz2吧,其他的.tar.gz等等只是压缩格式不同,代码都是一样的,.sig是验证文件,我也懒得验证了,但严格操作是需要验证的。

下载后解压,并在编译选项中包含:

liuxu:nginx$ pwd
/home/liuxu/learn/nginx
liuxu:nginx$ tar -xvf pcre-8.41.tar.bz2
liuxu:nginx$ ls -al
total 2540
drwxr-xr-x 4 liuxu liuxu    4096 5月  28 15:38 .
drwxr-xr-x 3 liuxu liuxu    4096 5月  28 14:30 ..
drwxr-xr-x 9 liuxu liuxu    4096 5月  28 15:06 nginx-1.14.0
-rw-r--r-- 1 liuxu liuxu 1016272 4月  17 23:35 nginx-1.14.0.tar.gz
drwxr-xr-x 7 liuxu liuxu    4096 7月   5  2017 pcre-8.41
-rw-r--r-- 1 liuxu liuxu 1561874 7月   5  2017 pcre-8.41.tar.bz2
liuxu:nginx$ cd nginx-1.14.0/
liuxu:nginx-1.14.0$ ./configure --with-pcre=../pcre-8.41

看看./configure --with-pcre=../pcre-8.41,就是包含上级目录的pcre包。然后一阵输出,Makefile生成成功。

liuxu:nginx-1.14.0$ ./configure --with-pcre=../pcre-8.41
checking for OS
 + Linux 4.15.0-20-generic x86_64
checking for C compiler ... found
 + using GNU C compiler
 + gcc version: 7.3.0 (Ubuntu 7.3.0-16ubuntu3) 
checking for gcc -pipe switch ... found
checking for -Wl,-E switch ... found
...
...
checking for zlib library ... found
creating objs/Makefile

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"

看下面的Configuration summary输出,里边包括了pcre使用了我们设置的目录,openssl没有使用,它应该是给https用的,zlib用的系统的,它应该是给nginx压缩支持。然后一堆nginx默认选项,例如默认配置文件位置,默认日志文件位置。

好了,既然Makefile已经有了,可以开始编译:

liuxu:nginx-1.14.0$ ls 
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  Makefile  man  objs  README  src
liuxu:nginx-1.14.0$ make
make -f objs/Makefile
make[1]: Entering directory '/home/liuxu/learn/nginx/nginx-1.14.0'
cd ../pcre-8.41 \
&& if [ -f Makefile ]; then make distclean; fi \
&& CC="cc" CFLAGS="-O2 -fomit-frame-pointer -pipe " \
./configure --disable-shared 
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
...
...
objs/src/http/modules/ngx_http_upstream_keepalive_module.o \
objs/src/http/modules/ngx_http_upstream_zone_module.o \
objs/ngx_modules.o \
-ldl -lpthread -lcrypt ../pcre-8.41/.libs/libpcre.a -lz \
-Wl,-E
sed -e "s|%%PREFIX%%|/usr/local/nginx|" \
    -e "s|%%PID_PATH%%|/usr/local/nginx/logs/nginx.pid|" \
    -e "s|%%CONF_PATH%%|/usr/local/nginx/conf/nginx.conf|" \
    -e "s|%%ERROR_LOG_PATH%%|/usr/local/nginx/logs/error.log|" \
    < man/nginx.8 > objs/nginx.8
make[1]: Leaving directory '/home/liuxu/learn/nginx/nginx-1.14.0'

编译很快,一会就成功了:

liuxu:nginx-1.14.0$ ls
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  Makefile  man  objs  README  src
liuxu:nginx-1.14.0$ ls objs/
autoconf.err  Makefile  nginx  nginx.8  ngx_auto_config.h  ngx_auto_headers.h  ngx_modules.c  ngx_modules.o  src

objs目录下的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

好了,接下来就是从这个可执行文件开始学习nginx了。