mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 23:21:22 +03:00
coredumpctl: use dispatch_verb()
This commit is contained in:
parent
5488660154
commit
5ce97d33d0
@ -51,18 +51,11 @@
|
|||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "verbs.h"
|
||||||
|
|
||||||
#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC)
|
#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC)
|
||||||
|
|
||||||
static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
|
static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
|
||||||
|
|
||||||
static enum {
|
|
||||||
ACTION_NONE,
|
|
||||||
ACTION_INFO,
|
|
||||||
ACTION_LIST,
|
|
||||||
ACTION_DUMP,
|
|
||||||
ACTION_GDB,
|
|
||||||
} arg_action = ACTION_LIST;
|
|
||||||
static const char* arg_field = NULL;
|
static const char* arg_field = NULL;
|
||||||
static const char *arg_directory = NULL;
|
static const char *arg_directory = NULL;
|
||||||
static bool arg_no_pager = false;
|
static bool arg_no_pager = false;
|
||||||
@ -70,7 +63,6 @@ static int arg_no_legend = false;
|
|||||||
static int arg_one = false;
|
static int arg_one = false;
|
||||||
static FILE* arg_output = NULL;
|
static FILE* arg_output = NULL;
|
||||||
static bool arg_reverse = false;
|
static bool arg_reverse = false;
|
||||||
static char** arg_matches = NULL;
|
|
||||||
static bool arg_quiet = false;
|
static bool arg_quiet = false;
|
||||||
|
|
||||||
static int add_match(sd_journal *j, const char *match) {
|
static int add_match(sd_journal *j, const char *match) {
|
||||||
@ -102,7 +94,7 @@ static int add_match(sd_journal *j, const char *match) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_matches(sd_journal *j) {
|
static int add_matches(sd_journal *j, char **matches) {
|
||||||
char **match;
|
char **match;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -114,7 +106,7 @@ static int add_matches(sd_journal *j) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
|
return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
|
||||||
|
|
||||||
STRV_FOREACH(match, arg_matches) {
|
STRV_FOREACH(match, matches) {
|
||||||
r = add_match(j, *match);
|
r = add_match(j, *match);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -123,7 +115,44 @@ static int add_matches(sd_journal *j) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void help(void) {
|
static int acquire_journal(sd_journal **ret, char **matches) {
|
||||||
|
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (arg_directory) {
|
||||||
|
r = sd_journal_open_directory(&j, arg_directory, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
|
||||||
|
} else {
|
||||||
|
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to open journal: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
r = journal_access_check_and_warn(j, arg_quiet, true);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = add_matches(j, matches);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (DEBUG_LOGGING) {
|
||||||
|
_cleanup_free_ char *filter;
|
||||||
|
|
||||||
|
filter = journal_make_match_string(j);
|
||||||
|
log_debug("Journal filter: %s", filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret = j;
|
||||||
|
j = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int help(void) {
|
||||||
printf("%s [OPTIONS...]\n\n"
|
printf("%s [OPTIONS...]\n\n"
|
||||||
"List or retrieve coredumps from the journal.\n\n"
|
"List or retrieve coredumps from the journal.\n\n"
|
||||||
"Flags:\n"
|
"Flags:\n"
|
||||||
@ -145,6 +174,8 @@ static void help(void) {
|
|||||||
" dump [MATCHES...] Print first matching coredump to stdout\n"
|
" dump [MATCHES...] Print first matching coredump to stdout\n"
|
||||||
" gdb [MATCHES...] Start gdb for the first matching coredump\n"
|
" gdb [MATCHES...] Start gdb for the first matching coredump\n"
|
||||||
, program_invocation_short_name);
|
, program_invocation_short_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_argv(int argc, char *argv[]) {
|
static int parse_argv(int argc, char *argv[]) {
|
||||||
@ -177,12 +208,9 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0)
|
while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0)
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
arg_action = ACTION_NONE;
|
return help();
|
||||||
help();
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
arg_action = ACTION_NONE;
|
|
||||||
return version();
|
return version();
|
||||||
|
|
||||||
case ARG_NO_PAGER:
|
case ARG_NO_PAGER:
|
||||||
@ -254,31 +282,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc) {
|
return 1;
|
||||||
const char *cmd = argv[optind++];
|
|
||||||
if (streq(cmd, "list"))
|
|
||||||
arg_action = ACTION_LIST;
|
|
||||||
else if (streq(cmd, "dump"))
|
|
||||||
arg_action = ACTION_DUMP;
|
|
||||||
else if (streq(cmd, "gdb"))
|
|
||||||
arg_action = ACTION_GDB;
|
|
||||||
else if (streq(cmd, "info"))
|
|
||||||
arg_action = ACTION_INFO;
|
|
||||||
else {
|
|
||||||
log_error("Unknown action '%s'", cmd);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg_field && arg_action != ACTION_LIST) {
|
|
||||||
log_error("Option --field/-F only makes sense with list");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc)
|
|
||||||
arg_matches = argv + optind;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int retrieve(const void *data,
|
static int retrieve(const void *data,
|
||||||
@ -631,10 +635,10 @@ static int focus(sd_journal *j) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_entry(sd_journal *j, unsigned n_found) {
|
static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) {
|
||||||
assert(j);
|
assert(j);
|
||||||
|
|
||||||
if (arg_action == ACTION_INFO)
|
if (verb_is_info)
|
||||||
return print_info(stdout, j, n_found);
|
return print_info(stdout, j, n_found);
|
||||||
else if (arg_field)
|
else if (arg_field)
|
||||||
return print_field(stdout, j);
|
return print_field(stdout, j);
|
||||||
@ -642,11 +646,19 @@ static int print_entry(sd_journal *j, unsigned n_found) {
|
|||||||
return print_list(stdout, j, n_found);
|
return print_list(stdout, j, n_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_list(sd_journal *j) {
|
static int dump_list(int argc, char **argv, void *userdata) {
|
||||||
|
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||||
unsigned n_found = 0;
|
unsigned n_found = 0;
|
||||||
|
bool verb_is_info;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(j);
|
verb_is_info = (argc >= 1 && streq(argv[0], "info"));
|
||||||
|
|
||||||
|
r = acquire_journal(&j, argv + 1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
pager_open(arg_no_pager, false);
|
||||||
|
|
||||||
/* The coredumps are likely to compressed, and for just
|
/* The coredumps are likely to compressed, and for just
|
||||||
* listing them we don't need to decompress them, so let's
|
* listing them we don't need to decompress them, so let's
|
||||||
@ -658,7 +670,7 @@ static int dump_list(sd_journal *j) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return print_entry(j, 0);
|
return print_entry(j, 0, verb_is_info);
|
||||||
} else {
|
} else {
|
||||||
if (arg_since != USEC_INFINITY && !arg_reverse)
|
if (arg_since != USEC_INFINITY && !arg_reverse)
|
||||||
r = sd_journal_seek_realtime_usec(j, arg_since);
|
r = sd_journal_seek_realtime_usec(j, arg_since);
|
||||||
@ -703,7 +715,7 @@ static int dump_list(sd_journal *j) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = print_entry(j, n_found++);
|
r = print_entry(j, n_found++, verb_is_info);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -856,10 +868,18 @@ error:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_core(sd_journal* j) {
|
static int dump_core(int argc, char **argv, void *userdata) {
|
||||||
|
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(j);
|
if (arg_field) {
|
||||||
|
log_error("Option --field/-F only makes sense with list");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = acquire_journal(&j, argv + 1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = focus(j);
|
r = focus(j);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -878,7 +898,8 @@ static int dump_core(sd_journal* j) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_gdb(sd_journal *j) {
|
static int run_gdb(int argc, char **argv, void *userdata) {
|
||||||
|
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||||
_cleanup_free_ char *exe = NULL, *path = NULL;
|
_cleanup_free_ char *exe = NULL, *path = NULL;
|
||||||
bool unlink_path = false;
|
bool unlink_path = false;
|
||||||
const char *data;
|
const char *data;
|
||||||
@ -886,7 +907,14 @@ static int run_gdb(sd_journal *j) {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(j);
|
if (arg_field) {
|
||||||
|
log_error("Option --field/-F only makes sense with list");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = acquire_journal(&j, argv + 1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = focus(j);
|
r = focus(j);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1007,73 +1035,35 @@ static int check_units_active(void) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int coredumpctl_main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
static const Verb verbs[] = {
|
||||||
|
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list },
|
||||||
|
{ "info", VERB_ANY, VERB_ANY, 0, dump_list },
|
||||||
|
{ "dump", VERB_ANY, VERB_ANY, 0, dump_core },
|
||||||
|
{ "gdb", VERB_ANY, VERB_ANY, 0, run_gdb },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
return dispatch_verb(argc, argv, verbs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
_cleanup_(sd_journal_closep) sd_journal*j = NULL;
|
int r, units_active;
|
||||||
int r = 0, units_active;
|
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r < 0)
|
if (r <= 0)
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (arg_action == ACTION_NONE)
|
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
sigbus_install();
|
sigbus_install();
|
||||||
|
|
||||||
if (arg_directory) {
|
|
||||||
r = sd_journal_open_directory(&j, arg_directory, 0);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to open journal: %m");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = journal_access_check_and_warn(j, arg_quiet, true);
|
|
||||||
if (r < 0)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
r = add_matches(j);
|
|
||||||
if (r < 0)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
|
||||||
_cleanup_free_ char *filter;
|
|
||||||
|
|
||||||
filter = journal_make_match_string(j);
|
|
||||||
log_debug("Journal filter: %s", filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
units_active = check_units_active(); /* error is treated the same as 0 */
|
units_active = check_units_active(); /* error is treated the same as 0 */
|
||||||
|
|
||||||
switch(arg_action) {
|
r = coredumpctl_main(argc, argv);
|
||||||
|
|
||||||
case ACTION_LIST:
|
|
||||||
case ACTION_INFO:
|
|
||||||
pager_open(arg_no_pager, false);
|
|
||||||
r = dump_list(j);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACTION_DUMP:
|
|
||||||
r = dump_core(j);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACTION_GDB:
|
|
||||||
r = run_gdb(j);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Shouldn't be here");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (units_active > 0)
|
if (units_active > 0)
|
||||||
printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n",
|
printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user