-
这是本人的读书笔记,自己翻译了一下,水平有限,不求太准确,只求自己回头能看懂,各位看官见谅。
原文地址:
http://library.linode.com/web-servers/nginx/configuration/basic 一、全局配置
我们从nginx的默认配置文件开始学习如何配置nginx。
文件: nginx.conf
#user
nobody;
worker_processes1;
#error_loglogs/error.log;
#error_loglogs/error.log notice;
#error_loglogs/error.log info;
#pidlogs/nginx.pid;
events {
worker_connections 1024;
}上边这部分是nginx.conf的前几行,一般情况下不需要修改这些选项。在此处有几个方面需要我们注意:
- 所有以"#"开头的行,都是注释行,nginx不会对其进行处理。
- 指令以一个变量名为开头,后边跟着一个参数(例如 1 或 logs/nginx.pid)或者一系列参数("logs/error.log notice")
- 所有指令都以分号";"结尾。
- 一些指令,例如上边的events,可以包含多个子指令作为参数。这些子指令被大括号{ }封闭。
- 空白字符(tab,空格,换行符)会被忽略,nginx不会对其进行处理。可以使用空白字符增强配置文件的可读性。
-
我们继续向下查看nginx.conf
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65; #gzip on; http {
} 块中的配置一般来说也不需要进行修改。我们着重关注以下几点: - 开头的 include 声明将mime.types文件包含进了nginx.conf中,mime.types文件存放在/opt/nginx/conf/mime.types。虽然使用include声明可以使配置文件显得更有组织和清晰,但是太多的递归include会造成混乱,所以要有节制的使用include。
- 可以将log_format前边的"#"去掉,修改后边的参数,获得自己希望的日志格式
- gzip指令告诉服务器使用"on-the-fly"gzip压缩,以减少传输中所用的带宽。这个指令与Apache的mod_deflate功能一样。
-
如果要激活gzip压缩功能,可以在配置文件中加入如下指令。
gzip on;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain text/html text/css
application/x-javascript text/xml
application/xml application/xml+rss
text/javascript; 使用gzip压缩虽然可以减少一部分带宽消耗,但同时也会增加服务器的CPU消耗。gzip_comp_level的取值可以从1到9,设置为9则消耗最多CPU,设为1消耗最少,默认值是1。
二、server配置
我们接着向下继续查看nginx.conf,请注意,上边的http {
} 到此处才完全封闭,也就是说server的配置也包含在http { }中。 server {
listen 80;
server_name localhost;
access_log logs/localhost.access.log main;
location / {
root html;
index index.html index.htm;
}
}
}Server指令段是大多数用户配置他们服务器的地方。在Server指令段中有不少重要指令。listen指令告诉nginx在一个特定的主机名或IP或TCP端口上监听连接。默认情况下,HTTP服务使用端口80。以下的listen指令都是合法的:
listen
127.0.0.1:80;
listenlocalhost:80;
listen127.0.0.1:8080;
listenlocalhost:8080;
listen192.168.3.105:80;
listen192.168.3.105:8080;
listen80;
listen*:80;
listen8080;
listen*:8080;
listen12.34.56.77:80;
listen12.34.56.78:80;
listen12.34.56.79:80; 上边的例子中列举了一些不同的使用惯例:
- 头两个指令指明服务器应该监听在127.0.0.1或者本地的loopback接口上。localhost是127.0.0.1的主机名,在/etc/hosts定义。
- 第二对指令和第一对的例子一样,就是端口变成了8080。
- 第三对指令指明服务器同时在192.168.3.105的地址上监听80,8080两个端口
- 第四组指令包含4个指令,指明在所有接口上监听指定端口。listen 80和 listen *:80是一模一样的作用。
- 最后一组指令指明服务器在3个不同IP上都监听80端口。
-
server_name指令允许管理员提供"基于主机名的虚拟主机",也就是服务器监听在一个单一IP地址上,但是却可以根据HTTP请求中的header不同而访问不同的域名。请看下边这些示例:
server_name
ducklington.org;
server_nameducklington.org www.ducklington.org;
server_name*.ducklington.org;
server_name.ducklington.org;
server_nameducklington.*;
server_nameducklington.org bucknell.net brackley.org;
server_namelocalhost litchfield bleddington;
server_name""; 独立的server_name使用空白符分隔。nginx允许管理员给服务器配置多个名字,所以一个服务器可以服务多个不同名称的请求。也可以使用通配符"*"和正则表达式来指明虚拟主机名字。我们来分析一下上边示例:
第一组示例,第一行我们指定了server_name为ducklington.org,所以所有访问http://ducklington.org的请求会被这台服务器捕捉到。在第二行中所有访问ducklington.org和www.ducklington.org都会被这台服务器捕捉。
第三行和第四行的作用是相同的,*.ducklington.org和.ducklington.org表达的意思相同,所有基于ducklington.org的二级域名都会被捕捉。(www.ducklington.org,mirrors.ducklington.org等等)
第二组示例,所有以ducklington.开头的域名都会被捕捉,例如ducklington.com, ducklington.net, ducklington.org, ducklington.morris.com, ducklington.dance.org,ducklington.morris.dance.com等等。
第三组示例,所有发往指令中的3个域名的请求都会被捕捉。多个域名可以安全的合并在一个指令中。另外,nginx允许给虚拟主机指定不合法的域名,比如例子中的localhost, litchfiled,和 bleddington。nginx只在HTTP header中搜索指定的名称,而不关心这个名称是否是合法的域名。在这组示例中,主机名可以写在/etc/hosts文件中。
当你的nginx部署在局域网中或者你可以明确知道访问这台主机的用户的时候,使用非合法域名的主机名非常有用。This includes front-end proxy servers that have entries for the IP address that nginx is listening on in their /etc/hosts file.
最后一组示例," "空白引号告诉nginx捕捉那些请求中不包含主机名或包含没有指定的主机名的请求。
我们继续向下看server指令段,access_log指令。
access_log logs/ducklington.access.log;
access_log /srv/http/ducklington.org/logs/access.log;
access_log /var/log/nginx/access/ducklington.org;
access_log off;第一行的log文件位置是相对路径,存储在/opt/nginx/logs/ducklington.access.log
第二、三的log文件位置是绝对路径。
如果不需要access_log,可以将它关闭,不过通常不建议关闭。
server指令段中的最后一个指令是 location。
就像可以使用server_name指令允许nginx根据请求中的信息来相应处理客户发送来的请求一样,location指令允许管理员定义响应不同请求的资源该去什么地方寻找。
location / { }
location /images/ { }
location /blog/ { }
location /planet/ { }
location /planet/blog/ { }
location ~ IndexPage\.php$ { }
location ~ ^/BlogPlanet(/|/index\.php)$ { }
location ~* \.(pl|cgi|perl|prl)$ { }
location ~* \.(md|mdwn|txt|mkdn)$ { }
location ^~ /images/IndexPage/ { }
location ^~ /blog/BlogPlanet/ { }
location = / { }第一组的5行例子,是逐字匹配。匹配请求的主机名以后的部分。假定有一个请求http://ducklington.org/ ,假设server_name配置为ducklington.org,那么"location /"指令会捕捉这个请求。nginx总是使用最精确的匹配来处理请求。例如,一个http://ducklington.org/planet/blog/ 的请求和一个 http://ducklington.org/planet/blog/about/ 的请求,会被"location /planet/blog/" 指令捕捉到,尽管"location /planet/" 也能匹配这2个请求。
当一个location 指令后边跟着一个"~"波浪线符号时,nginx会执行一个正则表达式匹配。这些匹配总是大小写敏感的。所以在第二组,第一行的示例中,包含IndexPage.php的请求会被捕捉,而包含indexpage.php的请求则不会。在第二行的示例中,所有包含/BlogPlanet/ 和/BlogPlanet/index.php的请求会被捕捉,而包含/BlogPlanet, /blogplanet/, /blogplanet/index.php的请求则不会。nginx使用Perl Compatible Regular Expressions (PCRE)正则。
在location指令后便跟着一个"~*"波浪线和星号时,nginx只能给一个正则表达式匹配,但是会忽略大小写。在第三组第一行的示例中,所有后缀为.pl, .PL, .cgi, .CGI, .perl, .Perl, .prl, .PrL的请求都会被捕捉。
第四组示例中的location 指令功能和第一组的相同,所不同的是,当location后边跟着"^~"的时候,它强制nginx停止搜索更多的匹配。在第四组的示例中,"^~ /images/IndexPage/" 和 "^~ /blog/BlogPlanet/"会强制nginx捕捉包含有对应表达式的请求,即便还有其他location指令也可以匹配这个请求。
最后一组示例,"="等号会精确匹配请求的路径,并且使nginx停止搜索其他更详尽的匹配。例如,http://ducklington.org/ 会被捕捉到,但是 http://ducklington.org/index.html 则不会被捕捉。使用精确匹配可以轻微加速请求,尤其是在某些请求特别受欢迎的时候。
location指令的执行顺序如下:
精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。
接下来处理逐字匹配指令,如果使用了"^~",则nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。
接下来处理带有"~"和"~*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配。
当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。
三、Location 配置
一旦nginx为一个给定的请求选择了一个location,那么如何回应这个请求,则是由location指令块中的内容决定的。一个基本的location配置块如下:
location / {
root html;
index index.html index.htm;
}在上边这个例子中,web文档根目录被指定为 html/ 目录,加上nginx的默认安装目录,则绝对路径应该为/opt/nginx/html/。假如有一个针对/blog/includes/style.css的请求,而nginx.conf中没有location指令匹配这个请求,则nginx会去查找/opt/nginx/html/blog/includes/style.css这个文件。如果你喜欢,也可以在root中使用绝对路径。
index指令告诉nginx如果一个请求中不包含文件名,那么文件系统上的哪个文件应该默认被使用。比如请求http://.ducklington.org/ 那么真正访问的资源是/opt/nginx/http/index.html。如果index指令后边有多个文件,则nginx会按照列表的顺序查找,用找到的第一个文件回应。假如index.html找不到,则查找index.htm,如果都找不到,则返回404错误。
让我们来看一个更复杂的例子:
location / {
root /srv/www/ducklington.org/public_html;
index index.html index.htm;
}
location ~ \.pl$ {
gzip off;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:8999;
fastcgi_index index.pl;
fastcgi_param SCRIPT_FILENAME /srv/www/ducklington.org/public_html$fastcgi_script_name;
}在这个例子中,所有结尾带有.pl的请求都会被第二个location指令块处理,在其指令块中指定了fastcgi处理这些请求。如果请求中不包含.pl,则第一个location指令块负责处理,会在/srv/www/ducklington.org/public_html/目录下寻找请求的文件。如果请求中没有指定文件名,则nginx会去寻找index.html和index.htm。如果找不到index指令中定义的2个文件,则返回404错误。
- 请求http://ducklington.org/,如果/srv/www/ducklington.org/public_html/index.html存在,则返回此文件。如果不存在,则查找/srv/www/ducklington.org/public_html/index.htm,如果也不存在,则返回404错误。
- 请求http://ducklington.org/blog/,如果/srv/www/ducklington.org/public_html/blog/index.html存在,则返回此文件。如果不存在,则查找/srv/www/ducklington.org/public_html/blog/index.htm,如果也不存在,则返回404错误。
- 请求http://ducklington.org/tasks.pl,会使用FastCGI处理器执行/srv/www/ducklington.org/public_html/tasks.pl,然后返回处理结果。
- 请求http://ducklington.org/squire/roster.pl,会使用FastCGI处理器执行 /srv/www/ducklington.org/public_html/squire/roster.pl,然后返回处理结果。
-
四、最佳指南
学习了上边的例子,已经让我们有足够的信心去开始尝试编写自己的nignx.conf文件了。以下是一些给管理员的最佳指南。
第一、压缩server指令段的配置,使用include声明来保持配置文件的整洁。
例如对于ducklington.org这个服务器,俄哦们把它的server指令段配置文件存储在/srv/www/ducklington.org/nginx.conf,然或在主配置文件/opt/nginx/conf/nginx.conf中使用include指令。
文件/opt/nginx/conf/nginx.conf:
http {
# [...]
include /srv/www/ducklington.org/nginx.conf;
# [...]
}在本例中,服务器ducklington.org的root目录在/srv/www/ducklington.org/public_html/,如果我们希望将所有nginx相关的文件都放在/opt/nginx/目录下,那么我们可以在/opt/nginx/conf/ducklington.conf中指定root为/opt/nginx/http/ducklington.org/,然后再在http { } 指令段包含这个配置文件。
http {
# [...]
include ducklington.conf;
# [...]
}我们通常建议管理员坚定地保持一个一致的文件命名规范,保持文件的有序和良好的格式可以极大的减少维护nginx服务器的负担。
-
五、access log的分割
-
-
Igor Sysoev(Nginx作者)建议的方法是写如下一个hourly cron执行。
-
date_dir=`date +%Y/%m/%d/%H`
/bin/mkdir -p ${log_dir}/${date_dir} > /dev/null 2>&1
/bin/mv ${log_dir}/access.log ${log_dir}/${date_dir}/access.log
/bin/mv ${log_dir}/error.log ${log_dir}/${date_dir}/error.log
kill -USR1 `cat /var/run/nginx.pid`
/bin/gzip ${log_dir}/${date_dir}/access.log &
/bin/gzip ${log_dir}/${date_dir}/error.log & -
-
另外一种方法是使用logrotate,参考 http://drumcoder.co.uk/blog/2012/feb/03/nginx-and-logrotate/
-
[root@demo ~]#
vi /etc/logrotate.d/nginx
修改里面配置如下:
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
endscript
}
-
一些选项的说明:
daily - 每天做一次日志轮转
missingok - 如果找不到日志可轮转也不报错
rotate 52 - 轮转52次,然后删掉最旧的
mail drumcoder@here.com - 删掉旧日志前,将旧日志发送到这个邮箱
compress - 使用gzip压缩旧日志
delaycompress - 留下一个轮转过的日志不进行压缩,以便进程在需要的时候可以继续向其中写入信息
notifempty - 空文件无需轮转
sharedscripts - 当通知nginx日志已经轮转完毕的时候,只执行一次postrotate脚本,而不是每个文件轮转后都执行