技术员联盟提供win764位系统下载,win10,win7,xp,装机纯净版,64位旗舰版,绿色软件,免费软件下载基地!

当前位置:主页 > 教程 > 服务器类 >

Nginx的error_log和Access_log分析

来源:技术员联盟┆发布时间:2018-05-27 06:24┆点击:

  nginx配置中有关日志的配置主要是围绕着下面两个指令:

  1、error_log

  2、access_log:记录访问日志

  首先要强调的一点是,如果access日志和error日志都是常量文件名(因为access支持变量文件名,后续会讲到),那么nginx进程会缓存文件描述符直到进程结束。

  什么时候日志的fd会改变呢?

  1)进程重启

  2)收到了NGX_REOPEN_SIGNAL信号,会产生新的日志文件

  其他情况下,日志的fd不变,所以当进程运行中,删除了日志文件的话,并不会生成新的日志文件,且日志都会丢失

  下面详细讲一下这两个指令的来龙去脉

  一:先说error_log:

  nginx有两个模块支持error_log指令:

  一个是 ngx_errlog_module ,这个模块只有一个指令,就是error_log ,配置类型为:NGX_MAIN_CONF,回调函数为:ngx_error_log;

  另一个是 ngx_http_core_module,这个模块中也有指令:error_log ,配置类型为:NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF,回调函数为:ngx_http_core_error_log。

  static ngx_command_t ngx_errlog_commands[] = {

  {ngx_string("error_log"),

  NGX_MAIN_CONF|NGX_CONF_1MORE,

  ngx_error_log,

  0,

  0,

  NULL},

  ngx_null_command

  };

  static ngx_command_t ngx_http_core_commands[] = {

  { ngx_string("error_log"),

  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,

  ngx_http_core_error_log,

  NGX_HTTP_LOC_CONF_OFFSET,

  0,

  NULL },

  }

  这样会产生几个疑问:

  1:为什么需要两个相同的指令实现相同的功能。

  2:两个指令的类型均支持NGX_HTTP_MAIN_CONF ,那么在main中配置的error_log到底使用的是哪一个

  3:两者的作用关系。

  下面来解释一下:

  nginx在进行模块注册时,会发现 ngx_errlog_module 模块是先于 ngx_http_core_module 模块注册的 。

  在nginx在解析配置文件的时候 ,见到 error_log,会按照注册模块的顺序查找指令,这样,会先找到ngx_errlog_module模块,如果此时,error_log是在main配置的,那么和ngx_errlog_module模块error_log的NGX_HTTP_MAIN_CONF match,执行ngx_error_log。

  如果error_log是在http{}配置的,也会按照注册模块的顺序查找指令,找到ngx_errlog_module模块的error_log,发现type是NGX_HTTP_MAIN_CONF,不match,继续往下找,找到ngx_http_core_module的error_log,type是NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF ,match后执行ngx_http_core_error_log。

  上面提到了ngx_error_log 和 ngx_http_core_error_log两个函数,这两个函数的功能基本一致,但是因为两个配置作用域不同,所以配置存储位置不同:ngx_errlog_module存储在cycle->new_log,ngx_http_core_module存储在http core模块数据结构ngx_http_core_loc_conf_s的error_log(在此简写成:clcf->error_log)。

  clcf->error_log是http模块中的,其主要记录和http请求相关的日志。

  cycle->new_log主要记录如进程启动,event等。

  但是主进程启动的时候,此时还没有读取配置文件,即没有指定日志打印在哪里。nginx这时候虽然可以将一些出错内容或者结果输到标准输出,但是如果要记录一些系统初始化情况,socket监听状况,还是需要写到日志文件中去的。在nginx的main函数中,首先会调用ngx_log_init 函数,默认日志文件为:安装路径/logs/error.log,如果这个文件没有权限访问的话,会直接报错退出。在mian函数结尾处,在ngx_master_process_cycle函数调用之前,会close掉这个日志文件。

  如果只在main配置了error_log,http{}中没有设置,那么clcf->error_log赋值为clcf->error_log,如下:

  static char *

  ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)

  {

  ngx_http_core_loc_conf_t *prev = parent;

  ngx_http_core_loc_conf_t *conf = child;

  。。。。。。

  if (conf->error_log == NULL) {

  if (prev->error_log) {

  conf->error_log = prev->error_log;

  } else {

  conf->error_log = &cf->cycle->new_log;

  }

  }

  。。。。。。

  }

  那为什么不把两个指令合并到一起呢。

  首先看一下模块注册顺序:

  ngx_module_t *ngx_modules[] = {

  &ngx_core_module,

  &ngx_errlog_module,

  &ngx_conf_module,

  &ngx_events_module,

  &ngx_event_core_module,

  &ngx_rtsig_module,

  &ngx_epoll_module,

  &ngx_regex_module,

  &ngx_http_module,

  &ngx_http_core_module,

  &ngx_http_log_module,

  ......

  }

  可见ngx_errlog_module 和 ngx_http_core_module中间有n多模块。这些模块是独立于http的,而且需要日志的打印,这些日志肯定是需要记录的。

  则此模块不可省,那么考虑把ngx_http_core_module的error_log合并过来呢,想想也不行,为什么呢?

  想想ngx_errlog_module将error_log信息存在哪里,想想ngx_http_core_module的error_log信息存在哪里。

  在调用ngx_error_log时候,把针对不同server或者location的error_log信息存储在哪里。(模块之间不能深度耦合)

  为了两个模块互不影响,这是个好办法呀!

  二:access_log

  接下来看一下access_log,access_log指令是属于ngx_http_log_module模块。

  ngx_http_log_module有三个指令:

  static ngx_command_t ngx_http_log_commands[] = {

  { ngx_string("log_format"),

  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,

  ngx_http_log_set_format,

  NGX_HTTP_MAIN_CONF_OFFSET,

  0,

  NULL },

  { ngx_string("access_log"),

  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF

  |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,

  ngx_http_log_set_log,

  NGX_HTTP_LOC_CONF_OFFSET,

  0,

  NULL },

  { ngx_string("open_log_file_cache"),

  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,

  ngx_http_log_open_file_cache,

  NGX_HTTP_LOC_CONF_OFFSET,

  0,

  NULL },

  ngx_null_command

  };