#include "journal-authenticate.h"
#include "journal-qrcode.h"
#include "fsprg.h"
+#include "unit-name.h"
#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
#endif
static usec_t arg_since, arg_until;
static bool arg_since_set = false, arg_until_set = false;
+static const char *arg_unit = NULL;
+static const char *arg_field = NULL;
static enum {
ACTION_SHOW,
static int help(void) {
printf("%s [OPTIONS...] [MATCH]\n\n"
- "Send control commands to or query the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " -a --all Show all fields, including long and unprintable\n"
+ "Query the journal.\n\n"
+ "Flags:\n"
" -c --cursor=CURSOR Start showing entries from specified cursor\n"
" --since=DATE Start showing entries newer or of the specified date\n"
" --until=DATE Stop showing entries older or of the specified date\n"
+ " -b --this-boot Show data only from current boot\n"
+ " -u --unit=UNIT Show data only from the specified unit\n"
+ " -p --priority=RANGE Show only messages within the specified priority range\n\n"
" -f --follow Follow journal\n"
" -n --lines[=INTEGER] Number of journal entries to show\n"
" --no-tail Show all lines, even in follow mode\n"
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
" verbose, export, json, json-pretty, json-sse, cat)\n"
+ " -a --all Show all fields, including long and unprintable\n"
" -q --quiet Don't show privilege warning\n"
+ " --no-pager Do not pipe output into a pager\n"
" -m --merge Show entries from all available journals\n"
- " -b --this-boot Show data only from current boot\n"
" -D --directory=PATH Show journal files from directory\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n\n"
- "Commands:\n"
+#ifdef HAVE_GCRYPT
+ " --interval=TIME Time interval for changing the FSS sealing key\n"
+ " --verify-key=KEY Specify FSS verification key\n"
+#endif
+ "\nCommands:\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
" --new-id128 Generate a new 128 Bit ID\n"
" --header Show journal header information\n"
" --disk-usage Show total disk usage\n"
+ " -F --field=FIELD List all values a certain field takes\n"
#ifdef HAVE_GCRYPT
" --setup-keys Generate new FSS key pair\n"
- " --interval=TIME Time interval for changing the FSS sealing key\n"
" --verify Verify journal file consistency\n"
- " --verify-key=KEY Specify FSS verification key\n"
#endif
, program_invocation_short_name);
{ "cursor", required_argument, NULL, 'c' },
{ "since", required_argument, NULL, ARG_SINCE },
{ "until", required_argument, NULL, ARG_UNTIL },
+ { "unit", required_argument, NULL, 'u' },
+ { "field", required_argument, NULL, 'F' },
{ NULL, 0, NULL, 0 }
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:", options, NULL)) >= 0) {
switch (c) {
case 'o':
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
- log_error("Unknown output '%s'.", optarg);
+ log_error("Unknown output format '%s'.", optarg);
return -EINVAL;
}
+ if (arg_output == OUTPUT_EXPORT ||
+ arg_output == OUTPUT_JSON ||
+ arg_output == OUTPUT_JSON_PRETTY ||
+ arg_output == OUTPUT_JSON_SSE ||
+ arg_output == OUTPUT_CAT)
+ arg_quiet = true;
+
break;
case 'a':
arg_until_set = true;
break;
+ case 'u':
+ arg_unit = optarg;
+ break;
+
case '?':
return -EINVAL;
+ case 'F':
+ arg_field = optarg;
+ break;
+
default:
log_error("Unknown option code %c", c);
return -EINVAL;
return 0;
}
+static int add_unit(sd_journal *j) {
+ _cleanup_free_ char *m = NULL, *u = NULL;
+ int r;
+
+ assert(j);
+
+ if (isempty(arg_unit))
+ return 0;
+
+ u = unit_name_mangle(arg_unit);
+ if (!u)
+ return log_oom();
+
+ m = strappend("_SYSTEMD_UNIT=", u);
+ if (!m)
+ return log_oom();
+
+ r = sd_journal_add_match(j, m, strlen(m));
+ if (r < 0) {
+ log_error("Failed to add match: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
static int add_priorities(sd_journal *j) {
char match[] = "PRIORITY=0";
int i, r;
if (r < 0)
goto finish;
+ r = add_unit(j);
+ if (r < 0)
+ goto finish;
+
r = add_matches(j, argv + optind);
if (r < 0)
goto finish;
if (r < 0)
goto finish;
+ if (arg_field) {
+ const void *data;
+ size_t size;
+
+ r = sd_journal_query_unique(j, arg_field);
+ if (r < 0) {
+ log_error("Failed to query unique data objects: %s", strerror(-r));
+ goto finish;
+ }
+
+ SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
+ const void *eq;
+
+ eq = memchr(data, '=', size);
+ if (eq)
+ printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
+ else
+ printf("%.*s\n", (int) size, (const char*) data);
+ }
+
+ r = 0;
+ goto finish;
+ }
+
if (arg_cursor) {
r = sd_journal_seek_cursor(j, arg_cursor);
if (r < 0) {
if (r > 0) {
if (arg_follow)
- printf("---- Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start));
+ printf("-- Logs begin at %s. --\n",
+ format_timestamp(start_buf, sizeof(start_buf), start));
else
- printf("---- Logs begin at %s, end at %s.\n",
+ printf("-- Logs begin at %s, end at %s. --\n",
format_timestamp(start_buf, sizeof(start_buf), start),
format_timestamp(end_buf, sizeof(end_buf), end));
}
}
for (;;) {
- while (arg_lines == 0 || n_shown < arg_lines) {
+ while (arg_lines == 0 || arg_follow || n_shown < arg_lines) {
int flags;
if (need_seek) {
if (r >= 0) {
if (previous_boot_id_valid &&
!sd_id128_equal(boot_id, previous_boot_id))
- printf(ANSI_HIGHLIGHT_ON "---- Reboot ----" ANSI_HIGHLIGHT_OFF "\n");
+ printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
previous_boot_id = boot_id;
previous_boot_id_valid = true;