location
语法:location [=|~|~*|^~] /uri/ { … }
默认:否
上下文:server
这个指令随URL不同而接受不同的结构。你可以配置使用常规字符串和正则表达式。如果使用正则表达式,你必须使用 ~* 前缀选择不区分大小写的匹配或者 ~ 选择区分大小写的匹配。
确定 哪个location 指令匹配一个特定指令,常规字符串第一个测试。常规字符串匹配请求的开始部分并且区分大小写,最明确的匹配将会被使用(查看下文明白 nginx 怎么确定它)。然后正则表达式按照配置文件里的顺序测试。找到第一个比配的正则表达式将停止搜索。如果没有找到匹配的正则表达式,使用常规字符串的结果。
有两个方法修改这个行为。第一个方法是使用 “=”前缀,将只执行严格匹配。如果这个查询匹配,那么将停止搜索并立即处理这个请求。例子:如果经常发生”/”请求,那么使用 “location = /” 将加速处理这个请求。
第二个是使用 ^~ 前缀。如果把这个前缀用于一个常规字符串那么告诉nginx 如果路径匹配那么不测试正则表达式。
而且它重要在于 NGINX 做比较没有 URL 编码,所以如果你有一个 URL 链接’/images/%20/test’ , 那么使用 “images/ /test” 限定location。
总结,指令按下列顺序被接受:
1. = 前缀的指令严格匹配这个查询。如果找到,停止搜索。
2. 剩下的常规字符串,长的在前。如果这个匹配使用 ^~ 前缀,搜索停止。
3. 正则表达式,按配置文件里的顺序。
4. 如果第三步产生匹配,则使用这个结果。否则使用第二步的匹配结果。
例子:
location = / {
# 只匹配 / 查询。
[ configuration A ]
}
location / {
# 匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配。
[ configuration B ]
}
location ^~ /images/ {
# 匹配任何已 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
[ configuration C ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配任何已 gif、jpg 或 jpeg 结尾的请求。然而所有 /images/ 目录的请求将使用 Configuration C。
[ configuration D ]
}
例子请求:
/ -> configuration A
/documents/document.html -> configuration B
/images/1.gif -> configuration C
/documents/1.jpg -> configuration D
注意:按任意顺序定义这4个配置结果将仍然一样。
这几天在把我们网站的主web server从apache迁移到nginx上面,没想到还是遇到了些问题。
1.原来在apache每个二级域名都是用建站点的方式,我打算在nginx里面使用rewrite规则的方式来进行跳转,比如:
1
2
3
4
| location /
{
rewrite ^(.*)life.my.com(.*)$ $1www.my.com/lan28/$2 last;
} |
可事实上这样写是完全没有效果的,后来分析了下实际上在 location / 里面的rewrite是只能处理hostname之后的内容就是www.my.com/(rewrite),对于hostname是没法进行rewrite的,那如果要对hostname进行rewrite怎么办呢。目前想到是把rewrite挪到location外面去,不过尝试了下貌似还是有问题,继续研究中。。。
2.原来www下面有几个alias,比如访问/wwwroot/www/php/ alias 到/wwwroot/php/ 这样,但是在nginx里面alias的话呢htm、图片等静态文件没问题,但是php问题就来了,由于php是通过正则转发到fastcgi的比如:
1
2
3
4
5
6
7
8
9
10
11
| root /wwwroot/www;
location /php/
{
alias /wwwroot/php/;
}
location ~ .*\.php?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
} |
这种情况下如果http访问/php/*.php文件实际上是由 location ~ .*\.php?$ 处理的,也就是说php文件根本没没有进行alias还是按照/wwwroot/www/php/的路径访问的。
这个问题如何解决呢,我想到了几个方法:
1)使用symbolic link从系统上把/wwwroot/php/映射到/wwwroot/www/php/
2)修改location ~ .*\.php?$ 的正则,将/php/目录排除,然后在写一个location ~ /php/.*\.php?$ 来处理/php/下面的php文件
3)放弃alias使用rewrite的方式来处理。
三个方法第一个属于回避型,虽然能解决问题但是不符合我的要求。第二个么太复杂,能否实现还是未知。最后我选择了第三个方法就是用rewrite来处理。
略微修改了下代码
1
2
3
4
5
6
7
8
9
10
11
12
| root /wwwroot/www;
location ^~ /php/ #这里的关键就是使用“^~”,这样如果是/php/的话就不去匹配下面的php的正则,而全部重定向到php.my.com去,不然的话还是一样的htm正常,php无法访问。
{
rewrite (.*)/php/(.*) http://php.my.com/$2 permanent;
}
location ~ .*\.php?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}
· |
这里的http://php.my.com 对应的就是/wwwroot/www/php/
这样基本就实现了需求了
最近在迁移写应用到nginx中,在rewrite上面遇到了些问题。
虽然大部分的rewrite规则转换到nginx中几乎改动很小,但是一些特殊的比如下面这段,在nginx里面可以说完全不一样。
1
2
3
4
5
| RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^.*(\.html|\.xml|\.css|\.js|\.gif|\.png|\.jpg|\.jpeg)$|.*(FCKeditor).*$|.*(fckeditor).*$|.*(userfiles).*|.*(testadow).|.*(api).*|.*(passportcode).*
RewriteRule !\.(js|ico|gif|jpg|png|css)$ /index.php
|
转换到nginx的写法(只是参照的语法,并不是上面内容的转换)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| location /xxxx/ {
set $test "";
if ($request_method = POST) {
set $test P;
}
if ($http_cookie ~* "CCCC=.+(?:;|$)" ) {
set $test ${test}C";
}
if ($test = PC) {
#rewrite rule goes here.
}
} |
今天在做测试环境的时候发现网站的
http://testbbs.thmz.com/uc/ 打得开的
但是
http://testbbs.thmz.com/uc 就打不开,就少一个/
照例说http://testbbs.thmz.com/uc 访问时会自动跳转为 http://testbbs.thmz.com/uc/
但是我这个偏偏就是没有跳转
问了个朋友,他说他的好的,要来配置文件对比着看看,没啥大的区别
最好一个一个调试,结果发现问题出在了
server_name 221.134.22.196 testbbs.thmz.com;
我的conf文件是从以前的机器复制过来的,结果221.134.22.196这个ip忘了改了,导致了这个问题。
另外一直解决方案是做个rewrite,这样即使server_name填错也没关系
if (-d $request_filename)
{
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
作者:shunz,出处:http://shunz.net/2008/07/nginx_log_rotation.html
Nginx是一款采用Linux 2.6内核epoll新机制开发的Web服务器软件,能极大地提高Web访问特别是小文件访问的I/O性能,是c10k问题的一个解决方案。有测试称Nginx比Apache效率提高10倍,而从我自己上次的测试来看,其并发性能确实比Apache强不少。Nginx以短小精悍著称,所以虽然一些web核心功能他都支持得挺好,但是一些扩展功能却还不能支持,比如Nginx目前就还不支持通过pipe输出log,所以就不支持利用cronolog来按时间进行日志截断回滚。下面提供一种替代解决方案:
#!/bin/shlog_dir="/var/log/httpd"yesterday=`date +%Y%m%d -d '-1 day'`lastday =`date +%Y%m%d -d '-1 month'`/bin/rm ${log_dir}/access.${lastday}.log/bin/rm ${log_dir}/error.${lastday}.log/bin/mv ${log_dir}/access.log ${log_dir}/access.${yesterday}.log/bin/mv ${log_dir}/error.log ${log_dir}/error.${yesterday}.logkill -USR1 `cat /var/run/nginx.pid`/bin/gzip ${log_dir}/access.${yesterday}.log &/bin/gzip ${log_dir}/error.${yesterday}.log &
然后将该脚本保存在/etc/cron.daily目录里,或者在crontab里每日0点时运行。