Nginx http filter异常排查

访问异常

root@cloud:/usr/local/nginx# curl -i curl: (52) Empty reply from server

错误日志

2016/09/11 13:17:03 [alert] 63560#0: worker process 63663 exited on signal 11 (core dumped)

dmesg信息

[265950.220943] nginx[63663]: segfault at 128 ip 000000000048259d sp 00007ffde898eab0 error 4 in nginx[400000+a5000]

core dump设置
默认Worker进程用户nobody:nogroup,无法写coredump. 需在nginx.conf配置:

worker_rlimit_core 1024m; #1G working_directory /tmp/core #保证nobody:nogroup有W权限

执行"sbin/nginx -s reload"重新加载配置。

core dump分析

使用readelf工具
core dump是ELF格式文件,你可以用readelf -a 查看core dump文件,但哪只是一堆数据。

使用gdb工具

gdb <command> <core>

一般会直接显示出错的代码位置

位置1

conf = ngx_http_conf_get_module_loc_conf(r,ngx_http_myfilter_module); #应该是ngx_http_get_module_loc_conf(...)

位置2

myfilter_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module); if (ctx->add_prefix != 1) { 应该先判断ctx == NULL return next_body_filter(r, in); }

Nginx http filter示例源码

ngx_addon_name=ngx_http_myfilter_module HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_myfilter_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_myfilter_module.c" #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static ngx_str_t filter_prefix = ngx_string("[my filter prefix]"); static ngx_http_output_header_filter_pt next_header_filter; static ngx_http_output_body_filter_pt next_body_filter; typedef struct { ngx_flag_t enable; } myfilter_conf_t; typedef struct { ngx_int_t add_prefix; } myfilter_ctx_t; static ngx_int_t myfilter_header_filter(ngx_http_request_t *r); static ngx_int_t myfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in); static ngx_int_t myfilter_init(ngx_conf_t *cf); static void *myfilter_create_loc_conf(ngx_conf_t *cf); static char *myfilter_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_http_module_t myfilter_conf = { NULL, myfilter_init, NULL, NULL, NULL, NULL, myfilter_create_loc_conf, myfilter_merge_loc_conf }; static ngx_command_t myfilter_commands[] = { { ngx_string("add_prefix"), NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(myfilter_conf_t, enable), NULL }, ngx_null_command }; ngx_module_t ngx_http_myfilter_module = { NGX_MODULE_V1, &myfilter_conf, myfilter_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING }; static ngx_int_t myfilter_init(ngx_conf_t *cf){ next_header_filter = ngx_http_top_header_filter; next_body_filter = ngx_http_top_body_filter; ngx_http_top_header_filter = myfilter_header_filter; ngx_http_top_body_filter = myfilter_body_filter; return NGX_OK; } static ngx_int_t myfilter_header_filter(ngx_http_request_t *r){ myfilter_conf_t *conf; myfilter_ctx_t *ctx; if(r->headers_out.status != NGX_HTTP_OK){ return next_header_filter(r); } ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module); if(ctx){ return next_header_filter(r); } conf = ngx_http_get_module_loc_conf(r,ngx_http_myfilter_module); if(conf == NULL || conf->enable == 0){ return next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(myfilter_ctx_t)); if(ctx == NULL){ return NGX_ERROR; } ctx->add_prefix = 0; ngx_http_set_ctx(r, ctx, ngx_http_myfilter_module); r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY; ngx_str_t keys = ngx_string("Location"); ngx_str_t vals = ngx_string("http://www.163.com"); ngx_table_elt_t *headers = ngx_list_push(&r->headers_out.headers); if(headers){ headers->key.data = keys.data; headers->key.len = keys.len; headers->value.data = vals.data; headers->value.len = vals.len; headers->hash = 1; } // if (r->headers_out.content_type.len >= sizeof("text/plain") - 1 // && ngx_strncasecmp(r->headers_out.content_type.data, // (u_char *) "text/plain", sizeof("text/plain") - 1) == 0) { ctx->add_prefix = 1; if(r->headers_out.content_length_n > 0){ r->headers_out.content_length_n += filter_prefix.len; } // } return next_header_filter(r); } static ngx_int_t myfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { myfilter_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module); if (ctx == NULL || ctx->add_prefix != 1) { return next_body_filter(r, in); } ctx->add_prefix = 2; ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len); b->start = b->pos = filter_prefix.data; b->last = b->pos + filter_prefix.len; ngx_chain_t *cl = ngx_alloc_chain_link(r->pool); cl->buf = b; cl->next = in; return next_body_filter(r, cl); } static void *myfilter_create_loc_conf(ngx_conf_t *cf) { myfilter_conf_t *mycf; mycf = (myfilter_conf_t *)ngx_pcalloc(cf->pool, sizeof(myfilter_conf_t)); if(mycf == NULL) return NULL; mycf->enable = NGX_CONF_UNSET; return mycf; } static char *myfilter_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child){ myfilter_conf_t *prev = (myfilter_conf_t *)parent; myfilter_conf_t *conf = (myfilter_conf_t *)child; ngx_conf_merge_value(conf->enable, prev->enable, 0); return NGX_CONF_OK; }

--------------------------------------分割线 --------------------------------------

Nginx负载均衡配置实战 

CentOS 6.2实战部署Nginx+MySQL+PHP

使用Nginx搭建WEB服务器

搭建基于Linux6.3+Nginx1.2+PHP5+MySQL5.5的Web服务器全过程

CentOS 6.3下Nginx性能调优

CentOS 6.3下配置Nginx加载ngx_pagespeed模块

CentOS 6.4安装配置Nginx+Pcre+php-fpm

Nginx安装配置使用详细笔记

Nginx日志过滤 使用ngx_log_if不记录特定日志

--------------------------------------分割线 --------------------------------------

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/975d56a1fce345a20cb9cc0e57faa74b.html