logs-show.c revision 31f7bf1994523f5b8fd014c69b97e09d7043d9ff
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek This file is part of systemd.
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek Copyright 2012 Lennart Poettering
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (at your option) any later version.
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmekstatic int print_catalog(FILE *f, sd_journal *j) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek _cleanup_free_ char *t = NULL, *z = NULL;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_catalog(j, &t);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek z = strreplace(strstrip(t), "\n", "\n-- ");
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmekstatic int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek memcpy(buf, (const char*) data + fl, nl);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmekstatic bool shall_print(const char *p, size_t l, OutputFlags flags) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmekstatic void print_multiline(FILE *f, unsigned prefix, unsigned n_columns, int flags, int priority, const char* message, size_t message_len) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek const char *color_on = "", *color_off = "";
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek color_on = ANSI_HIGHLIGHT_RED_ON;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek } else if (priority <= LOG_NOTICE) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek for (pos = message; pos < message + message_len; pos = end + 1) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek for (end = pos; end < message + message_len && *end != '\n'; end++)
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if ((flags & OUTPUT_FULL_WIDTH) || (prefix + len + 1 < n_columns))
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek else if (prefix < n_columns && n_columns - prefix >= 3) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek e = ellipsize_mem(pos, len, n_columns - prefix, 90);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, "%s%.*s%s\n", color_on, len, pos, color_off);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, "%s%s%s\n", color_on, e, color_off);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : PRINT_THRESHOLD);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek SD_JOURNAL_FOREACH_DATA(j, data, length) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "_COMM=", &comm, &comm_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "_PID=", &pid, &pid_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = parse_field(data, length, "MESSAGE=", &message, &message_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek strip_tab_ansi(&message, &message_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (priority_len == 1 && *priority >= '0' && *priority <= '7')
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (mode == OUTPUT_SHORT_MONOTONIC) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get monotonic: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (unsigned long long) (t / USEC_PER_SEC),
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (unsigned long long) (t % USEC_PER_SEC));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_realtime_usec(j, &x);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get realtime: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek t = (time_t) (x / USEC_PER_SEC);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to format time.");
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (hostname && shall_print(hostname, hostname_len, flags)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, " %.*s", (int) hostname_len, hostname);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (identifier && shall_print(identifier, identifier_len, flags)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, " %.*s", (int) identifier_len, identifier);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek } else if (comm && shall_print(comm, comm_len, flags)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, " %.*s", (int) comm_len, comm);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (pid && shall_print(pid, pid_len, flags)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, "[%.*s]", (int) pid_len, pid);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek _cleanup_free_ char *cursor = NULL;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek sd_journal_set_data_threshold(j, 0);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_realtime_usec(j, &realtime);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get realtime timestamp: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_cursor(j, &cursor);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get cursor: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek format_timestamp(ts, sizeof(ts), realtime),
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek SD_JOURNAL_FOREACH_DATA(j, data, length) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fieldlen = c - (const char*) data;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if ((flags & OUTPUT_SHOW_ALL) || (length < PRINT_THRESHOLD && utf8_is_printable(data, length))) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, " %.*s=", fieldlen, (const char*)data);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, " %.*s=[%s blob data]\n",
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (int) (c - (const char*) data),
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek _cleanup_free_ char *cursor = NULL;
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek sd_journal_set_data_threshold(j, 0);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_realtime_usec(j, &realtime);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get realtime timestamp: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get monotonic timestamp: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek r = sd_journal_get_cursor(j, &cursor);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek log_error("Failed to get cursor: %s", strerror(-r));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek "__REALTIME_TIMESTAMP=%llu\n"
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek "__MONOTONIC_TIMESTAMP=%llu\n"
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek "_BOOT_ID=%s\n",
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (unsigned long long) realtime,
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek (unsigned long long) monotonic,
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek sd_id128_to_string(boot_id, sid));
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek SD_JOURNAL_FOREACH_DATA(j, data, length) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek /* We already printed the boot id, from the data in
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek * the header, hence let's suppress it here */
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek memcmp(data, "_BOOT_ID=", 9) == 0)
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (!utf8_is_printable(data, length)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fwrite(data, c - (const char*) data, 1, f);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek le64 = htole64(length - (c - (const char*) data) - 1);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fwrite(&le64, sizeof(le64), 1, f);
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
92bd5ff3a062c3f9475b9d9d39b9335bfeb7705eDavid Herrmann const char* p,
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek else if (!utf8_is_printable(p, l)) {
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek fprintf(f, ", %u", (uint8_t) *p);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering } else if (*p == '\n')
2b3ab29de466ae6bd7c3243a5a48c7291cc2af0aZbigniew Jędrzejewski-Szmek else if (*p < ' ')
fputc(*p, f);
static int output_json(
FILE *f,
sd_journal *j,
unsigned n_columns,
const void *data;
assert(j);
fprintf(f,
(unsigned long long) realtime,
(unsigned long long) monotonic,
fprintf(f,
(unsigned long long) realtime,
(unsigned long long) monotonic,
return -ENOMEM;
const char *eq;
if (!eq)
r = -ENOMEM;
goto finish;
free(n);
goto finish;
free(n);
goto finish;
separator = true;
done = true;
const char *eq;
char *kk, *n;
size_t m;
if (!eq)
if (separator) {
r = -ENOMEM;
goto finish;
free(n);
separator = false;
hashmap_remove(h, n);
free(n);
separator = true;
hashmap_remove(h, n);
free(n);
done = false;
separator = true;
} while (!done);
while ((k = hashmap_steal_first_key(h)))
free(k);
hashmap_free(h);
static int output_cat(
FILE *f,
sd_journal *j,
unsigned n_columns,
const void *data;
size_t l;
assert(j);
assert(f);
if (r == -ENOENT)
FILE *f,
sd_journal*j,
unsigned n_columns,
int output_journal(
FILE *f,
sd_journal *j,
unsigned n_columns,
int ret;
if (n_columns <= 0)
return ret;
sd_journal *j,
unsigned n_columns,
unsigned how_many,
unsigned line = 0;
bool need_seek = false;
assert(j);
r = sd_journal_seek_tail(j);
goto finish;
goto finish;
if (need_seek) {
r = sd_journal_next(j);
goto finish;
need_seek = true;
if (not_before > 0) {
if (r == -ESTALE)
goto finish;
line ++;
goto finish;
goto finish;
goto finish;
fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
warn_cutoff = false;
goto finish;
assert(j);
return -ENOMEM;
(r = sd_journal_add_disjunction(j)) ||
(r = sd_journal_add_match(j,
(r = sd_journal_add_disjunction(j)) ||
assert(j);
return -ENOMEM;
(r = sd_journal_add_disjunction(j)) ||
(r = sd_journal_add_disjunction(j)) ||
assert(j);
r = sd_journal_add_conjunction(j);
int show_journal_by_unit(
FILE *f,
const char *unit,
unsigned n_columns,
unsigned how_many,
bool system) {
if (how_many <= 0)
r = add_match_this_boot(j);
if (system)