Nginx 配置指令的执行顺序(七)
来看一个 ngx_static
模块服务磁盘文件的例子。我们使用下面这个配置片段:
同时在本机的 /var/www/
目录下创建两个文件,一个文件叫做 index.html
,内容是一行文本 this is my home
;另一个文件叫做 hello.html
,内容是一行文本 hello world
. 同时注意这两个文件的权限设置,确保它们都对运行 Nginx worker 进程的系统帐户可读。
现在来通过 HTTP 协议请求一下这两个文件所对应的 URI:
$ curl 'http://localhost:8080/index.html'
this is my home
$ curl 'http://localhost:8080/hello.html'
hello world
我们看到,先前创建的那两个磁盘文件的内容被分别输出了。
不妨来分析一下这里发生的事情:location /
中没有使用运行在 content
阶段的模块指令,于是也就没有模块注册这个 location
的“内容处理程序”,处理权便自动落到了在 content
阶段“垫底”的那 3 个静态资源服务模块。首先运行的 ngx_index 和 ngx_autoindex 模块先后看到当前请求的 URI,/index.html
和/hello.html
,并不以 /
结尾,于是直接弃权,将处理权转给了最后运行的 ngx_static
模块。ngx_static
模块根据 root 指令指定的“文档根目录”(document root),分别将请求 URI /index.html
和 /hello.html
映射为文件系统路径 /var/www/index.html
和 /var/www/hello.html
,在确认这两个文件存在后,将它们的内容分别作为响应体输出,并自动设置 Content-Type
、Content-Length
以及 Last-Modified
等响应头。
为了确认 ngx_static
模块确实运行了,可以启用 (一) 中介绍过的 Nginx “调试日志”,然后再次请求 /index.html
这个接口。此时,在 Nginx 错误日志文件中可以看到类似下面这一行的调试信息:
[debug] 3033#0: *1 http static fd: 8
这一行信息便是 ngx_static
模块生成的,其含义是“正在输出的静态文件的描述符是数字 8
”。当然,具体的文件描述符编号会经常发生变化,这里只是我机器的一次典型输出。值得一提的是,能生成这一行调试信息的还有标准模块 ngx_gzip_static ,但它默认是不启用的,后面会专门介绍到这个模块。
注意上面这个例子中使用的 root 配置指令只起到了声明“文档根目录”的作用,并不是它开启了ngx_static
模块。ngx_static
模块总是处于开启状态,但是否轮得到它运行就要看 content
阶段先于它运行的那些模块是否“弃权”了。为了进一步确认这一点,来看下面这个空白 location
的定义:
location / {
}
因为没有配置 root 指令,所以在访问这个接口时,Nginx 会自动计算出一个缺省的“文档根目录”。该缺省值是取所谓的“配置前缀”(configure prefix)路径下的 html/
子目录。举一个例子,假设“配置前缀”是/foo/bah/
,则缺省的“文档根目录”便是 /foo/bar/html/
.
那么“配置前缀”是由什么来决定的呢?默认情况下,就是 Nginx 安装时的根目录(或者说 Nginx 构造时传递给 ./configure
脚本的 --prefix
选项的路径值)。如果 Nginx 安装到了 /usr/local/nginx/
下,则“配置前缀”便是 /usr/local/nginx/
,同时默认的“文档根目录”便是 /usr/local/nginx/html/
. 不过,我们也可以在启动 Nginx 的时候,通过 --prefix
命令行选项临时指定自己的“配置前缀”路径。假设我们启动 Nginx 时使用的命令是
nginx -p /home/agentzh/test/
则对于该服务器实例,其“配置前缀”便是 /home/agentzh/test/
,而默认的“文档根目录”便是/home/agentzh/test/html/
. “配置前缀”不仅会决定默认的“文档根目录”,还决定着 Nginx 配置文件中许多相对路径值如何解释为绝对路径,后面我们还会看到许多需要引用到“配置前缀”的例子。
获取当前“文档根目录”的路径有一个非常简便的方法,那就是请求一个肯定不存在的文件所对应的资源名,例如:
$ curl 'http://localhost:8080/blah-blah.txt'
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
我们会很自然地得到 404
错误页。此时再看 Nginx 错误日志文件,应该会看到类似下面这一行错误消息:
[error] 9364#0: *1 open() "/home/agentzh/test/html/blah-blah.txt" failed (2: No such file or directory)
这条错误消息是 ngx_static
模块打印出来的,因为它并不能在文件系统的对应路径上找到名为 blah-blah.txt
的文件。因为这条错误信息中包含有 ngx_static
试图打开的文件的绝对路径,所以从这个路径不难看出,当前的“文档根目录”是 /home/agentzh/test/html/
.
很多初学者会想当然地把 404
错误理解为某个 location
不存在,其实上面这个例子表明,即使 location
存在并成功匹配,也是可能返回 404
错误页的。因为决定着 404
错误页的是抽象的“资源”是否存在,而非某个具体的 location
是否存在。
初学者常犯的一个错误是忘记配置 content
阶段的模块指令,而他们自己其实并不期望使用 content
阶段缺省运行的静态资源服务,例如:
location /auth {
access_by_lua '
-- a lot of Lua code omitted here...
';
}
显然,这个 /auth
接口只定义了 access
阶段的配置指令,即 access_by_lua,并未定义任何 content
阶段的配置指令。于是当我们请求 /auth
接口时,在 access
阶段的 Lua 代码会如期执行,然后 content
阶段的那些静态文件服务会紧接着自动发生作用,直至 ngx_static
模块去文件系统上找名为 auth
的文件。而经常地,404
错误页会抛出,除非运气太好,在对应路径上确实存在一个叫做 auth
的文件。所以,一条经验是,当遇到意外的 404
错误并且又不涉及静态文件服务时,应当首先检查是否在对应的 location
配置块中恰当地配置了 content
阶段的模块指令,例如 content_by_lua、 echo 以及 proxy_pass 之类。当然,Nginx 的error.log
文件一般总是会提供各种意外问题的答案,例如对于上面这个例子,我的 error.log
中有下面这条错误信息:
[error] 9364#0: *1 open() "/home/agentzh/test/html/auth" failed (2: No such file or directory)
Nginx 配置指令的执行顺序(七)的更多相关文章
- Nginx 配置指令的执行顺序(五)
Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”(content)并输出 HTTP 响应的使命.正因为其重要性,这个阶段的配 ...
- Nginx 配置指令的执行顺序(八)
前面我们详细讨论了 rewrite.access 和 content 这三个最为常见的 Nginx 请求处理阶段,在此过程中,也顺便介绍了运行在这三个阶段的众多 Nginx 模块及其配置指令.同时可以 ...
- Nginx 配置指令的执行顺序(一)
大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个 location 配置块使用了多个 Nginx 模块的配置指令时,这些指令的执行顺序很可能会跟它们的书写顺序大相径庭.于是许多人选择了 ...
- Nginx配置指令的执行顺序
rewrite阶段 rewrite阶段是一个比较早的请求处理阶段,这个阶段的配置指令一般用来对当前请求进行各种修改(比如对URI和URL参数进行改写),或者创建并初始化一系列后续处理阶段可能需要的Ng ...
- Nginx 配置指令的执行顺序(二)
我们前面已经知道,当 set 指令用在 location 配置块中时,都是在当前请求的 rewrite 阶段运行的.事实上,在此上下文中,ngx_rewrite 模块中的几乎全部指令,都运行在 rew ...
- Nginx 配置指令的执行顺序(十一)
紧跟在 post-access 阶段之后的是 try-files 阶段.这个阶段专门用于实现标准配置指令 try_files 的功能,并不支持 Nginx 模块注册处理程序.由于 try_files ...
- Nginx 配置指令的执行顺序(十)
运行在 post-rewrite 阶段之后的是所谓的 preaccess 阶段.该阶段在 access 阶段之前执行,故名preaccess. 标准模块 ngx_limit_req 和 ngx_lim ...
- Nginx 配置指令的执行顺序(六)
前面我们在 (五) 中提到,在一个 location 中使用 content 阶段指令时,通常情况下就是对应的 Nginx 模块注册该 location 中的“内容处理程序”.那么当一个 locati ...
- Nginx 配置指令的执行顺序(三)
如前文所述,除非像 ngx_set_misc 模块那样使用特殊技术,其他模块的配置指令即使是在 rewrite 阶段运行,也不能和 ngx_rewrite 模块的指令混合使用.不妨来看几个这样的例子. ...
随机推荐
- WPF安装部署小结
开机启动 右击"MySetup">>"视图">>"注册表",在"HKEY_LOCAL-MACHINE&qu ...
- CentOS6.4卸载自带的OpenJDK并安装jdk1.6.21
#进入系统的terminal,查看当前的jdk版本: shell>java -version #查看安装包 shell>rpm -qa|grep java #将上条命令查出来的结果卸载掉, ...
- 就是爱Java
就是爱Java,提供了Java代码示例,文章和教程,可以帮助你学习Java编程语言. 网站名称:就是爱Java 网站地址:http://java.openyu.org
- Ext4 MVC CRUD操作
项目目录结构如下: (1)index.html <!DOCTYPE html> <html> <head> <title>用户管理</title& ...
- Ubuntu14.04LST安装weblogic11g
1:下载链接http://download.oracle.com/otn/nt/middleware/11g/wls/1036/wls1036_generic.jar 2:进行安装(前提已经安装好JD ...
- (?:pattern) (?=pattern) (?!pattern)
(pattern) 匹配 pattern 并获取这一匹配.所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0- ...
- 百度地图JavaScript API V1.5初级开发工具类
/** * 百度地图使用工具类-v1.5 * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email boo ...
- 运用 BoxLayout 进行 Swing 控件布局
摘自http://www.cnblogs.com/fnlingnzb-learner/p/6008572.html 运用 BoxLayout 进行 Swing 控件布局 对于初学 Java Swing ...
- hdu 5463 Clarke and minecraft(贪心)
Problem Description Clarke is a patient with multiple personality disorder. One day, Clarke turned i ...
- 用Unity做的一个小游戏,仿照一个样例写的,个人认为文章写的不错,哈哈