From: Timo Sirainen Date: Thu, 20 Oct 2016 10:12:34 +0000 (+0300) Subject: Added "doveadm service status" X-Git-Tag: 2.2.26~75 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6cae1f3ed624de9fa76aa0e64ab9cff3132f83e3;p=thirdparty%2Fdovecot%2Fcore.git Added "doveadm service status" This allows asking for services' current status in master process. --- diff --git a/src/doveadm/doveadm-cmd.c b/src/doveadm/doveadm-cmd.c index 3c2da477bc..7d50bcf141 100644 --- a/src/doveadm/doveadm-cmd.c +++ b/src/doveadm/doveadm-cmd.c @@ -20,6 +20,7 @@ static struct doveadm_cmd *doveadm_commands[] = { static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = { &doveadm_cmd_service_stop_ver2, + &doveadm_cmd_service_status_ver2, &doveadm_cmd_stop_ver2, &doveadm_cmd_reload_ver2, &doveadm_cmd_stats_dump_ver2, diff --git a/src/doveadm/doveadm-cmd.h b/src/doveadm/doveadm-cmd.h index ec54f41413..f3c7796c3e 100644 --- a/src/doveadm/doveadm-cmd.h +++ b/src/doveadm/doveadm-cmd.h @@ -149,6 +149,7 @@ void doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv); void doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv); extern struct doveadm_cmd_ver2 doveadm_cmd_service_stop_ver2; +extern struct doveadm_cmd_ver2 doveadm_cmd_service_status_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_stop_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_reload_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_stats_reset_ver2; diff --git a/src/doveadm/doveadm-master.c b/src/doveadm/doveadm-master.c index 06802a9426..ecf3ed3261 100644 --- a/src/doveadm/doveadm-master.c +++ b/src/doveadm/doveadm-master.c @@ -6,6 +6,7 @@ #include "istream.h" #include "write-full.h" #include "doveadm.h" +#include "doveadm-print.h" #include #include @@ -148,6 +149,51 @@ static void cmd_service_stop(struct doveadm_cmd_context *cctx) i_stream_destroy(&input); } +static void cmd_service_status(struct doveadm_cmd_context *cctx) +{ + const char *line, *const *services; + + if (!doveadm_cmd_param_array(cctx, "service", &services)) + services = NULL; + + struct istream *input = master_service_send_cmd("SERVICE-STATUS"); + + doveadm_print_init("pager"); + doveadm_print_header_simple("name"); + doveadm_print_header_simple("process_count"); + doveadm_print_header_simple("process_avail"); + doveadm_print_header_simple("process_limit"); + doveadm_print_header_simple("client_limit"); + doveadm_print_header_simple("throttle_secs"); + doveadm_print_header_simple("exit_failure_last"); + doveadm_print_header_simple("exit_failures_in_sec"); + doveadm_print_header_simple("last_drop_warning"); + doveadm_print_header_simple("listen_pending"); + doveadm_print_header_simple("listening"); + + alarm(5); + while ((line = i_stream_read_next_line(input)) != NULL) { + if (line[0] == '\0') + break; + T_BEGIN { + const char *const *args = t_strsplit_tabescaped(line); + if (str_array_length(args) >= 11 && + (services == NULL || + str_array_find(services, args[0]))) { + for (unsigned int i = 0; i < 11; i++) + doveadm_print(args[i]); + } + } T_END; + } + if (line == NULL) { + i_error("read(%s) failed: %s", i_stream_get_name(input), + i_stream_get_error(input)); + doveadm_exit_code = EX_TEMPFAIL; + } + alarm(0); + i_stream_destroy(&input); +} + struct doveadm_cmd_ver2 doveadm_cmd_stop_ver2 = { .old_cmd = cmd_stop, .name = "stop", @@ -172,3 +218,12 @@ DOVEADM_CMD_PARAMS_START DOVEADM_CMD_PARAM('\0', "service", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) DOVEADM_CMD_PARAMS_END }; + +struct doveadm_cmd_ver2 doveadm_cmd_service_status_ver2 = { + .cmd = cmd_service_status, + .name = "service status", + .usage = "[ [...]]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_PARAM('\0', "service", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/src/master/master-client.c b/src/master/master-client.c index 32cfbc3eb4..64d9872229 100644 --- a/src/master/master-client.c +++ b/src/master/master-client.c @@ -1,6 +1,9 @@ /* Copyright (c) 2016 Dovecot authors, see the included COPYING file */ #include "common.h" +#include "array.h" +#include "str.h" +#include "strescape.h" #include "ostream.h" #include "connection.h" #include "service.h" @@ -11,6 +14,37 @@ struct master_client { struct connection conn; }; +static void +master_client_service_status_output(string_t *str, + const struct service *service) +{ + str_append_tabescaped(str, service->set->name); + str_printfa(str, "\t%u\t%u\t%u\t%u\t%u\t%ld\t%u\t%ld\t%c\t%c\n", + service->process_count, service->process_avail, + service->process_limit, service->client_limit, + service->to_throttle == NULL ? 0 : service->throttle_secs, + (long)service->exit_failure_last, + service->exit_failures_in_sec, + (long)service->last_drop_warning, + service->listen_pending ? 'y' : 'n', + service->listening ? 'y' : 'n'); +} + +static int +master_client_service_status(struct master_client *client) +{ + struct service *const *servicep; + string_t *str = t_str_new(128); + + array_foreach(&services->services, servicep) { + str_truncate(str, 0); + master_client_service_status_output(str, *servicep); + o_stream_nsend(client->conn.output, str_data(str), str_len(str)); + } + o_stream_nsend_str(client->conn.output, "\n"); + return 1; +} + static int master_client_stop(struct master_client *client, const char *const *args) { @@ -40,6 +74,8 @@ master_client_input_args(struct connection *conn, const char *const *args) } args++; + if (strcmp(cmd, "SERVICE-STATUS") == 0) + return master_client_service_status(client); if (strcmp(cmd, "STOP") == 0) return master_client_stop(client, args); i_error("%s: Unknown command: %s", conn->name, cmd);