starting the process. See also "daemon".
stats socket <path> [{uid | user} <uid>] [{gid | group} <gid>] [mode <mode>]
+ [level <level>]
+
Creates a UNIX socket in stream mode at location <path>. Any previously
existing socket will be backed up then replaced. Connections to this socket
- will get a CSV-formated output of the process statistics in response to the
- "show stat" command followed by a line feed, more general process information
- in response to the "show info" command followed by a line feed, and a
- complete list of all existing sessions in response to the "show sess" command
- followed by a line feed.
+ will return various statictics outputs and even allow some commands to be
+ issued. Please consult section 9.2 "Unix Socket commands" for more details.
+
+ An optional "level" parameter can be specified to restrict the nature of
+ the commands that can be issued on the socket :
+ - "user" is the least privileged level ; only non-sensitive stats can be
+ read, and no change is allowed. It would make sense on systems where it
+ is not easy to restrict access to the socket.
+
+ - "operator" is the default level and fits most common uses. All data can
+ be read, and only non-sensible changes are permitted (eg: clear max
+ counters).
+
+ - "admin" should be used with care, as everything is permitted (eg: clear
+ all counters).
On platforms which support it, it is possible to restrict access to this
socket by specifying numerical IDs after "uid" and "gid", or valid user and
show errors [<iid>]
Dump last known request and response errors collected by frontends and
backends. If <iid> is specified, the limit the dump to errors concerning
- either frontend or backend whose ID is <iid>.
+ either frontend or backend whose ID is <iid>. This command is restricted
+ and can only be issued on sockets configured for levels "operator" or
+ "admin".
The errors which may be collected are the last request and response errors
caused by protocol violations, often due to invalid characters in header
show sess
Dump all known sessions. Avoid doing this on slow connections as this can
- be huge.
+ be huge. This command is restricted and can only be issued on sockets
+ configured for levels "operator" or "admin".
+
show stat [<iid> <type> <sid>]
Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is
Clear the max values of the statistics counters in each proxy (frontend &
backend) and in each server. The cumulated counters are not affected. This
can be used to get clean counters after an incident, without having to
- restart nor to clear traffic counters.
+ restart nor to clear traffic counters. This command is restricted and can
+ only be issued on sockets configured for levels "operator" or "admin".
clear counters all
Clear all statistics counters in each proxy (frontend & backend) and in each
- server. This has the same effect as restarting.
+ server. This has the same effect as restarting. This command is restricted
+ and can only be issued on sockets configured for level "admin".
+
/*
* Local variables:
/* platform-specific options */
#define GTUNE_USE_SPLICE (1<<5)
+/* Access level for a stats socket */
+#define ACCESS_LVL_NONE 0
+#define ACCESS_LVL_USER 1
+#define ACCESS_LVL_OPER 2
+#define ACCESS_LVL_ADMIN 3
/* FIXME : this will have to be redefined correctly */
struct global {
uid_t uid; /* -1 to leave unchanged */
gid_t gid; /* -1 to leave unchanged */
mode_t mode; /* 0 to leave unchanged */
+ int level; /* access level (ACCESS_LVL_*) */
} ux;
} perm;
char *interface; /* interface name or NULL */
.len = sizeof(stats_sock_usage_msg)-1
};
+const char stats_permission_denied_msg[] =
+ "Permission denied\n"
+ "";
+
+const struct chunk stats_permission_denied = {
+ .str = (char *)&stats_permission_denied_msg,
+ .len = sizeof(stats_permission_denied_msg)-1
+};
+
/* This function parses a "stats" statement in the "global" section. It returns
* -1 if there is any error, otherwise zero. If it returns -1, it may write an
* error message into ther <err> buffer, for at most <errlen> bytes, trailing
global.stats_sock.analysers = 0;
global.stats_sock.nice = -64; /* we want to boost priority for local stats */
global.stats_sock.private = global.stats_fe; /* must point to the frontend */
+ global.stats_sock.perm.ux.level = ACCESS_LVL_OPER; /* default access level */
global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */
global.stats_sock.timeout = &global.stats_fe->timeout.client;
global.stats_sock.perm.ux.gid = group->gr_gid;
cur_arg += 2;
}
+ else if (!strcmp(args[cur_arg], "level")) {
+ if (!strcmp(args[cur_arg+1], "user"))
+ global.stats_sock.perm.ux.level = ACCESS_LVL_USER;
+ else if (!strcmp(args[cur_arg+1], "operator"))
+ global.stats_sock.perm.ux.level = ACCESS_LVL_OPER;
+ else if (!strcmp(args[cur_arg+1], "admin"))
+ global.stats_sock.perm.ux.level = ACCESS_LVL_ADMIN;
+ else {
+ snprintf(err, errlen, "'stats socket level' only supports 'user', 'operator', and 'admin'");
+ return -1;
+ }
+ cur_arg += 2;
+ }
else {
- snprintf(err, errlen, "'stats socket' only supports 'user', 'uid', 'group', 'gid', and 'mode'");
+ snprintf(err, errlen, "'stats socket' only supports 'user', 'uid', 'group', 'gid', 'level', and 'mode'");
return -1;
}
}
}
else if (strcmp(args[1], "sess") == 0) {
s->data_state = DATA_ST_INIT;
+ if (s->listener->perm.ux.level < ACCESS_LVL_OPER) {
+ buffer_feed(si->ib, stats_permission_denied.str, stats_permission_denied.len);
+ return 1;
+ }
si->st0 = STAT_CLI_O_SESS; // stats_dump_sess_to_buffer
}
else if (strcmp(args[1], "errors") == 0) {
+ if (s->listener->perm.ux.level < ACCESS_LVL_OPER) {
+ buffer_feed(si->ib, stats_permission_denied.str, stats_permission_denied.len);
+ return 1;
+ }
if (*args[2])
s->data_ctx.errors.iid = atoi(args[2]);
else
if (strcmp(args[2], "all") == 0)
clrall = 1;
+ /* check permissions */
+ if (s->listener->perm.ux.level < ACCESS_LVL_OPER ||
+ (clrall && s->listener->perm.ux.level < ACCESS_LVL_ADMIN)) {
+ buffer_feed(si->ib, stats_permission_denied.str, stats_permission_denied.len);
+ return 1;
+ }
+
for (px = proxy; px; px = px->next) {
if (clrall)
memset(&px->counters, 0, sizeof(px->counters));