您当前的位置:首页 > Linux 网站首页Linux
怎样转换nginx日志中的16进制内容为可打印字符
继之前的文章使用ngx_lua记录nginx的Response
最终我们记录的日志是这个样的:
58.56.46.xx - [27/Jun/2017:17:11:03 +0800] [200] - api.xxx.com GET /api/ HTTP/1.1 - RESPONSE:{'code':200010,'msg':'\xE6\x9C\xAA\xE8\x8E\xB7\xE5\x8F\x96\xE5\x88\xB0\xE7\x94\xA8\xE6\x88\xB7\xE7\x9A\x84id\xE4\xBF\xA1\xE6\x81\xAF'}
58.56.46.xx - [27/Jun/2017:17:11:03 +0800] [200] - api.xxx.com GET /api/ HTTP/1.1 - RESPONSE:{'code':200010,'msg':'\xE6\x9C\xAA\xE8\x8E\xB7\xE5\x8F\x96\xE5\x88\xB0\xE7\x94\xA8\xE6\x88\xB7\xE7\x9A\x84id\xE4\xBF\xA1\xE6\x81\xAF'}
实际中也有很多这样的日志
辣么,我们怎么识别这些十六进制的内容呢,好快速的debug,查看接口的输出是否正确。
本文至少介绍三个方法,暂时写一个最简单和一劳永逸的办法。
一、修改nginx源码 (一劳永逸)
我们知道,我们使用的是nginx,nginx的日志是nginx程序创建的,那么伟大的nginx又是开源的,然后呢?
然后继续之前文章中的路径/tmp/nginx-1.11.2/src/http/modules/ngx_http_log_module.c 就可以看到如下的代码,这个是nginx记录日志的源码:
static uintptr_t
ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
{
ngx_uint_t n;
/* 这是十六进制字符表 */
static u_char hex[] = "0123456789ABCDEF";
/* 这是ASCII码表,每一位表示一个符号,其中值为1表示此符号需要转换,值为0表示不需要转换 */
static uint32_t escape[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
if (dst == NULL) {
/* find the number of the characters to be escaped */
n = 0;
while (size) {
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
n++;
}
src++;
size--;
}
return (uintptr_t) n;
/* 返回需要转换的字符总数*/
}
while (size) {
/* escape[*src >> 5],escape每一行保存了32个符号,
所以右移5位,即除以32就找到src对应的字符保存在escape的行,
(1 << (*src & 0x1f))此符号在escape一行中的位置,
相&结果就是判断src符号位是否为1,需不需要转换 */
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
*dst++ = '\\';
*dst++ = 'x';
/* 一个字符占一个字节8位,每4位转成一个16进制表示 */
/* 高4位转换成16进制 */
*dst++ = hex[*src >> 4];
/* 低4位转换成16进制*/
*dst++ = hex[*src & 0xf];
src++;
} else {
/* 不需要转换的字符直接赋值 */
*dst++ = *src++;
}
size--;
}
return (uintptr_t) dst;
}
所 以,
我们需要对代码进行如下修改
static uintptr_t
ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
{
ngx_uint_t n;
/*static u_char hex[] = "0123456789ABCDEF";*/
static uint32_t escape[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
if (dst == NULL) {
/* find the number of the characters to be escaped */
n = 0;
while (size) {
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
n++;
}
src++;
size--;
}
return (uintptr_t) n;
}
while (size) {
/*
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
*dst++ = '\\';
*dst++ = 'x';
*dst++ = hex[*src >> 4];
*dst++ = hex[*src & 0xf];
src++;
} else {
*dst++ = *src++;
}
*/
*dst++ = *src++;
size--;
}
return (uintptr_t) dst;
}
首先注释的是这一段,非常好理解,将转换注释掉,只执行else的部分
/*
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
*dst++ = '\\';
*dst++ = 'x';
*dst++ = hex[*src >> 4];
*dst++ = hex[*src & 0xf];
src++;
} else {
*dst++ = *src++;
}
*/
但 是,注释还是不够的,编译还是会报错,因为上方的的hex就没有用了,会报错
src/http/modules/ngx_http_log_module.c: In function ‘ngx_http_log_escape’:
src/http/modules/ngx_http_log_module.c:975:21: error: unused variable ‘hex’ [-Werror=unused-variable]
所以再注释之,编译即可。
安装完成之后,我们再看一下日志中记录的内容已经变成了可打印字符。不再是16进制这种让人类无法直接看懂的内容了。
二、外部shell文件处理
后续再写
三、外部php脚本处理
后续再写
其他任意你喜欢的脚本处理
转载请注明出处:黄桂林的博客上一篇:使用ngx_lua记录nginx的Response Tags: nginx lua log nginx响应日志 nginx response
下一篇:find命令常用参数 及查找删除N时间之前的文件示例 Tags: find linux 运维 日志