[Libguestfs] [PATCH] fish: add journal-view command

Maros Zatko mzatko at redhat.com
Mon Feb 23 15:20:32 UTC 2015


Lets user view journald log from VM in a similar format as journalctl
uses.

Fixes RFE: journal reader in guestfish (RHBZ#988100)
---
 fish/Makefile.am     |   1 +
 fish/journal.c       | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++
 generator/actions.ml |   9 ++++
 3 files changed, 138 insertions(+)
 create mode 100644 fish/journal.c

diff --git a/fish/Makefile.am b/fish/Makefile.am
index c4b82ae..e4b4fcf 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -94,6 +94,7 @@ guestfish_SOURCES = \
 	glob.c \
 	help.c \
 	hexedit.c \
+	journal.c \
 	lcd.c \
 	man.c \
 	more.c \
diff --git a/fish/journal.c b/fish/journal.c
new file mode 100644
index 0000000..5839330
--- /dev/null
+++ b/fish/journal.c
@@ -0,0 +1,128 @@
+/* guestfish - guest filesystem shell
+ * Copyright (C) 2009-2015 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libintl.h>
+#include <time.h>
+#include <syslog.h>
+
+#include "fish.h"
+
+/* Find the value of the named field from the list of attributes.  If
+ * not found, returns NULL (not an error).  If found, returns a
+ * pointer to the field, and the length of the field.  NOTE: The field
+ * is NOT \0-terminated, so you have to print it using "%.*s".
+ *
+ * There may be multiple fields with the same name.  In this case, the
+ * function returns the first entry.
+ */
+static const char *
+get_journal_field (const struct guestfs_xattr_list *xattrs, const char *name,
+                   size_t *len_rtn)
+{
+  uint32_t i;
+
+  for (i = 0; i < xattrs->len; ++i) {
+    if (STREQ (name, xattrs->val[i].attrname)) {
+      *len_rtn = xattrs->val[i].attrval_len;
+      return xattrs->val[i].attrval;
+    }
+  }
+
+  return NULL;                  /* not found */
+}
+
+static const char *const log_level_table[] = {
+  [LOG_EMERG] = "emerg",
+  [LOG_ALERT] = "alert",
+  [LOG_CRIT] = "crit",
+  [LOG_ERR] = "err",
+  [LOG_WARNING] = "warning",
+  [LOG_NOTICE] = "notice",
+  [LOG_INFO] = "info",
+  [LOG_DEBUG] = "debug"
+};
+
+int
+run_journal_view (const char *cmd, size_t argc, char *argv[])
+{
+  int r;
+  int errors = 0;
+  while ((r = guestfs_journal_next(g)) > 0) {
+    CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL;
+    const char *message, *command, *pid, *ident, *prio;
+    size_t message_len, command_len, pid_len, ident_len, prio_len;
+    int64_t ts;
+    int priority = LOG_INFO;
+
+    xattrs = guestfs_journal_get (g);
+    if (xattrs == NULL)
+      return -1;
+
+    ts = guestfs_journal_get_realtime_usec (g);
+    /* Timestamp. */
+    if (ts >= 0) {
+      char buf[64];
+      time_t t = ts / 1000000;
+      struct tm tm;
+
+      if (strftime (buf, sizeof buf, "%b %d %H:%M:%S",
+                    localtime_r (&t, &tm)) <= 0) {
+        fprintf (stderr, _("could not format journal entry timestamp\n"));
+        errors++;
+        continue;
+      }
+      fputs (buf, stdout);
+    }
+
+    // Show identifier or command name
+    ident = get_journal_field (xattrs, "SYSLOG_IDENTIFIER", &ident_len);
+    command = get_journal_field (xattrs, "_COMM", &command_len);
+    if (ident)
+      printf (" %.*s", (int) ident_len, ident);
+    else if (command)
+      printf (" %.*s", (int) command_len, command);
+
+    // Show PID
+    pid = get_journal_field (xattrs, "_PID", &pid_len);
+    if (pid)
+      printf ("[%.*s]", (int) pid_len, pid);
+
+    // Show priority, this is not in journalctl output by default
+    prio = get_journal_field (xattrs, "PRIORITY", &prio_len);
+    if (prio && *prio >= '0' && *prio <= '7')
+      priority = *prio - '0';
+    printf (" %s:", log_level_table[priority]);
+
+    // Show message
+    message = get_journal_field (xattrs, "MESSAGE", &message_len);
+    if (message)
+      printf (" %.*s", (int) message_len, message);
+
+    printf ("\n");
+  }
+
+  return errors > 0 ? -1 : 0;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index c995787..c31b9a8 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12667,6 +12667,15 @@ environment variable.
 See also L</hexdump>." };
 
   { defaults with
+    name = "journal_view";
+    shortdesc = "view journald log";
+    longdesc = "  journal-view
+
+View journald log in format similar to journalctl.
+
+Use C<journal-open> first." };
+
+  { defaults with
     name = "lcd";
     shortdesc = "change working directory";
     longdesc = " lcd directory
-- 
1.9.3




More information about the Libguestfs mailing list