summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-05-05 14:00:26 +0200
committerGitHub <noreply@github.com>2020-05-05 14:00:26 +0200
commit640ebaa9526ddfdb73feac464707bbac49c83a46 (patch)
treefed3d7d8c7db0c0d8c1ae43f7b7ad07768f91d1b
parentc83347b49de7a8d0cb7d51129b2534aa7e4a2a2e (diff)
parent5444520628830aacab85be630a6cdeb179ff510b (diff)
downloadsystemd-640ebaa9526ddfdb73feac464707bbac49c83a46.tar.gz
Merge pull request #15648 from poettering/journalctl-cat-beefup
journalctl: honour --output-fields= in -o cat mode
-rw-r--r--man/journalctl.xml16
-rw-r--r--src/shared/logs-show.c98
-rw-r--r--src/shared/logs-show.h2
3 files changed, 72 insertions, 44 deletions
diff --git a/man/journalctl.xml b/man/journalctl.xml
index d6d475ed97..6e4728b013 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -374,9 +374,10 @@
<option>cat</option>
</term>
<listitem>
- <para>generates a very terse output, only showing the
- actual message of each journal entry with no metadata,
- not even a timestamp.</para>
+ <para>generates a very terse output, only showing the actual message of each journal entry
+ with no metadata, not even a timestamp. If combined with the
+ <option>--output-fields=</option> option will output the listed fields for each log record,
+ instead of the message.</para>
</listitem>
</varlistentry>
@@ -398,10 +399,11 @@
<varlistentry>
<term><option>--output-fields=</option></term>
- <listitem><para>A comma separated list of the fields which should be included in the output. This has an
- effect only for the output modes which would normally show all fields (<option>verbose</option>,
- <option>export</option>, <option>json</option>, <option>json-pretty</option>, <option>json-sse</option> and
- <option>json-seq</option>). The <literal>__CURSOR</literal>, <literal>__REALTIME_TIMESTAMP</literal>,
+ <listitem><para>A comma separated list of the fields which should be included in the output. This has
+ an effect only for the output modes which would normally show all fields (<option>verbose</option>,
+ <option>export</option>, <option>json</option>, <option>json-pretty</option>,
+ <option>json-sse</option> and <option>json-seq</option>), as well as on <option>cat</option>. For the
+ former, the <literal>__CURSOR</literal>, <literal>__REALTIME_TIMESTAMP</literal>,
<literal>__MONOTONIC_TIMESTAMP</literal>, and <literal>_BOOT_ID</literal> fields are always
printed.</para></listitem>
</varlistentry>
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 2bfd0b60c2..a55d307447 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -131,7 +131,7 @@ static int field_set_test(Set *fields, const char *name, size_t n) {
if (!s)
return log_oom();
- return set_get(fields, s) ? 1 : 0;
+ return set_contains(fields, s);
}
static bool shall_print(const char *p, size_t l, OutputFlags flags) {
@@ -158,7 +158,7 @@ static bool print_multiline(
bool audit,
const char* message,
size_t message_len,
- size_t highlight[2]) {
+ size_t highlight[static 2]) {
const char *color_on = "", *color_off = "", *highlight_on = "";
const char *pos, *end;
@@ -370,7 +370,7 @@ static int output_short(
unsigned n_columns,
OutputFlags flags,
Set *output_fields,
- const size_t highlight[2]) {
+ const size_t highlight[static 2]) {
int r;
const void *data;
@@ -534,7 +534,7 @@ static int output_verbose(
unsigned n_columns,
OutputFlags flags,
Set *output_fields,
- const size_t highlight[2]) {
+ const size_t highlight[static 2]) {
const void *data;
size_t length;
@@ -653,7 +653,7 @@ static int output_export(
unsigned n_columns,
OutputFlags flags,
Set *output_fields,
- const size_t highlight[2]) {
+ const size_t highlight[static 2]) {
sd_id128_t boot_id;
char sid[SD_ID128_STRING_MAX];
@@ -883,7 +883,7 @@ static int output_json(
unsigned n_columns,
OutputFlags flags,
Set *output_fields,
- const size_t highlight[2]) {
+ const size_t highlight[static 2]) {
char sid[SD_ID128_STRING_MAX], usecbuf[DECIMAL_STR_MAX(usec_t)];
_cleanup_(json_variant_unrefp) JsonVariant *object = NULL;
@@ -1016,57 +1016,83 @@ finish:
return r;
}
-static int output_cat(
+static int output_cat_field(
FILE *f,
sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
OutputFlags flags,
- Set *output_fields,
- const size_t highlight[2]) {
+ const char *field,
+ const size_t highlight[static 2]) {
+ const char *highlight_on, *highlight_off;
const void *data;
- size_t l;
+ size_t l, fl;
int r;
- const char *highlight_on = "", *highlight_off = "";
- assert(j);
- assert(f);
-
- if (flags & OUTPUT_COLOR) {
+ if (FLAGS_SET(flags, OUTPUT_COLOR)) {
highlight_on = ANSI_HIGHLIGHT_RED;
highlight_off = ANSI_NORMAL;
- }
-
- sd_journal_set_data_threshold(j, 0);
+ } else
+ highlight_on = highlight_off = "";
- r = sd_journal_get_data(j, "MESSAGE", &data, &l);
+ r = sd_journal_get_data(j, field, &data, &l);
if (r == -EBADMSG) {
log_debug_errno(r, "Skipping message we can't read: %m");
return 0;
}
- if (r < 0) {
- /* An entry without MESSAGE=? */
- if (r == -ENOENT)
- return 0;
-
+ if (r == -ENOENT) /* An entry without the requested field */
+ return 0;
+ if (r < 0)
return log_error_errno(r, "Failed to get data: %m");
- }
- assert(l >= 8);
+ fl = strlen(field);
+ assert(l >= fl + 1);
+ assert(((char*) data)[fl] == '=');
+
+ data = (const uint8_t*) data + fl + 1;
+ l -= fl + 1;
- if (highlight && (flags & OUTPUT_COLOR)) {
+ if (highlight && FLAGS_SET(flags, OUTPUT_COLOR)) {
assert(highlight[0] <= highlight[1]);
- assert(highlight[1] <= l - 8);
+ assert(highlight[1] <= l);
- fwrite((const char*) data + 8, 1, highlight[0], f);
+ fwrite((const char*) data, 1, highlight[0], f);
fwrite(highlight_on, 1, strlen(highlight_on), f);
- fwrite((const char*) data + 8 + highlight[0], 1, highlight[1] - highlight[0], f);
+ fwrite((const char*) data + highlight[0], 1, highlight[1] - highlight[0], f);
fwrite(highlight_off, 1, strlen(highlight_off), f);
- fwrite((const char*) data + 8 + highlight[1], 1, l - 8 - highlight[1], f);
+ fwrite((const char*) data + highlight[1], 1, l - highlight[1], f);
} else
- fwrite((const char*) data + 8, 1, l - 8, f);
+ fwrite((const char*) data, 1, l, f);
+
fputc('\n', f);
+ return 0;
+}
+
+static int output_cat(
+ FILE *f,
+ sd_journal *j,
+ OutputMode mode,
+ unsigned n_columns,
+ OutputFlags flags,
+ Set *output_fields,
+ const size_t highlight[static 2]) {
+
+ const char *field;
+ Iterator iterator;
+ int r;
+
+ assert(j);
+ assert(f);
+
+ (void) sd_journal_set_data_threshold(j, 0);
+
+ if (set_isempty(output_fields))
+ return output_cat_field(f, j, flags, "MESSAGE", highlight);
+
+ SET_FOREACH(field, output_fields, iterator) {
+ r = output_cat_field(f, j, flags, field, streq(field, "MESSAGE") ? highlight : NULL);
+ if (r < 0)
+ return r;
+ }
return 0;
}
@@ -1078,7 +1104,7 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(
unsigned n_columns,
OutputFlags flags,
Set *output_fields,
- const size_t highlight[2]) = {
+ const size_t highlight[static 2]) = {
[OUTPUT_SHORT] = output_short,
[OUTPUT_SHORT_ISO] = output_short,
@@ -1104,7 +1130,7 @@ int show_journal_entry(
unsigned n_columns,
OutputFlags flags,
char **output_fields,
- const size_t highlight[2],
+ const size_t highlight[static 2],
bool *ellipsized) {
int ret;
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
index 345efa4b2b..62be1b157f 100644
--- a/src/shared/logs-show.h
+++ b/src/shared/logs-show.h
@@ -20,7 +20,7 @@ int show_journal_entry(
unsigned n_columns,
OutputFlags flags,
char **output_fields,
- const size_t highlight[2],
+ const size_t highlight[static 2],
bool *ellipsized);
int show_journal(
FILE *f,