📄 mod_status.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* Status Module. Display lots of internal data about how Apache is * performing and the state of all children processes. * * To enable this, add the following lines into any config file: * * <Location /server-status> * SetHandler server-status * </Location> * * You may want to protect this location by password or domain so no one * else can look at it. Then you can access the statistics with a URL like: * * http://your_server_name/server-status * * /server-status - Returns page using tables * /server-status?notable - Returns page for browsers without table support * /server-status?refresh - Returns page with 1 second refresh * /server-status?refresh=6 - Returns page with refresh every 6 seconds * /server-status?auto - Returns page with data for automatic parsing * * Mark Cox, mark@ukweb.com, November 1995 * * 12.11.95 Initial version for www.telescope.org * 13.3.96 Updated to remove rprintf's [Mark] * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie] * 18.3.96 Make extra Scoreboard variables #definable * 25.3.96 Make short report have full precision [Ben Laurie suggested] * 25.3.96 Show uptime better [Mark/Ben Laurie] * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested] * 09.4.96 Added message for non-STATUS compiled version * 18.4.96 Added per child and per slot counters [Jim Jagielski] * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.] * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing * piece in short reports [Ben Laurie] * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if * extended STATUS is enabled) [George Burgyan/Jim J.] * 10.8.98 Allow for extended status info at runtime (no more STATUS) * [Jim J.] */#define CORE_PRIVATE#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_protocol.h"#include "http_conf_globals.h" /* for ap_extended_status */#include "http_main.h"#include "util_script.h"#include <time.h>#include "scoreboard.h"#include "http_log.h"#ifdef NEXT#if (NX_CURRENT_COMPILER_RELEASE == 410)#ifdef m68k#define HZ 64#else#define HZ 100#endif#else#include <machine/param.h>#endif#endif /* NEXT */#define STATUS_MAXLINE 64#define KBYTE 1024#define MBYTE 1048576L#define GBYTE 1073741824L#ifndef DEFAULT_TIME_FORMAT #define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"#endifmodule MODULE_VAR_EXPORT status_module;/* *command-related code. This is here to prevent use of ExtendedStatus * without status_module included. */static const char *set_extended_status(cmd_parms *cmd, void *dummy, int arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_extended_status = arg; return NULL;}static const command_rec status_module_cmds[] ={ { "ExtendedStatus", set_extended_status, NULL, RSRC_CONF, FLAG, "\"On\" to enable extended status information, \"Off\" to disable" }, {NULL}};/* Format the number of bytes nicely */static void format_byte_out(request_rec *r, unsigned long bytes){ if (bytes < (5 * KBYTE)) ap_rprintf(r, "%d B", (int) bytes); else if (bytes < (MBYTE / 2)) ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE); else if (bytes < (GBYTE / 2)) ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE); else ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);}static void format_kbyte_out(request_rec *r, unsigned long kbytes){ if (kbytes < KBYTE) ap_rprintf(r, "%d kB", (int) kbytes); else if (kbytes < MBYTE) ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE); else ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);}static void show_time(request_rec *r, time_t tsecs){ long days, hrs, mins, secs; secs = tsecs % 60; tsecs /= 60; mins = tsecs % 60; tsecs /= 60; hrs = tsecs % 24; days = tsecs / 24; if (days) ap_rprintf(r, " %ld day%s", days, days == 1 ? "" : "s"); if (hrs) ap_rprintf(r, " %ld hour%s", hrs, hrs == 1 ? "" : "s"); if (mins) ap_rprintf(r, " %ld minute%s", mins, mins == 1 ? "" : "s"); if (secs) ap_rprintf(r, " %ld second%s", secs, secs == 1 ? "" : "s");}/* Main handler for x-httpd-status requests *//* ID values for command table */#define STAT_OPT_END -1#define STAT_OPT_REFRESH 0#define STAT_OPT_NOTABLE 1#define STAT_OPT_AUTO 2struct stat_opt { int id; const char *form_data_str; const char *hdr_out_str;};static const struct stat_opt status_options[] = /* see #defines above */{ {STAT_OPT_REFRESH, "refresh", "Refresh"}, {STAT_OPT_NOTABLE, "notable", NULL}, {STAT_OPT_AUTO, "auto", NULL}, {STAT_OPT_END, NULL, NULL}};static char status_flags[SERVER_NUM_STATUS];static int status_handler(request_rec *r){ char *loc; time_t nowtime = time(NULL); time_t up_time; int i, res; int ready = 0; int busy = 0; unsigned long count = 0; unsigned long lres, bytes; unsigned long my_lres, my_bytes, conn_bytes; unsigned short conn_lres; unsigned long bcount = 0; unsigned long kbcount = 0; long req_time;#ifndef NO_TIMES#ifdef _SC_CLK_TCK float tick = sysconf(_SC_CLK_TCK);#else float tick = HZ;#endif#endif int short_report = 0; int no_table_report = 0; short_score score_record; parent_score ps_record; char stat_buffer[HARD_SERVER_LIMIT]; int pid_buffer[HARD_SERVER_LIMIT]; clock_t tu, ts, tcu, tcs; server_rec *vhost; tu = ts = tcu = tcs = 0; if (!ap_exists_scoreboard_image()) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Server status unavailable in inetd mode"); return HTTP_INTERNAL_SERVER_ERROR; } r->allowed = (1 << M_GET); if (r->method_number != M_GET) return DECLINED; r->content_type = "text/html; charset=ISO-8859-1"; /* * Simple table-driven form data set parser that lets you alter the header */ if (r->args) { i = 0; while (status_options[i].id != STAT_OPT_END) { if ((loc = strstr(r->args, status_options[i].form_data_str)) != NULL) { switch (status_options[i].id) { case STAT_OPT_REFRESH: if (*(loc + strlen(status_options[i].form_data_str)) == '=' && atol(loc + strlen(status_options[i].form_data_str) + 1) > 0) ap_table_set(r->headers_out, status_options[i].hdr_out_str, loc + strlen(status_options[i].hdr_out_str) + 1); else ap_table_set(r->headers_out, status_options[i].hdr_out_str, "1"); break; case STAT_OPT_NOTABLE: no_table_report = 1; break; case STAT_OPT_AUTO: r->content_type = "text/plain; charset=ISO-8859-1"; short_report = 1; break; } } i++; } } ap_send_http_header(r);#ifdef CHARSET_EBCDIC /* Server-generated response, converted */ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);#endif if (r->header_only) return 0; ap_sync_scoreboard_image(); for (i = 0; i < HARD_SERVER_LIMIT; ++i) { score_record = ap_scoreboard_image->servers[i]; ps_record = ap_scoreboard_image->parent[i]; res = score_record.status; stat_buffer[i] = status_flags[res]; pid_buffer[i] = (int) ps_record.pid; if (res == SERVER_READY) ready++; else if (res != SERVER_DEAD) busy++; if (ap_extended_status) { lres = score_record.access_count; bytes = score_record.bytes_served; if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {#ifndef NO_TIMES tu += score_record.times.tms_utime; ts += score_record.times.tms_stime; tcu += score_record.times.tms_cutime; tcs += score_record.times.tms_cstime;#endif /* NO_TIMES */ count += lres; bcount += bytes; if (bcount >= KBYTE) { kbcount += (bcount >> 10); bcount = bcount & 0x3ff; } } } } up_time = nowtime - ap_restart_time; ap_hard_timeout("send status info", r); if (!short_report) { ap_rputs(DOCTYPE_HTML_3_2 "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n", r); ap_rputs("<H1>Apache Server Status for ", r); ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL); ap_rvputs(r, "Server Version: ", ap_get_server_version(), "<br>\n", NULL); ap_rvputs(r, "Server Built: ", ap_get_server_built(), "<br>\n<hr>\n", NULL); ap_rvputs(r, "Current Time: ", ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL); ap_rvputs(r, "Restart Time: ", ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL); ap_rprintf(r, "Parent Server Generation: %d <br>\n", (int) ap_my_generation); ap_rputs("Server uptime: ", r); show_time(r, up_time); ap_rputs("<br>\n", r); } if (ap_extended_status) { if (short_report) { ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n", count, kbcount);#ifndef NO_TIMES /* Allow for OS/2 not having CPU stats */ if (ts || tu || tcu || tcs) ap_rprintf(r, "CPULoad: %g\n", (tu + ts + tcu + tcs) / tick / up_time * 100.);#endif ap_rprintf(r, "Uptime: %ld\n", (long) (up_time)); if (up_time > 0) ap_rprintf(r, "ReqPerSec: %g\n", (float) count / (float) up_time); if (up_time > 0) ap_rprintf(r, "BytesPerSec: %g\n", KBYTE * (float) kbcount / (float) up_time); if (count > 0) ap_rprintf(r, "BytesPerReq: %g\n", KBYTE * (float) kbcount / (float) count); } else { /* !short_report */ ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count); format_kbyte_out(r, kbcount);#ifndef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rputs("<br>\n", r); ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g", tu / tick, ts / tick, tcu / tick, tcs / tick); if (ts || tu || tcu || tcs) ap_rprintf(r, " - %.3g%% CPU load", (tu + ts + tcu + tcs) / tick / up_time * 100.);#endif ap_rputs("<br>\n", r); if (up_time > 0) ap_rprintf(r, "%.3g requests/sec - ", (float) count / (float) up_time); if (up_time > 0) { format_byte_out(r, (unsigned long) (KBYTE * (float) kbcount / (float) up_time)); ap_rputs("/second - ", r); } if (count > 0) { format_byte_out(r, (unsigned long) (KBYTE * (float) kbcount / (float) count)); ap_rputs("/request", r); } ap_rputs("<br>\n", r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -