Nginx 常用变量汇总及测试

一、背景

Nginx 的变量在 Nginx 的使用中还是占了一定的重要性,尤其是在日志和 rewrite 中,必须对各种变量的含义有所了解,才能组合出适合自己的日志格式和更高级的 rewrite 规则。其次了解 Nginx的变量含义也有助于调试 Nginx 和优化 Nginx。

二、常见变量

  下面列出的变量都是根据 Nginx 官网的变量列表结合平时的使用,整理的一些常用的变量,对于这些变量,有必要了解并记住其含义。

$args
$arg_PARAMETER
$is_args
$http_HEADER
$http_user_agent
$http_cookie
$sent_http_HEADER
$cookie_COOKIE
$request_body_file
$request_filename
$request_body
$request_method
$request_uri
$content_length
$content_type
$document_root
$document_uri
$remote_addr
$remote_port
$remote_user
$server_protocol
$server_addr
$server_name
$server_port
$binary_remote_addr
$host
$hostname
$scheme
$uri
$limit_rate
$query_string
$realpath_root
$proxy_add_x_forwarded_for
$proxy_host
$proxy_port
$proxy_protocol_addr
$upstream_addr
$upstream_cache_status
$upstream_cookie_
$upstream_http_
$upstream_response_length
$upstream_response_time
$upstream_status 

三、变量含义

1、测试环境

OS: CentOS 6.4x64
hostname: test1.lxm.com
ip: 10.0.10.11
function: Nginx 前端代理,主要用来测试 Nginx 的各变量

OS: CentOS 6.4x64
hostname: test2.lxm.com
ip: 10.0.10.12
function: LNMP 后端服务器,用来提供一个简单的测试页面而已(主要是为了测试前端 Nginx 反向代理到后端的变量值)

2、环境搭建

  为了展示测试的效果,此次测试需要安装一个 Nginx 的第三方模块:echo-nginx-module-0.55.tar.gz. 借助于该模块中的一个指令echo 可以将个变量的值输出到终端上,给各位一个直观的感受,避免盲目的文字介绍,搞的头晕脑胀,也省的自己记错了。。。

安装 echo-nginx-module-0.55.tar.gz

  在我的测试环境中,已经安装好了 Nginx,此时要再安装第三方模块,则要使用下面的方法:

# cd /root/soft
# tar -zxvf nginx-1.6.1.tar.gz
# cd nginx-1.6.1
# ./configure --prefix=/usr/local/nginx/ --with-pcre --with-http_ssl_module --with-openssl=/root/soft/openssl-1.0.1i --with-http_gzip_static_module --with-http_realip_module --with-http_stub_status_module --http-client-body-temp-path=/usr/local/nginx/client_body_temp/ --http-proxy-temp-path=/usr/local/nginx/proxy_temp/ --http-fastcgi-temp-path=/usr/local/nginx/fastcgi_temp/ --http-uwsgi-temp-path=/usr/local/nginx/uwsgi_temp/ --http-scgi-temp-path=/usr/local/nginx/scgi_temp/ --add-module=../echo-nginx-module-0.55
# make 
# /usr/local/nginx/sbin/nginx -s stop
#cp -p objs/nginx /usr/local/nginx/sbin/nginx  //覆盖掉原先的nginx执行文件

  说明:
  ① --add-module
  该选项是 Nginx 的一个编译参数,用来添加额外的第三方模块。因此可知,对任何第三方模块都是使用该方法来添加进 Nginx 中。
  ② 以上的安装可见没有 make install 这一步,这是因为我已经安装了 Nnginx,我只需要更新我的可执行程序,而其他的文件我不需要更新,这也是 Nginx 升级的原理。如果没有安装过 Nginx,则需要 make install 这一步。


附:ngx_echo 模块的下载地址:GitHub

  测试 echo 指令是否可用:

# vim /usr/local/nginx/conf/nginx.conf //修改配置文件,添加一个server段做测试,配置如下:
 server {
        listen 80;
        server_name c.lxm.com;
        access_log /data/logs/access.log main;
        location / {
                root /data;
                index index.html index.htm;
        }
        location /test {
            set $foo "hello world";
            echo "foo: $foo";
        }

  由上面的信息可知,这里我使用了一个 /test 接口来测试 echo 指令是否可用。
  注:有的人可能会问,什么叫接口啊?说白了接口就是一个访问路径,访问入口而已,通过这个入口可以进行交互的作用。。其次这里的 set 是设置变量的指令,更多信息请看官方文档,这个不是该文档要讨论的。

# echo "10.0.10.11  c.lxm.com" >> /etc/hosts
# service nginx configtest
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# service nginx restart
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
Stopping nginx:                                            [  OK  ]
Starting nginx:                                            [  OK  ]
# curl http://c.lxm.com/test
foo: hello world     //成功的输出了信息

  到此,可以确定第三方模块添加成功,echo 指令也可以使用了。。。。

3、变量测试

① 第一组:

  修改配置文件 nginx.conf,将 test 接口改为如下配置:

  location /test {
            echo "args: $args";
            echo "name: $arg_name";
            echo "sex : $arg_sex";
            echo "is_args: $is_args";
        }

  访问测试:

# curl 'http://c.lxm.com:80/test?name=lxm&sex=man'    //注意:这里的测试 url 要加上引号,表示加上参数一起是一个完成的 url
args: name=lxm&sex=man
name: lxm
sex : man
is_args: ?

  由上面的测试信息,来解释下面几个变量:

  • $args //该变量用来获取url后面的所有参数,?表示参数的起始处;
  • $arg_PARAMETER //这是参数的一个匹配模式, PARAMETER 为具体的参数名;
  • $arg_PARAMETER //表示获取具体的参数值,例如上面的 $arg_name 就是获取 url 中 name 的值;
  • $is_args //判断url是否带参数,如果带,则返回一个?,否则返回一个空字符串。

② 第二组:

  • $http_HEADER //使用该方式来获取 http 请求头部中的值,HEADER 是一个匹配模式,匹配请求头部中 key:value 中的可以,返回的是 value;
  • $sent_http_HEADER //使用该方式来获取 http 响应头部中的值,HEADER 是一个匹配模式,匹配响应头部中 key:value 中的可以,返回的是 value。

  由于这个涉及到 http 请求流的问题,这里采用日志的形式展示效果,如果用 echo 来返回,有点东西测试不出来。
新建一日志格式:

 log_format  test  '$http_user_agent $sent_http_content_type $sent_http_content_length';

  修改 test 接口的 server 部分:

   server {
        listen 80;
        server_name c.lxm.com;
        access_log /data/logs/access.log test;
        location / {
                root html;
                index index.html index.htm;
        }
        location /test {
                root html;
                index   index.html index.htm;
        }
    } 
# service nginx configtest
# service nginx restart
# curl http://c.lxm.com/test/index.html
<h1>welcome to my variables test</h1>
# curl -I http://c.lxm.com/test/index.html  //获取的是响应头中的信息 
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 01 Sep 2014 06:56:18 GMT
Content-Type: text/html
Content-Length: 38
Last-Modified: Mon, 01 Sep 2014 06:43:54 GMT
Connection: keep-alive
ETag: "540415aa-26"
X-Cache-TEST:  - 
Accept-Ranges: bytes
# tail -f access.log 
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0 text/html 38
curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2 text/html 38

  由上面的访问测试和日志显示,变量成功获取到了值。。

  • $http_user_agent //获取的是客户端访问代理的类型,请求头中的信息;
  • $sent_http_content_type //获取的是 http 响应头中 content_type 的值;
  • $sent_http_content_length //获取的是 http 响应头重的 content_length 的值。

注意:在变量中的字符串一律是小写,虽然在请求头和响应头中的字符串可能有大写,但是 nginx 会一律将其转换为小写之后进行匹配。
此外,要想知道 http 请求头和响应头中都有些什么内容,建议使用火狐浏览器的 F12 调试功能中的网络功能,来获取请求头和响应头的信息。
还要扒拉一句的是:虽然这两个变量可以获取头部中的信息值,但是经过我的测试,并不是对所有的都有效,起码在响应头中的 date 和 server,本人没测试成功,总是返回空值。或许你该注意。

③ 第三组:
  配置文件如下:

 server {
        listen 80;
        server_name c.lxm.com;
        access_log /data/logs/access.log test;
        location / {
                root html;
                index index.html index.htm;
        }
        location /test {
        proxy_pass http://backend;
        proxy_redirect off;
        echo "uri: $uri";
        echo "request_uri: $request_uri";
        echo "request_method: $request_method";
        echo "request_filename: $request_filename";
        echo "content_length: $content_length";
        echo "content_type: $content_type";
        echo "document_root: $document_root";
        echo "document_uri: $document_uri";
        echo "server_addr: $server_addr";
        echo "server_name: $server_name";
        echo "server_port: $server_port";
        echo "server_protocol: $server_protocol";
        echo "host: $host";
        echo "hostname: $hostname";
        echo "remote_addr: $remote_addr";
        echo "remote_user: $remote_user";
        echo "remote_port: $remote_port";
  }
 } 
# service nginx configtest
# service nginx restart
# curl 'http://c.lxm.com:80/test/index.html?name=lxm&sex=man'
uri: /test/index.html
request_uri: /test/index.html?name=lxm&sex=man
request_method: GET
request_filename: /usr/local/nginx//html/test/index.html 
content_length: 
content_type: 
document_root: /usr/local/nginx//html
document_uri: /test/index.html
server_addr: 10.0.10.11
server_name: c.lxm.com
server_port: 80
server_protocol: HTTP/1.1
host: c.lxm.com
hostname: test1.lxm.com
remote_addr: 10.0.10.11
remote_user: 
remote_port: 57292

  根据上面的输出信息,来解释一下下面的变量:

  • $request_filename //该变量获取的是请求的文件在 Linux 服务器上的完整的绝对路径;
  • $request_method //该表示获取的是 http 请求的方法;
  • $request_uri //该变量表示的原始请求的 uri,包括参数。所谓原始请求就是即使在内部做了重定向之后也不会变化;
  • $uri //获取的是当前请求的 uri,不包括参数;
  • $content_length //获取的是 http 请求头中 Content-Length 的值,不过这里似乎没显示,抱歉这里的测试页面中没有该字段;
  • $content_type //获取的是 http 请求头中的 Content-Type 字段,不过这里也没显示;
  • $document_root //获取的是请求 url 的文件所在的目录路径;
  • $document_uri //当前请求的 uri,从上面的信息来看,和 uri 的效果是一样的;
  • $remote_addr //获取的是客户端的ip地址,这里为什么是10.0.10.11呢,因为我是在本机上用curl测试的,即使客户端也是服务器;
  • $remote_port //获取客户端的访问端口,这个端口是随机的;
  • $remote_user //获取客户端的认证用户信息,这里因为没有用认证,所谓显示为空;
  • $server_protocol //表示服务器端想客户端发送响应的协议;
  • $server_addr //服务器的地址;
  • $server_name //客户端访问服务端的域名,即 url 中的域名;
  • $server_port //服务器端做出响应的端口号;
  • $binary_remote_addr //显示二进制的客户端地址;
  • $host //和 server_name 一样,表示的是域名;
  • $hostname //表示服务器端的主机名。

④ 第四组:
  对于这一组使用日志的形式来展示。
  修改配置文件 nginx.conf:

log_format   testproxy  '$proxy_add_x_forwarded_for $proxy_host $proxy_port $proxy_protocol_addr $upstream_addr $upstream_cache_status $upstream_response_length $upstream_response_time $upstream_status';

server {
       listen      80;
        server_name  a.lxm.com b.lxm.com c.liwei.com;
        #charset koi8-r;
        access_log  logs/host.access.log  testproxy;
        #location / {
        #    root   html;
        #    index  index.html index.htm;
        #    auth_basic "relam authentication";
        #    auth_basic_user_file /usr/local/nginx/htpasswd;
        #}
        location / {
                root html;
                proxy_redirect off;
                proxy_pass   http://backend;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
                proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header;
                proxy_cache cache_one;
                proxy_cache_valid 200 302 1h;
                proxy_cache_valid 301 1d;
                proxy_cache_valid any 1m;
                expires 30d;
        }
}  //注意:上面的内容是nginx配置文件的一个片段,只是跟我们的测试内容相关而已  
#service nginx configtest
#service nginx restart

启动 nginx 之后,使用浏览器访问,然后看日志:

# tail -f host.access.log 
10.0.10.254 backend 80  10.0.10.12:80 MISS 91 0.004 200
10.0.10.254 backend 80  - HIT - - -

根据上面的信息,来解释一下下面的变量:

  • $proxy_add_x_forwarded_for :获取的是客户端的真实 ip 地址;
  • $proxy_host :该变量获取的是 upstream 的上游代理名称,例如 upstream backend;
  • $proxy_port //该变量表示的是要代理到的端口;
  • $proxy_protocol_addr //代理头部中客户端的 ip 地址,或者是一个空的字符串;
  • $upstream_addr //代理到上游的服务器地址信息;
  • $upstream_cache_status //proxy 的缓存状态,例如这里第一次访问为 MISS,第二次访问时为 HIT;
  • $upstream_response_length //上游服务器响应报文的长度;
  • $upstream_response_time //上游服务器响应的时间;
  • $upstream_status //上游服务器响应的状态码。

⑤ 第五组:
  配置文件 nginx.conf:

 server {
        listen 80;
        server_name c.lxm.com;
        access_log /data/logs/access.log test;
        location / {
                root html;
                index index.html index.htm;
        }
        location /test {
  echo "scheme: $scheme";
        echo "limit_rate: $limit_rate";
        echo "query_string: $query_string";
        echo "realpath_root: $realpath_root";
        }
    }
#service nginx configtest
#service nginx restart

  测试:

# curl 'http://c.lxm.com:80/test/index.html?name=lxm&sex=man'
scheme: http
limit_rate: 0
query_string: name=lxm&sex=man
realpath_root: /usr/local/nginx/html

根据上面的信息,解释下面几个变量;

  • $scheme //表示的是使用 http 的访问协议 http or https;
  • $limit_rate //表示当前连接的限速是多少,0 表示无限制;
  • $query_string //表示的是查询字符串,也就是 url 中的参数,和 $args 一样;
  • $realpath_root //表示的是请求页面的真实所在目录的路径 和 $document_root 是一样的。

到此,关于 nginx 的常用变量就聊到这个地方,这并不是 nginx 变量的全部,但是确实是我们常见的变量,因此,有必要去了解一下其含义。


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 linuxnginx变量 的文章

 本文最后更新于 2020/08/31 14:42:22,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > 系统 > Nginx 常用变量汇总及测试