type
Post
status
Published
slug
2019/07/28/1564656219448
summary
Nginx静态服务配置--深入理解root与alias指令
tags
开发
工具
建站
Nginx
category
Linux
icon
password
new update day
Property
Oct 22, 2023 01:31 PM
created days
Last edited time
Oct 22, 2023 01:31 PM
Nginx静态服务配置--深入理解root与alias指令
原文链接:https://www.jianshu.com/p/4be0d5882ec5
作者:人世间
0. Nginx 介绍
众所周知
Nginx
以其高性能著称,所以常用做 前端反向代理服务器
。同时nginx也是一个高性能的静态文件服务器。通常都会把应用的静态文件使用
nginx
处理。但是配置
nginx
的静态文件则有两个指令,一个 root
和一个 alias
。对于这两个指令,在哪些场合使用哪个、以及是否需要在路径的后面加上 斜杠
,经常容易让人犯晕,本文通过实际尝试不同的匹配规则,来进行实战式学习、并对其使用方式进行了归纳,得到了一个比较通用的配置方式。1. 安装 nginx
本次使用的环境为
CentOS7
采用 yum
安装 nginx
2. Nginx 各配置文件的基本信息
运行
rpm -ql nginx
查看 nginx
各配置文件的路径、可以看出 nginx
的主配置文件为 /etc/nginx/nginx.conf
3. Nginx 的默认主配置文件
nginx
的默认的主配置文件、默认的虚拟主机配置文件目录为 /etc/nginx/conf.d/*.conf
4. 启动 nginx 查看是否能够正常运行
- 输入以下命令启动 nginx
# 启动命令 systemctl start nginx # 查看服务运行状态 systemctl status nginx
- 查看 80 端口是否被监听
运行
netsats -ntlp
输出结果见下图,若提示找不到命令、可以通过安装
net-tools
包来解决。
- 进行浏览器访问测试
如果你是使用的虚拟机的话、可以尝试使用
仅主机模式
、然后输入 虚拟机IP
进行访问、如果你的虚拟机网络默认配置为 网络地址转换(NAT)
那么可以通过 配置端口转发
然后浏览器打开 localhost:what_port_you_set
来实现访问。一切正常的话你应该会看到如下界面。如若不能正常的话、可以尝试关闭防火墙,再次尝试访问。
systemctl stop firewalld
5. 新建虚拟主机配置文件、学习虚拟服务器配置
- 修改
nginx
主配置文件、将server
模块剪切到/etc/nginx/conf.d/root_test.conf
内
- 测试与重载配置文件
- 再次访问、就可以看到熟悉的界面了。这样你就学会了如何新建一个虚拟主机了。
6. 修改配置文件、上传文件,学习 root
与 alias
指令的区别
- 新建一个目录、将原 nginx 默认站点里的文件复制到此文件夹里。
- 修改配置文件
- 将 nginx 所要提供服务的
www
文件夹添加到 selinux 规则里、否则会出现 权限问题、403
# 查看 selinux 运行状态 getenforce # 您可以运行以下命令,以允许 nginx 在此 www 目录提供服务 chcon -Rt httpd_sys_content_t /path/to/www # 如果仍然遇到问题,请查看 getebool -a 中的布尔标志,特别是您可能需要打开 httpd_can_network_connect 以进行网络访问 setsebool -P httpd_can_network_connect on # 重启 nginx 再次进行访问即可 systemctl restart nginx # 也可直接临时关闭 selinux (直到下次重启) setenforce Permissive
- 制作测试环境
分别有两个静态文件夹,一个是static,另外一个是upload。
1. root 指令
1. 初识root
root
是指定项目的根目录,适用与server
和 location
。可以指定多个,如果 locaiton
没有指定,会往其外层的 server
或 http
中寻找继承。这是如果访问
http://your_ip/static/stc.png
会发现图片已经返回。我们还尚未配置 location
,为啥会正确的找到文件?学习
root
或者 alias
指令的时候,最好的办法是给文件拓展名加上一个字符,使得 该文件在硬盘中不存在
,那么就能从 nginx
的 error.log
中看到 nginx
寻找文件的方式。访问
http://your_ip/static/stc.png
,然后查看 tail -f /var/log/nginx/error.log
文件,可以看到如下的错误信息:2019/07/28 23:40:38 [error] 11120#0: *12 open() "/var/www/html/static/stc.pngx" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /static/stc.pngx HTTP/1.1", host: "localhost"
即
/var/www/html/static/stc.pngx
文件不存在。我们的确没有这个文件。如果文件名正确,就能访问,原因是由于在server中指定了root /var/www/html
,此时的nginx 就在 该目录下寻找文件
,而url上的地址,正好和文件的路径一致<http://localhost> /static/stc.png /var/www/html /static/stc.png
由此可以猜想,nginx中
root指令
的地址,其实是 替换了匹配后的url中的host
。2. 再探 root 指令
为了验证上面的猜想,需要多写几个
location
做实验。添加一个location配置如下:location ^~ /static { root /var/www/html/static; }
别忘记了测试配置文件以及重载配置文件
再次访问
http://localhost/static/stc.png
,发现并不能显示图片了,查看error.log 返回如下:2019/07/28 23:49:48 [error] 11227#0: *19 open() "/var/www/html/static/static/stc.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /static/stc.png HTTP/1.1", host: "localhost"
nginx把地址识别成
/var/www/html/static/static/stc.png
多了一个static
,套用上面的规则,其组合为localhost /static/stc.png /var/www/html/static /static/stc.png
localhost == /var/www/html/static ,url是/static/stc.png。置换可以得到
/var/www/html/static/static/stc.png
。与 error
中的一致。解决方案就是把root中的 static 去掉,马上就能访问图片了。
那么把文件夹 static命名为stc,其结果又会怎样?
location ^~ /static { root /var/www/html; }
别忘记了测试配置文件以及重载配置文件
访问
http://localhost/static/stc.png
得到错误:2019/07/28 23:58:17 [error] 11282#0: *28 open() "/var/www/html/static/stc.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /static/stc.png HTTP/1.1", host: "localhost"
计算路径
/var/www/html
+ /static/stc.png
, 找不到 /var/www/html/static/stc.png
文件,符合之前所说的规则,尝试修改location:location ^~ /stc { root /var/www/html; }
别忘记了测试配置文件以及重载配置文件
因为url变了,访问
http://localhost/stc/stc.png
,才能够找到图片。现在把stc文件夹变回static。3. root 与 斜杠
我相信有很多人会像我一样疑惑,路径最后的斜杠
/
是否要加呢?location中的static 后面的斜杠,和匹配后的url有关。root中的路径的斜杠 / 可以再通过实验确定。把location配置如下:
location ^~ /static/ { root /var/www/html/; }
访问
http://localhost/static/stc.png
一切正常,访问 http://localhost/static/stc.pngs
,error为找不到 "/var/www/html/static/stc.pngs"
文件。如果按照root替换host的规则,那么替换过程为
/var/www/html/
+ /static/stc.png
== /var/www/html//static/stc.png
。在*nix系统中, 多个斜杠和一个斜杠是等价的,也就是
/var/www/html//static/stc.png
与 /var/www/html/static/stc.png
一样。这样一来,root路径后面的斜杠,加与不加效果都一样。既然如此,肯定有人会想到这么配置:
location ^~ static/ { root /var/www/html; }
如果安装之前上面的即算法,那么应该是
/var/www/html
+ static/stc.png
,相加的应该是 /var/www/htmlstatic/stc.png
,按理说应该是错误,可是实际上却能访问图片。咄咄怪事?如果对前文nginx location的url匹配规则了解的话,应该看出来了其实
^~ static/
并不能匹配。修改 locationlocation ^~ static/ { rewrite ^ <http://google.com>; # root /var/www/html; }
访问
http://localhost/static/stc.png
依然可以得到图片,没有跳转google,说明并没有匹配 ^~ static/
。其实原理也很简单,还记得我们第一次实验,当时尚未配置location,也同样可以返回图片。没错,尽管
^~ static/
没有匹配,而外层的 server
定义了 root为/var/www/html
,因此搜索图片正常返回,再注释外层的root,再一次访问。此时会得到一个404,查看error如下:2019/07/29 00:19:45 [error] 11386#0: *36 open() "/usr/share/nginx/html/static/stc.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /static/stc.png HTTP/1.1", host: "localhost"
/usr/share/nginx/html/static/stc.png
,说明即使没有指定root,nginx默认也有一个root,/usr/share/nginx/html
。当然,这个配置和 ^~ static/
没有关系。如果
~ static/stc.jpgs?
那么就能命中,此时访问图片,依然能够正确的解析,因此,并不存在 /var/www/html
+ static/stc.png
这种情况。理解这里的关键是 root替换host,并加上匹配后的url,匹配后的url当然包括前面的斜杠,匹配部分的url则不会。
对于
~ static/stc.jpgs?
模式,访问url http://localhost/static/stc.jpg
- 匹配后的url为
/static/stc.jpg
- 匹配部分的url为
static/stc.jpg
掌握这个很重要,直接关系到后面alias指令与斜杠的关系。
4. root 指令归纳。
- 对于匹配后的url地址,将匹配的location中的root路径替换访问url的host即得到文件的真实地址。(多个斜杠其实等价于一个斜杠)
- 如果不匹配location,则寻找更外层的root做替换。
- root指令最后的斜杠可加可不加。
2. alias指令
1. 初识 alias
对于root,操作上很简单,只要把root地址替换host后就是文件在硬盘路径(真实地址)。
对于alise,它并不是替换匹配后的url地址,而是替换匹配部分的url。alias指令也可以有多个。
添加一个location,和root的方式几乎一样:
location ^~ /upload { alias /var/www/html; }
访问
http://localhost/upload/up.png
并没有图片,查看error得到:2019/07/29 03:16:39 [error] 11514#0: *42 open() "/var/www/html/up.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /upload/up.png HTTP/1.1", host: "localhost"
可见 alias的模式并不是
/var/www/html
+ /upload/up.png
,而是 /var/www/html
+ /up.png
。alias这个词在计算机里很常用,字面意思是“别名”,顾名思议就是换一个名字啦。
实际替换规则就是 把匹配的url地址,换成alias中的路径即可。例如上述的例子替换过程可以模拟如下:
过程 | 模式或者 URL |
url模式 | ^~ /upload |
alias路径 | /var/www/html |
访问地址 | |
匹配部分的地址 | /upload + /up.png |
替换 | /upload == /var/www/html |
结果 | /var/www/html + /up.png |
为了修改图片的访问,修改locaton如下:
location ^~ /upload { alias /var/www/html/upload; }
此时访问
http://localhost/upload/up.png
就能得到正确的图片啦,仿造上面的计算过程为:过程 | 模式或 url |
url 模式 | ^~ /upload |
alias 路径 | /var/www/html/upload |
访问地址 | |
匹配部分的地址 | /upload + /up.png |
替换 | /upload == /var/www/html/upload |
结果 | /var/www/html/upload + /up.png |
从结果可以看出,正确的找到了文件路径,如果alias指令路径加上斜杠,那么计算处理的文件路径为:
/upload == /var/www/html/upload /var/www/html/upload/ + /up.png
多个斜杠是合法的。等价于一个斜杠的情况。
下面修改locaiton如下:
location ^~ /upload/ { alias /var/www/html/upload; }
此时匹配时的url则变成
/upload/
+ up.jpg
, 那么置换的结果为 /var/www/html/upload
+ up.png
,而 /var/www/html/uploadup.png
的路径是非法的,从error中也能看到置换的错误:2019/07/29 03:31:19 [error] 12105#0: *49 open() "/var/www/html/uploadup.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /upload/up.png HTTP/1.1", host: "localhost"
解决办法也很简单,把
/var/www/html/upload
改成 /var/www/html/upload/
即可。由此可见,alias最后的斜杠并不像root指令那样可有可无,是否需要,取决于配合loacation的url匹配模式。
前文root模式中,考虑了没有根的斜杠(~ static/stc.jpgs?)这种情况,alias情况下会很难捕捉错误。如果locaion配置如下:
location ~ upload/ { alias /var/www/html/upload/; }
替换置换的文件路径应该为
/var/www/html/upload/up.png
,可是实际测试中,这样配置alias,会一直导致一个301的重定向,如果alias目录没有打开autoindex,则会抛出一个403错误。具体情况尚未知晓,不知道是不是nginx的bug。为了避免这种情况,使用alias的时候,尽量不要配置location为 ~ upload/的模式,并且不从根指定url,还是显得不伦不类。
(原文中写的配置为)
location ^~ upload/ { alias /var/www/html/upload/; }
经测试发现、这样会导致不能正常匹配 url,以至于访问到nginx 默认文件夹
/usr/share/nginx/html
2019/07/29 03:34:37 [error] 12129#0: *52 open() "/usr/share/nginx/html/upload/up.png" failed (2: No such file or directory), client: 10.0.2.2, server: _, request: "GET /upload/up.png HTTP/1.1", host: "localhost"
alise作为别名,比起root的一大好处就是 不一定要url上的路径和文件路径一样,因为alise并不是替换host,而是替换匹配部分的host。修改配置如下:
location ^~ /upload/ { alias /var/www/html/static/; }
访问
http://localhost/upload/stc.png
或者 http://localhost/upload/flask/m.png
都能正确的访问到static目录下的文件,尽管url上是upload。替换规则也很简单,
/upload/
== /var/www/html/static/
得到 /var/www/html/static/
+ stc.png
或 /var/www/html/static/
+ flask/m.png
。3. 总结
nginx的静态文件配置中,root和alias指令都能实现。为了避免混淆,尽量不要写没有根路径的url模式,即避免
static/
这样的开头,根路径的斜杠需要保留,没有根路径其实也很奇怪。root和alias的区别主要在于替换的部分,root模式中,会把root配置的路径替换匹配后的url中的host。
alias则把他指定的路径,替换url中匹配的部分。指令中的斜杠对于root指令没有影响,对于alise则按照替换规则匹配即可。
- root 指令
location /dir/ root root_path -> <http://host/dir/file.txt> -> root_path/dir/file.txt
- alias 指令
location /dir alias alias_path -> <http://host> /dir /file.txt -> alias_path/file.txt location /dir/ alias alias_path/ -> <http://host> /dir/ file.txt -> alias_path/file.txt
了解了root和alise之后,通常最佳实际是配置一个项目的根root,其他的文件夹则使用alias,毕竟alias更加灵活。
欢迎加入“喵星计算机技术研究院”,原创技术文章第一时间推送。
- 作者:tangcuyu
- 链接:https://expoli.tech/articles/2019/07/28/1564656219448
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章