├── 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 |
--------------------------------------------------------------------------------