linux nginx log,Nginx 记录日志的几种方法

Nginx的日志记录主机设置

server {

listen       80;

server_name a8z8.com;

root /etc/www/abc;

access_log /var/log/www/abc/access.log;

location / {

index  index.htm index.htm;

}

}

默认情况下,access_log 会使用 combined 的配置来记录访问日志

log_format combined ‘$remote_addr – $remote_user [$time_local]  ‘

‘”$request” $status $body_bytes_sent ‘

‘”$http_referer” “$http_user_agent”‘;

通常这样就足够了。

如果是为了更加方便的日志分析,通常我们会使用特殊字符(如 ^A) 来作为日志字段的分隔符,

这样无论是过滤还是排序都会十分方便。甚至可以直接导入 mysql/hive 中,使用强大的 sql 来做查询分析。

为了排版方便,所有特殊字符都使用了展开的写法,请自行替换 ^A 为 ctrl+v,ctrl+a (nginx 日志格式不支持 \1 的写法)。

自定义日志格式:

server {

listen       80;

server_name a8z8.com;

root /etc/www/abc;

# 更多日志可用字段(基本上都是 nginx 的变量),见

# http://wiki.nginx.org/NginxHttpLogModule#log_format

# http://wiki.nginx.org/NginxHttpUpstreamModule#Variables

# http://wiki.nginx.org/NginxHttpCoreModule#Variables

log_format abc “$remote_addr^A$remote_user^A$time_local^A$request_method^A$uri^A$args^A$server_protocol”

“^A$status^A$body_bytes_sent^A$http_referer”

“^A$http_user_agent”;

access_log /var/log/www/abc/access.log abc;

location / {

index  index.htm index.htm;

}

}

当把日志使用 ^A 分割以后,后续就可以使用 sort 和 grep 之类工具对特定url做分析了,

比如统计各url请求量倒排取前50个

awk -F^A ‘{print $5}’ /var/log/www/abc/access.log | sort | uniq -c | sort -nr | head -50

有时候可能想对记录的字段做一些处理,比如 $arg_q 可能是搜索关键词,记录的时候如果 unescape 一下,

会更方便分析,存储上也会更小,

那么可以使用 NginxHttpSetMiscModule 模块提供的指令(http://wiki.nginx.org/NginxHttpSetMiscModule#set_unescape_uri )实现:

set_unescape_uri $q $arg_q;

log_format abc “$q”;

有时候,我们需要对字段做 hash 转换,可以使用 HttpMapModule 提供的功能(http://wiki.nginx.org/HttpMapModule)

# 需要放到 http 里面,不能放到 server 里

# 根据 url 地址计算分类,便于后续统计

# 具体根据需求做变换就好了

# 第一列是匹配规则,后面的是赋值 ~ 开头的匹配规则是正则

map $uri $typ {

default               -;

~/login              user;

~/my                 user;

~/static             static;

}

log_format abc “$typ^A$uri”;

如果使用 nginx 比较多,可能会尝试使用 if ,建议不要使用,因为nginx的if比较让人混乱。

如果有更多复杂的字段处理需求,可以使用 ngx_lua (http://wiki.nginx.org/HttpLuaModule)。

ngx_lua 里面操作 nginx 变量

# 实现上面 map 类似的功能

# 用法详见 http://wiki.nginx.org/HttpLuaModule#set_by_lua

# lua 语法见 http://www.lua.org/manual/5.1/manual.html#2.4

set_by_lua $typ ”

local uri = ngx.var.uri

local _m = string.match

local v = ‘-’

if _m(uri, ‘^/login’) then

v = ‘user’

elseif _m(uri, ‘^/my’) then

v = ‘user’

elseif _m(uri, ‘^/static’) then

v = ‘static’

end

return v

“;

某些情况下,可能我们的字段处理需要查询缓存(如redis)、数据库(如mysql)等,

这些都是可以使用 ngx_openresty 高效完成的(http://openresty.org/)。

这些功能就不在这一篇详细描述了,后续篇章会补充这些功能。

再描述一些复杂的日志记录功能吧。

有时候我们希望根据请求,来判断是否需要记录这一条日志。

在web的访问日志中这种需求比较少,但是独立的日志收集服务器一般有这样的需求的。

比如我需要判定,请求参数 arg_id 必须存在且为数字的时候我才记录日志,可以这样实现

server {

listen       80;

server_name a8z8.com;

root /etc/www/abc;

log_format abc “$msec^A$args^A$q^A$ie^A$oe^A$ref”

“^A$http_user_agent”;

access_log off;

location / {

# 专门记日志的服务,对非合法请求,直接断开连接 或者根据需求302到自己的站点

# 但是这种302一般不会被用户看到 可以综合考虑做法

# 444 的意义见 http://wiki.nginx.org/HttpRewriteModule#return

return 444;

}

location = /i-log {

internal;

set_unescape_uri $q $arg_q;

set_unescape_uri $ie $arg_ie;

set_unescape_uri $oe $arg_oe;

set_unescape_uri $ref $arg_ref;

# 这个很重要,否则不会记录的

log_subrequest on;

access_log /var/log/www/abc/access.log abc;

# 这个指令需要 HttpEchoModule (http://wiki.nginx.org/HttpEchoModule#echo) 的支持

# 因为这个地址只是为了辅助记录日志,所以不需要返回内容

echo ”;

}

location = /1.gif {

default_type  image/gif;

access_log off;

access_by_lua ”

local q = ngx.var.arg_q

if q then

q = ngx.unescape_uri(q)

if q and #q > 0 then

ngx.location.capture(‘/i-log?’ .. ngx.var.args)

end

end

“;

# 这种请求一般不缓存

add_header Expires “Fri, 01 Jan 1980 00:00:00 GMT”;

add_header Pragma “no-cache”;

add_header Cache-Control “no-cache, max-age=0, must-revalidate”;

# 一般独立记录日志的请求,都会返回一张 1×1 的空白gif图

empty_gif;

}

}

利用这个特性,我们甚至可以合并多个记录为1个http请求,在 ngx_lua 内再将多条记录拆分记录到日志文件

比如上例,我门可以添加一个字段 n 来标识有几条记录,并且给 q 之类的参数编号 q_1 .. q_n 。

# GET /1.gif?n=2&q_1=a&q_2=b&ie=gbk&oe=utf8&ref=

# 其他代码不变,只修改 1.gif 的 access_by_lua 为以下代码

local n = ngx.var.arg_n

if n then

n = tonumber(n)

if n > 0 then

local logs = {}

local prefix = string.format(‘/i-log?ie=%s&oe=%s&ref=%s&q=’, ngx.var.arg_ie, ngx.var.arg_oe, ngx.var.arg_ref)

while n >= 1 do

– 这里可以对 q_n 做进一步的校验,看是否需要记录下来

table.insert(logs, {prefix .. (ngx.var['arg_q_' .. n] or ”)})

n = n – 1

end

– 见 http://wiki.nginx.org/HttpLuaModule#ngx.location.capture_multi

ngx.location.capture_multi(logs)

end

end

如果请求量较大,一把需要添加写buffer,

方式为在每条 access_log 后面添加 buffer=32k 这样的设置(见http://wiki.nginx.org/NginxHttpLogModule#access_log)

缓存的大小可以设置成 可以忍受丢失的记录数*每条记录的size

至此,各种记录功能都完成啦。

日志服务其他必要的功能,就是日志轮转了。

nginx 日志轮转的原理是

# 启动nginx收日志

# 启用cron任务

## 将日志文件move走 (文件名可以带上时间戳)

## 给 nginx master 进程发送 USR1 信号(nginx就会重新打开新的日志文件)

### 否则,日志会仍然记录到之前的日志文件中,虽然被 move 了

## cron 的频度可以根据日志大小调整,尽可能大些,能以天为单位就不要以半天为单位0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值