<?php

Currently browsing nginx

nginx中的文件检查”缺陷”

接上一篇 nginx启用sendfile之高级篇,还是同一个项目,按照前文的配置已经都很正常,只是发现有些目标文件明明是已经存在的,但为什么还是走到了后端处理呢? 查看了十几个URL之后发现了一个共性:文件或目录名包含 “+”。
比如 用户请求http://yourdomain/ab+c.ext,经过测试之后发现nginx实际读取的文件名是 ab%2bc.ext ,注意:这是在经过location匹配和rewrite处理的情况下,如果是直接访问一个静态文件 ab+c.ext 且文件存在,是没有问题的。经过我测试发现加号和空格会有这个问题,其他符号都是不会被encode的。
如此一来就很好解释“有些目标文件明明是已经存在的,但为什么还是走到了后端处理呢?”,nginx检查文件是否存在时使用的是 ab%2bc.ext,但文件系统上实际保存的文件是 ab+c.ext,因此会将请求rewrite到后端程序处理。

既然知道了问题,解决办法自然就有了。有两种解决办法:
1,不要使用包含加号和空格的文件、目录名;
2,如果必须使用,应该encode后在做为文件、目录名

注意,在 location 文档说明有这么一句话“It is important to know that nginx does the comparison against decoded URIs.”

nginx启用sendfile之高级篇

什么是sendfile?
nginx官方只是一句带过,如果你需要了解详细的请参考: http://celebnamer.celebworld.ws/stuff/mod_xsendfile/

为什么要用sendfile?
原因很简单,项目中有个需求是后端程序负责把源文件打包加密生成目标文件,然后程序读取目标文件返回给浏览器;这种做法有个致命的缺陷就是占用大量后端程序资源,如果遇到一些访客下载速度巨慢,就会造成大量资源被长期占用得不到释放,很快后端程序就会因为没有资源可用而无法正常提供服务。通常表现就是nginx报502错误!其次在nginx内部我还想实现“由nginx检查目标文件是否存在,如果存在的话就直接返回给浏览器而无需经过后端程序的处理”,这样一来后端程序只是负责生成目标文件,一单目标文件被生成,基本上就不再提供服务,而nginx则提供全静态的文件浏览服务。可想而知,性能的提升还是大很多的!

怎么启用sendfile?
详细配置步骤就不说了,官方wiki已经说明的比较清楚。只提一下注意点吧:
1,location 必须 被定义为 internal;
2,如果在location中使用alias 一定要注意目录结尾的“/”;
3,要注意location 匹配时尽量只用目录名。 我在测试中遇到抓狂的问题。

先说一下我最终的方案:
1,增加一个location作为目标文件的检查,如果存在 就发给internal的location继续处理,如果不存在就rewrite到后端程序处理;

location ~ ^/vdir/(.*)\.ext$
{
	set $obj_file "$1.ext";
	if (!-f /path/to/obj/dir/$obj_file)
	{
		rewrite ^  /backend/app last;
	}
	rewrite ^ /revdir/$obj_file last;
}

以上代码可实现“由nginx检查目标文件是否存在,如果存在的话就直接返回给浏览器而无需经过后端程序的处理”。
接下来看下sendfile相关的location

location /revdir
{
	internal;
	alias /another/dir/;
	#rewrite (.*) /$1 redirect;	# 用于测试匹配到的数据是否正确,也可以使用 add_header  xxx  $1  来代替
}

程序里送出的header是 :

X-Accel-Redirect: /revdir/a/b/xxx.ext

需要再原本的文件路径前加一个虚拟目录 /revdir/

下面讲一下访客在浏览 http://yourdomain/vdir/d/i/r/xxx.ext时的一些处理过程:
1,nginx会先去检查是否存在目标文件”/path/to/obj/dir/d/i/r/xxx.ext”
2.1,如果文件不存在,就会发起一个rewrite ,将请求发往后端程序处理生成文件,然后后端程序只送出”X-Accel-Redirect”header之后完成处理,nginx接受X-Accel-Redirect会被 location /revdir 匹配到,继而发送该文件;
2.1,如果文件存在,也会发起一个rewrite ,然后会被 location /revdir 匹配到,继而直接发送该文件无需经过后端程序;
3,over.

提醒注意:
如果你在测试中发现nginx报500,首先一个考虑下是不是重复匹配次数达到nginx内部预设的10次上限,然后报500错误。有方法可以验证,适当的location添加:

log_subrequest on;

详细请点击参考官方wiki

最后再提一点,远程文件怎么使用这个功能来转发呢? 不是proxy喔~~
有兴趣的可以参考这里:Nginx-Fu: X-Accel-Redirect From Remote Servers

通过shell+crontab实现自动分割nginx日志

最近有几个朋友问这个事情,干脆写出来吧。。
nginx自身不能按天分割日志,因此还是自己动手来吧~
本文提供的这个脚本会把当前的log文件打包为当前日期为文件名的tgz包,并保存到指定目录。

首先把下面的脚本copy保存为/root/daily_logs.sh

#! /bin/bash

nginx_app=/home/nginx/sbin/nginx #设置nginx的目录
logs_dir=/data/logs/ #log目录
bak_dir=/data/logs/bak/ #log备份目录

#先把现有的log文件挪到备份目录临时存放
cd $logs_dir
echo "moving logs"
/bin/mv *.log $bak_dir
sleep 3

#重建nginx log
echo "rebuild logs"
echo "$nginx_app -s reopen"
$nginx_app -s reopen

#按天打包log文件
echo "begining of tar"
cd $bak_dir
/bin/tar czf `date +%Y%m%d`.tgz *.log

#删除备份目录的临时文件
echo "rm logs"
rm -f *.log
echo "done"

并添加执行权限:

chmod +x /root/daily_logs.sh

然后增加crontab,这里以每晚0点执行为例:

[root@localhost ~]# crontab -e
0 0 * * * /root/daily-task.sh > /dev/null 2>&1

保存后退出,以后就可以自动分割nginx的日志啦~

收工。。

nginx为目录增加auth_basic认证

之前几次配置一直失败,刚才闲来无事试了下。。居然成功了!记录一下

由于nginx的auth_basic认证采用的是与apache兼容密码文件,因此需要用到apache的htpasswd用以生成密码文件。

首先且到root, 安装httpd (如果已经安装的,可以跳过)

/usr/bin/yum install httpd

安装完毕之后就可以先找一下htpasswd的位置

/usr/bin/whereis htpasswd
htpasswd: /usr/bin/htpasswd /usr/share/man/man1/htpasswd.1.gz

可以看到路径是 /usr/bin/htpasswd

接下来就生成密码文件并添加一个用户(master)吧

/usr/bin/htpasswd -c /home/nginx/conf/authdb master

会得到以下提示信息
New password:
输入密码之后,系统会要求再次输入密码。确认之后即添加完毕。

然后就是修改nginx的配置文件,在需要使用auth_basic添加配置;
例如需要在 http://zhys9.com/secret/ 目录使用;

/bin/vi /home/nginx/conf/nginx.conf

找到zhys9.com对应的server段

增加一个location段

location /secret/
{
    auth_basic  "Secret Garden.";
    auth_basic_user_file  /home/nginx/conf/authdb;
}

保存退出之后,要记得reload一下nginx

/home/nginx/sbin/nginx -s reload

ok, 访问http://zhys9.com/secret/ 看看是否生效了?

centos下nginx+php+mysql的自动安装SHELL

今天安装了一下新的测试环境,因为不想反复输入命令。。也就有了本文章。

打算找一找自动安装的脚本,一键安装自然是追求自动化的崇高追求。。gg后发现真的有不少,于是找了一个看了看,没错!是我要的。

因为安装目录、配置方面有些不同于是拿来修改一下就可以方便使用了~

修改后的脚本:lnmp-auto-install

安装目录是:
nginx: /home/nginx
php: /home/php
mysql: /home/mysql
eaccelerator: /home/eaccelerator

至于版本号就不说了吧,基本都是比较新的稳定版本了。

启动nginx:  /etc/init.d/nginx start
启动php-fpm: /home/nginx/sbin/php-fpm start
启动mysql: /etc/init.d/mysql start

感谢原作者Licess’s,以及提供镜像下载的vpser

Nginx 新的开发分支 0.8.1 发布

自从 Nginx 0.7.59 版本发布后, Nginx 将 0.7.x 版本标识为稳定版,并开始下一个开发版本 0.8.x ,该版本为 0.8 系列的第一个发行版本。主要改进内容包括:

Changes with nginx 0.8.1 08 Jun 2009

*) Feature: the “updating” parameter in “proxy_cache_use_stale” and “fastcgi_cache_use_stale” directives.
*) Bugfix: the “If-Modified-Since”, “If-Range”, etc. client request header lines were passed to backend while caching if no “proxy_set_header” directive was used with any parameters.
*) Bugfix: the “Set-Cookie” and “P3P” response header lines were not hidden while caching if no “proxy_hide_header/fastcgi_hide_header” directives were used with any parameters.
*) Bugfix: the ngx_http_image_filter_module did not support GIF87a format.
*) Bugfix: nginx could not be built modules on Solaris 10 and early; the bug had appeared in 0.7.56.

Changes with nginx 0.8.0 02 Jun 2009

*) Feature: the “keepalive_requests” directive.
*) Feature: the “limit_rate_after” directive.
*) Bugfix: XLST filter did not work in subrequests.
*) Bugfix: in relative paths handling in nginx/Windows.
*) Bugfix: in proxy_store, fastcgi_store, proxy_cache, and fastcgi_cache in nginx/Windows.
*) Bugfix: in memory allocation error handling.

下载地址:

nginx-0.8.1, nginx/Windows-0.8.1

nginx 0.7 稳定版本发布

刚刚,,,Igor Sysoev发布了近一年来被广泛使用的轻量级Web服务器Nginx0.7系列最新版本0.7.59,同时正式将0.7做为新的Stable稳定系列(0.7.0由19 May 2008开始开发),此前的稳定系列0.6为0.6.37。
0.7系列的主要改进包括:

*) caching of proxied and FastCGI servers;
*) “try_files” directive;
*) the “location” and “server_name” directives support captures
in regular expressions;
*) XLST and image filters;
*) a preliminary IPv6 support;
*) nginx/Windows.

下载:
0.7.59 http://sysoev.ru/nginx/nginx-0.7.59.tar.gz
Windows平台 http://sysoev.ru/nginx/nginx-0.7.59.zip
改进 http://nginx.net/CHANGES