├── README.md ├── config ├── nginx_sysguard_1.2.5.patch ├── nginx_sysguard_1.3.9.patch ├── ngx_http_sysguard_module.c ├── ngx_sysinfo.c └── ngx_sysinfo.h /README.md: -------------------------------------------------------------------------------- 1 | ##Description 2 | 3 | This module can be used to protect your server in case system load or memory use goes too high.
4 | It comes from [Tengine](http://tengine.taobao.org), an Nginx distribution with quite a few advanced features. 5 | 6 | ###Examples: 7 | 8 | server { 9 | sysguard on; 10 | 11 | sysguard_load load=10.5 action=/loadlimit; 12 | sysguard_mem swapratio=20% action=/swaplimit; 13 | 14 | location /loadlimit { 15 | return 503; 16 | } 17 | 18 | location /swaplimit { 19 | return 503; 20 | } 21 | } 22 | 23 | ##Installation 24 | 25 | $ wget http://www.nginx.org/download/nginx-1.2.5.tar.gz 26 | $ tar xzvf nginx-1.2.5.tar.gz 27 | 28 | $ cd nginx-1.2.5 29 | $ git clone https://github.com/taobao/nginx-http-sysguard.git 30 | $ patch -p1 < nginx-http-sysguard/nginx_sysguard_1.2.5.patch 31 | 32 | $ ./configure --add-module=./nginx-http-sysguard 33 | # make && make install 34 | 35 | ##Directives 36 | 37 | **Syntax**: ***sysguard*** [on | off] 38 | **Default**: sysguard off 39 | **Context**: http, server, location 40 | 41 | Turn on or off this module. 42 |
43 | 44 | **Syntax**: ***sysguard_load*** load=number [action=/url] 45 | **Default**: none 46 | **Context**: http, server, location 47 | 48 | Specify the load threshold. When the system load exceeds this threshold, all subsequent requests will be redirected to the URL specified by the 'action' parameter. Nginx will return 503 if there's no 'action' URL defined. 49 |
50 | 51 | **Syntax**: ***sysguard_mem*** swapratio=ratio% [action=/url] 52 | **Default**: none 53 | **Context**: http, server, location 54 | 55 | Specify the used swap memory threshold. When the swap memory use ratio exceeds this threshold, all subsequent requests will be redirected to the URL specified by the 'action' parameter. Nginx will return 503 if there's no 'action' URL. 56 |
57 | 58 | **Syntax**: ***sysguard_interval*** time 59 | **Default**: sysguard_interval 1s 60 | **Context**: http, server, location 61 | 62 | Specify the time interval to update your system information. The default value is one second, which means Nginx updates the server status once a second. 63 |
64 | 65 | **Syntax**: ***sysguard_log_level*** [info | notice | warn | error] 66 | **Default**: sysguard_log_level error 67 | **Context**: http, server, location 68 | Specify the log level of sysguard. 69 |
-------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_sysguard_module 2 | HTTP_MODULES="$HTTP_MODULES ngx_http_sysguard_module" 3 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_sysguard_module.c $ngx_addon_dir/ngx_sysinfo.c" 4 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/ngx_sysinfo.h" 5 | HTTP_INCS="$HTTP_INCS $ngx_addon_dir" 6 | 7 | 8 | ngx_feature="sysinfo()" 9 | ngx_feature_name="NGX_HAVE_SYSINFO" 10 | ngx_feature_run=no 11 | ngx_feature_incs="#include " 12 | ngx_feature_path= 13 | ngx_feature_libs= 14 | ngx_feature_test="struct sysinfo s; 15 | sysinfo(&s);" 16 | . auto/feature 17 | 18 | 19 | ngx_feature="getloadavg()" 20 | ngx_feature_name="NGX_HAVE_GETLOADAVG" 21 | ngx_feature_run=no 22 | ngx_feature_incs="#include " 23 | ngx_feature_path= 24 | ngx_feature_libs= 25 | ngx_feature_test="double loadavg[1]; 26 | getloadavg(loadavg, 1);" 27 | . auto/feature 28 | -------------------------------------------------------------------------------- /nginx_sysguard_1.2.5.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h 2 | index c2651a8..f28ebbb 100644 3 | --- a/src/http/ngx_http_request.h 4 | +++ b/src/http/ngx_http_request.h 5 | @@ -491,6 +491,7 @@ struct ngx_http_request_s { 6 | */ 7 | unsigned limit_conn_set:1; 8 | unsigned limit_req_set:1; 9 | + unsigned sysguard_set:1; 10 | 11 | #if 0 12 | unsigned cacheable:1; 13 | -------------------------------------------------------------------------------- /nginx_sysguard_1.3.9.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h 2 | index f234840..b7665e9 100644 3 | --- a/src/http/ngx_http_request.h 4 | +++ b/src/http/ngx_http_request.h 5 | @@ -489,6 +489,7 @@ struct ngx_http_request_s { 6 | */ 7 | unsigned limit_conn_set:1; 8 | unsigned limit_req_set:1; 9 | + unsigned sysguard_set:1; 10 | 11 | #if 0 12 | unsigned cacheable:1; 13 | -------------------------------------------------------------------------------- /ngx_http_sysguard_module.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2012 Alibaba Group Holding Limited 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | typedef struct { 14 | ngx_flag_t enable; 15 | ngx_int_t load; 16 | ngx_str_t load_action; 17 | ngx_int_t swap; 18 | ngx_str_t swap_action; 19 | time_t interval; 20 | 21 | ngx_uint_t log_level; 22 | } ngx_http_sysguard_conf_t; 23 | 24 | 25 | static void *ngx_http_sysguard_create_conf(ngx_conf_t *cf); 26 | static char *ngx_http_sysguard_merge_conf(ngx_conf_t *cf, void *parent, 27 | void *child); 28 | static char *ngx_http_sysguard_load(ngx_conf_t *cf, ngx_command_t *cmd, 29 | void *conf); 30 | static char *ngx_http_sysguard_mem(ngx_conf_t *cf, ngx_command_t *cmd, 31 | void *conf); 32 | static ngx_int_t ngx_http_sysguard_init(ngx_conf_t *cf); 33 | 34 | 35 | static ngx_conf_enum_t ngx_http_sysguard_log_levels[] = { 36 | { ngx_string("info"), NGX_LOG_INFO }, 37 | { ngx_string("notice"), NGX_LOG_NOTICE }, 38 | { ngx_string("warn"), NGX_LOG_WARN }, 39 | { ngx_string("error"), NGX_LOG_ERR }, 40 | { ngx_null_string, 0 } 41 | }; 42 | 43 | 44 | static ngx_command_t ngx_http_sysguard_commands[] = { 45 | 46 | { ngx_string("sysguard"), 47 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 48 | ngx_conf_set_flag_slot, 49 | NGX_HTTP_LOC_CONF_OFFSET, 50 | offsetof(ngx_http_sysguard_conf_t, enable), 51 | NULL }, 52 | 53 | { ngx_string("sysguard_load"), 54 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, 55 | ngx_http_sysguard_load, 56 | NGX_HTTP_LOC_CONF_OFFSET, 57 | 0, 58 | NULL }, 59 | 60 | { ngx_string("sysguard_mem"), 61 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, 62 | ngx_http_sysguard_mem, 63 | NGX_HTTP_LOC_CONF_OFFSET, 64 | 0, 65 | NULL }, 66 | 67 | { ngx_string("sysguard_interval"), 68 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 69 | ngx_conf_set_sec_slot, 70 | NGX_HTTP_LOC_CONF_OFFSET, 71 | offsetof(ngx_http_sysguard_conf_t, interval), 72 | NULL }, 73 | 74 | { ngx_string("sysguard_log_level"), 75 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 76 | ngx_conf_set_enum_slot, 77 | NGX_HTTP_LOC_CONF_OFFSET, 78 | offsetof(ngx_http_sysguard_conf_t, log_level), 79 | &ngx_http_sysguard_log_levels }, 80 | 81 | ngx_null_command 82 | }; 83 | 84 | 85 | static ngx_http_module_t ngx_http_sysguard_module_ctx = { 86 | NULL, /* preconfiguration */ 87 | ngx_http_sysguard_init, /* postconfiguration */ 88 | 89 | NULL, /* create main configuration */ 90 | NULL, /* init main configuration */ 91 | 92 | NULL, /* create server configuration */ 93 | NULL, /* merge server configuration */ 94 | 95 | ngx_http_sysguard_create_conf, /* create location configuration */ 96 | ngx_http_sysguard_merge_conf /* merge location configuration */ 97 | }; 98 | 99 | 100 | ngx_module_t ngx_http_sysguard_module = { 101 | NGX_MODULE_V1, 102 | &ngx_http_sysguard_module_ctx, /* module context */ 103 | ngx_http_sysguard_commands, /* module directives */ 104 | NGX_HTTP_MODULE, /* module type */ 105 | NULL, /* init master */ 106 | NULL, /* init module */ 107 | NULL, /* init process */ 108 | NULL, /* init thread */ 109 | NULL, /* exit thread */ 110 | NULL, /* exit process */ 111 | NULL, /* exit master */ 112 | NGX_MODULE_V1_PADDING 113 | }; 114 | 115 | 116 | static time_t ngx_http_sysguard_cached_load_exptime; 117 | static time_t ngx_http_sysguard_cached_swap_exptime; 118 | static ngx_int_t ngx_http_sysguard_cached_load; 119 | static ngx_int_t ngx_http_sysguard_cached_swapstat; 120 | 121 | 122 | static ngx_int_t 123 | ngx_http_sysguard_update_load(ngx_http_request_t *r, time_t exptime) 124 | { 125 | ngx_int_t load, rc; 126 | 127 | ngx_http_sysguard_cached_load_exptime = ngx_time() + exptime; 128 | 129 | rc = ngx_getloadavg(&load, 1, r->connection->log); 130 | if (rc == NGX_ERROR) { 131 | 132 | ngx_http_sysguard_cached_load = 0; 133 | 134 | return NGX_ERROR; 135 | } 136 | 137 | ngx_http_sysguard_cached_load = load; 138 | 139 | return NGX_OK; 140 | } 141 | 142 | 143 | static ngx_int_t 144 | ngx_http_sysguard_update_swap(ngx_http_request_t *r, time_t exptime) 145 | { 146 | ngx_int_t rc; 147 | ngx_meminfo_t m; 148 | 149 | ngx_http_sysguard_cached_swap_exptime = ngx_time() + exptime; 150 | 151 | rc = ngx_getmeminfo(&m, r->connection->log); 152 | if (rc == NGX_ERROR) { 153 | 154 | ngx_http_sysguard_cached_swapstat = 0; 155 | 156 | return NGX_ERROR; 157 | } 158 | 159 | ngx_http_sysguard_cached_swapstat = m.totalswap == 0 160 | ? 0 : (m.totalswap - m.freeswap) * 100 / m.totalswap; 161 | 162 | return NGX_OK; 163 | } 164 | 165 | 166 | static ngx_int_t 167 | ngx_http_sysguard_do_redirect(ngx_http_request_t *r, ngx_str_t *path) 168 | { 169 | if (path->len == 0) { 170 | return NGX_HTTP_SERVICE_UNAVAILABLE; 171 | } else if (path->data[0] == '@') { 172 | (void) ngx_http_named_location(r, path); 173 | } else { 174 | (void) ngx_http_internal_redirect(r, path, &r->args); 175 | } 176 | 177 | ngx_http_finalize_request(r, NGX_DONE); 178 | 179 | return NGX_DONE; 180 | } 181 | 182 | 183 | static ngx_int_t 184 | ngx_http_sysguard_handler(ngx_http_request_t *r) 185 | { 186 | ngx_http_sysguard_conf_t *glcf; 187 | 188 | if (r->main->sysguard_set) { 189 | return NGX_DECLINED; 190 | } 191 | 192 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 193 | 194 | if (!glcf->enable) { 195 | return NGX_DECLINED; 196 | } 197 | 198 | r->main->sysguard_set = 1; 199 | 200 | /* load */ 201 | 202 | if (glcf->load >= 0) { 203 | 204 | if (ngx_http_sysguard_cached_load_exptime < ngx_time()) { 205 | ngx_http_sysguard_update_load(r, glcf->interval); 206 | } 207 | 208 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 209 | "http sysguard handler load: %i %i %V %V", 210 | ngx_http_sysguard_cached_load, 211 | glcf->load, 212 | &r->uri, 213 | &glcf->load_action); 214 | 215 | if (ngx_http_sysguard_cached_load > glcf->load) { 216 | 217 | ngx_log_error(glcf->log_level, r->connection->log, 0, 218 | "sysguard load limited, current:%i conf:%i", 219 | ngx_http_sysguard_cached_load, 220 | glcf->load); 221 | 222 | return ngx_http_sysguard_do_redirect(r, &glcf->load_action); 223 | } 224 | } 225 | 226 | /* swap */ 227 | 228 | if (glcf->swap >= 0) { 229 | 230 | if (ngx_http_sysguard_cached_swap_exptime < ngx_time()) { 231 | ngx_http_sysguard_update_swap(r, glcf->interval); 232 | } 233 | 234 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 235 | "http sysguard handler swap: %i %i %V %V", 236 | ngx_http_sysguard_cached_swapstat, 237 | glcf->swap, 238 | &r->uri, 239 | &glcf->swap_action); 240 | 241 | if (ngx_http_sysguard_cached_swapstat > glcf->swap) { 242 | 243 | ngx_log_error(glcf->log_level, r->connection->log, 0, 244 | "sysguard swap limited, current:%i conf:%i", 245 | ngx_http_sysguard_cached_swapstat, 246 | glcf->swap); 247 | 248 | return ngx_http_sysguard_do_redirect(r, &glcf->swap_action); 249 | } 250 | } 251 | 252 | return NGX_DECLINED; 253 | } 254 | 255 | 256 | static void * 257 | ngx_http_sysguard_create_conf(ngx_conf_t *cf) 258 | { 259 | ngx_http_sysguard_conf_t *conf; 260 | 261 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sysguard_conf_t)); 262 | if (conf == NULL) { 263 | return NGX_CONF_ERROR; 264 | } 265 | 266 | /* 267 | * set by ngx_pcalloc(): 268 | * 269 | * conf->load_action = {0, NULL}; 270 | * conf->swap_action = {0, NULL}; 271 | */ 272 | 273 | conf->enable = NGX_CONF_UNSET; 274 | conf->load = NGX_CONF_UNSET; 275 | conf->swap = NGX_CONF_UNSET; 276 | conf->interval = NGX_CONF_UNSET; 277 | conf->log_level = NGX_CONF_UNSET_UINT; 278 | 279 | return conf; 280 | } 281 | 282 | 283 | static char * 284 | ngx_http_sysguard_merge_conf(ngx_conf_t *cf, void *parent, void *child) 285 | { 286 | ngx_http_sysguard_conf_t *prev = parent; 287 | ngx_http_sysguard_conf_t *conf = child; 288 | 289 | ngx_conf_merge_value(conf->enable, prev->enable, 0); 290 | ngx_conf_merge_str_value(conf->load_action, prev->load_action, ""); 291 | ngx_conf_merge_str_value(conf->swap_action, prev->swap_action, ""); 292 | ngx_conf_merge_value(conf->load, prev->load, -1); 293 | ngx_conf_merge_value(conf->swap, prev->swap, -1); 294 | ngx_conf_merge_value(conf->interval, prev->interval, 1); 295 | ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR); 296 | 297 | return NGX_CONF_OK; 298 | } 299 | 300 | static char * 301 | ngx_http_sysguard_load(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 302 | { 303 | ngx_http_sysguard_conf_t *glcf = conf; 304 | 305 | ngx_str_t *value; 306 | ngx_uint_t i; 307 | 308 | value = cf->args->elts; 309 | i = 1; 310 | 311 | if (ngx_strncmp(value[i].data, "load=", 5) == 0) { 312 | 313 | if (glcf->load != NGX_CONF_UNSET) { 314 | return "is duplicate"; 315 | } 316 | 317 | if (value[i].len == 5) { 318 | goto invalid; 319 | } 320 | 321 | glcf->load = ngx_atofp(value[i].data + 5, value[i].len - 5, 3); 322 | if (glcf->load == NGX_ERROR) { 323 | goto invalid; 324 | } 325 | 326 | if (cf->args->nelts == 2) { 327 | return NGX_CONF_OK; 328 | } 329 | 330 | i++; 331 | 332 | if (ngx_strncmp(value[i].data, "action=", 7) != 0) { 333 | goto invalid; 334 | } 335 | 336 | if (value[i].len == 7) { 337 | goto invalid; 338 | } 339 | 340 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 341 | goto invalid; 342 | } 343 | 344 | glcf->load_action.data = value[i].data + 7; 345 | glcf->load_action.len = value[i].len - 7; 346 | 347 | return NGX_CONF_OK; 348 | } 349 | 350 | invalid: 351 | 352 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 353 | "invalid parameter \"%V\"", &value[i]); 354 | 355 | return NGX_CONF_ERROR; 356 | } 357 | 358 | 359 | static char * 360 | ngx_http_sysguard_mem(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 361 | { 362 | ngx_http_sysguard_conf_t *glcf = conf; 363 | 364 | ngx_str_t *value; 365 | ngx_uint_t i; 366 | 367 | value = cf->args->elts; 368 | i = 1; 369 | 370 | if (ngx_strncmp(value[i].data, "swapratio=", 10) == 0) { 371 | 372 | if (glcf->swap != NGX_CONF_UNSET) { 373 | return "is duplicate"; 374 | } 375 | 376 | if (value[i].data[value[i].len - 1] != '%') { 377 | goto invalid; 378 | } 379 | 380 | glcf->swap = ngx_atofp(value[i].data + 10, value[i].len - 11, 2); 381 | if (glcf->swap == NGX_ERROR) { 382 | goto invalid; 383 | } 384 | 385 | if (cf->args->nelts == 2) { 386 | return NGX_CONF_OK; 387 | } 388 | 389 | i++; 390 | 391 | if (ngx_strncmp(value[i].data, "action=", 7) != 0) { 392 | goto invalid; 393 | } 394 | 395 | if (value[i].len == 7) { 396 | goto invalid; 397 | } 398 | 399 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 400 | goto invalid; 401 | } 402 | 403 | glcf->swap_action.data = value[i].data + 7; 404 | glcf->swap_action.len = value[i].len - 7; 405 | 406 | return NGX_CONF_OK; 407 | } 408 | 409 | invalid: 410 | 411 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 412 | "invalid parameter \"%V\"", &value[i]); 413 | 414 | return NGX_CONF_ERROR; 415 | } 416 | 417 | 418 | static ngx_int_t 419 | ngx_http_sysguard_init(ngx_conf_t *cf) 420 | { 421 | ngx_http_handler_pt *h; 422 | ngx_http_core_main_conf_t *cmcf; 423 | 424 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 425 | 426 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); 427 | if (h == NULL) { 428 | return NGX_ERROR; 429 | } 430 | 431 | *h = ngx_http_sysguard_handler; 432 | 433 | return NGX_OK; 434 | } 435 | -------------------------------------------------------------------------------- /ngx_sysinfo.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2012 Alibaba Group Holding Limited 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #if (NGX_HAVE_SYSINFO) 12 | #include 13 | #endif 14 | 15 | 16 | ngx_int_t 17 | ngx_getloadavg(ngx_int_t avg[], ngx_int_t nelem, ngx_log_t *log) 18 | { 19 | #if (NGX_HAVE_GETLOADAVG) 20 | double loadavg[3]; 21 | ngx_int_t i; 22 | 23 | if (getloadavg(loadavg, nelem) == -1) { 24 | return NGX_ERROR; 25 | } 26 | 27 | for (i = 0; i < nelem; i ++) { 28 | avg[i] = loadavg[i] * 1000; 29 | } 30 | 31 | return NGX_OK; 32 | 33 | #elif (NGX_HAVE_SYSINFO) 34 | 35 | struct sysinfo s; 36 | ngx_int_t i; 37 | 38 | if (sysinfo(&s)) { 39 | return NGX_ERROR; 40 | } 41 | 42 | for (i = 0; i < nelem; i ++) { 43 | avg[i] = s.loads[i] * 1000 / 65536; 44 | } 45 | 46 | return NGX_OK; 47 | 48 | #else 49 | 50 | ngx_log_error(NGX_LOG_EMERG, log, 0, 51 | "getloadavg is unsurpported under current os"); 52 | 53 | return NGX_ERROR; 54 | #endif 55 | } 56 | 57 | 58 | ngx_int_t 59 | ngx_getmeminfo(ngx_meminfo_t *meminfo, ngx_log_t *log) 60 | { 61 | #if (NGX_HAVE_SYSINFO) 62 | struct sysinfo s; 63 | 64 | if (sysinfo(&s)) { 65 | return NGX_ERROR; 66 | } 67 | 68 | meminfo->totalram = s.totalram; 69 | meminfo->freeram = s.freeram; 70 | meminfo->sharedram = s.sharedram; 71 | meminfo->bufferram = s.bufferram; 72 | meminfo->totalswap = s.totalswap; 73 | meminfo->freeswap = s.freeswap; 74 | 75 | return NGX_OK; 76 | #else 77 | ngx_log_error(NGX_LOG_EMERG, log, 0, 78 | "getmeminfo is unsurpported under current os"); 79 | return NGX_ERROR; 80 | #endif 81 | } 82 | -------------------------------------------------------------------------------- /ngx_sysinfo.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2012 Alibaba Group Holding Limited 4 | */ 5 | 6 | 7 | #ifndef _NGX_SYSINFO_H_INCLUDED_ 8 | #define _NGX_SYSINFO_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | typedef struct { 16 | size_t totalram; 17 | size_t freeram; 18 | size_t sharedram; 19 | size_t bufferram; 20 | size_t totalswap; 21 | size_t freeswap; 22 | } ngx_meminfo_t; 23 | 24 | 25 | ngx_int_t ngx_getloadavg(ngx_int_t avg[], ngx_int_t nelem, ngx_log_t *log); 26 | ngx_int_t ngx_getmeminfo(ngx_meminfo_t *meminfo, ngx_log_t *log); 27 | 28 | #endif /* _NGX_SYSINFO_H_INCLUDED_ */ 29 | --------------------------------------------------------------------------------