[systemd-devel] [PATCH] journalctl: add --revert option to show the newest lines first

Lukas Nykryn lnykryn at redhat.com
Thu Feb 28 05:32:57 PST 2013


---
 man/journalctl.xml       |  7 ++++++
 src/journal/journalctl.c | 59 +++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/man/journalctl.xml b/man/journalctl.xml
index 5ed0e1f..768c588 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -185,6 +185,13 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--reverse</option></term>
+
+                                <listitem><para>Reverse output, so the newest
+                                entries are displayed first.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><option>-o</option></term>
                                 <term><option>--output=</option></term>
 
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 0b3a79b..7be68de 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -77,6 +77,7 @@ static bool arg_since_set = false, arg_until_set = false;
 static const char *arg_unit = NULL;
 static const char *arg_field = NULL;
 static bool arg_catalog = false;
+static bool arg_reverse = false;
 
 static enum {
         ACTION_SHOW,
@@ -103,6 +104,7 @@ static int help(void) {
                "  -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"
+               "     --reverse           Show the newest entries first\n"
                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
                "  -x --catalog           Add message explanations where available\n"
@@ -151,7 +153,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SINCE,
                 ARG_UNTIL,
                 ARG_LIST_CATALOG,
-                ARG_UPDATE_CATALOG
+                ARG_UPDATE_CATALOG,
+                ARG_REVERSE
         };
 
         static const struct option options[] = {
@@ -184,6 +187,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "catalog",      no_argument,       NULL, 'x'              },
                 { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
                 { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
+                { "reverse",      no_argument,       NULL, ARG_REVERSE      },
                 { NULL,           0,                 NULL, 0                }
         };
 
@@ -424,6 +428,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_UPDATE_CATALOG;
                         break;
 
+                case ARG_REVERSE:
+                        arg_reverse = true;
+                        break;
+
                 default:
                         log_error("Unknown option code %c", c);
                         return -EINVAL;
@@ -443,6 +451,11 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
+        if (arg_follow && arg_reverse) {
+                log_error("Please specify either --reverse= or --follow=, not both.");
+                return -EINVAL;
+        }
+
         return 1;
 }
 
@@ -994,10 +1007,12 @@ int main(int argc, char *argv[]) {
                         log_error("Failed to seek to cursor: %s", strerror(-r));
                         goto finish;
                 }
+                if (!arg_reverse)
+                        r = sd_journal_next(j);
+                else
+                        r = sd_journal_previous(j);
 
-                r = sd_journal_next(j);
-
-        } else if (arg_since_set) {
+        } else if (arg_since_set && !arg_reverse) {
                 r = sd_journal_seek_realtime_usec(j, arg_since);
                 if (r < 0) {
                         log_error("Failed to seek to date: %s", strerror(-r));
@@ -1005,6 +1020,14 @@ int main(int argc, char *argv[]) {
                 }
                 r = sd_journal_next(j);
 
+        } else if (arg_until_set && arg_reverse) {
+                r = sd_journal_seek_realtime_usec(j, arg_until);
+                if (r < 0) {
+                        log_error("Failed to seek to date: %s", strerror(-r));
+                        goto finish;
+                }
+                r = sd_journal_previous(j);
+
         } else if (arg_lines >= 0) {
                 r = sd_journal_seek_tail(j);
                 if (r < 0) {
@@ -1014,6 +1037,15 @@ int main(int argc, char *argv[]) {
 
                 r = sd_journal_previous_skip(j, arg_lines);
 
+        } else if (arg_reverse) {
+                r = sd_journal_seek_tail(j);
+                if (r < 0) {
+                        log_error("Failed to seek to tail: %s", strerror(-r));
+                        goto finish;
+                }
+
+                r = sd_journal_previous(j);
+
         } else {
                 r = sd_journal_seek_head(j);
                 if (r < 0) {
@@ -1058,7 +1090,10 @@ int main(int argc, char *argv[]) {
                         int flags;
 
                         if (need_seek) {
-                                r = sd_journal_next(j);
+                                if(!arg_reverse)
+                                        r = sd_journal_next(j);
+                                else
+                                        r = sd_journal_previous(j);
                                 if (r < 0) {
                                         log_error("Failed to iterate through journal: %s", strerror(-r));
                                         goto finish;
@@ -1068,7 +1103,7 @@ int main(int argc, char *argv[]) {
                         if (r == 0)
                                 break;
 
-                        if (arg_until_set) {
+                        if (arg_until_set && !arg_reverse) {
                                 usec_t usec;
 
                                 r = sd_journal_get_realtime_usec(j, &usec);
@@ -1080,6 +1115,18 @@ int main(int argc, char *argv[]) {
                                         goto finish;
                         }
 
+                        if (arg_since_set && arg_reverse) {
+                                usec_t usec;
+
+                                r = sd_journal_get_realtime_usec(j, &usec);
+                                if (r < 0) {
+                                        log_error("Failed to determine timestamp: %s", strerror(-r));
+                                        goto finish;
+                                }
+                                if (usec < arg_since)
+                                        goto finish;
+                        }
+
                         if (!arg_merge) {
                                 sd_id128_t boot_id;
 
-- 
1.7.11.7



More information about the systemd-devel mailing list