diff options
-rw-r--r-- | man/journalctl.xml | 11 | ||||
-rw-r--r-- | shell-completion/bash/journalctl | 2 | ||||
-rw-r--r-- | shell-completion/zsh/_journalctl | 1 | ||||
-rw-r--r-- | src/journal/journalctl.c | 65 |
4 files changed, 67 insertions, 12 deletions
diff --git a/man/journalctl.xml b/man/journalctl.xml index 7ff0a479e0..89878c5408 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -619,6 +619,17 @@ </varlistentry> <varlistentry> + <term><option>--cursor-file=<replaceable>FILE</replaceable></option></term> + + <listitem><para>If <replaceable>FILE</replaceable> exists and contains a + cursor, start showing entries <emphasis>after</emphasis> this location. + Otherwise the show entries according the other given options. At the end, + write the cursor of the last entry to <replaceable>FILE</replaceable>. Use + this option to continually read the journal by sequentially calling + <command>journalctl</command>.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--after-cursor=</option></term> <listitem><para>Start showing entries from the location in the diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl index bcd4533a63..f2e882ca00 100644 --- a/shell-completion/bash/journalctl +++ b/shell-completion/bash/journalctl @@ -48,7 +48,7 @@ _journalctl() { -M --machine -o --output -u --unit --user-unit -p --priority --root --case-sensitive' [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until - --after-cursor --verify-key -g --grep + --after-cursor --cursor-file --verify-key -g --grep --vacuum-size --vacuum-time --vacuum-files --output-fields' ) diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl index aa6ace0485..a4df88ef4b 100644 --- a/shell-completion/zsh/_journalctl +++ b/shell-completion/zsh/_journalctl @@ -104,6 +104,7 @@ _arguments -s \ {-p+,--priority=}'[Show only messages within the specified priority range]:priority:_journalctl_field_values PRIORITY' \ {-t+,--identifier=}'[Show only messages with the specified syslog identifier]:identifier:_journalctl_field_values SYSLOG_IDENTIFIER' \ {-c+,--cursor=}'[Start showing entries from the specified cursor]:cursors:_journalctl_field_values __CURSORS' \ + '--cursor-file=[Show entries using cursor store in file]:file:_files' \ '--after-cursor=[Start showing entries from after the specified cursor]:cursors:_journalctl_field_values __CURSORS' \ '--since=[Start showing entries on or newer than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ '--until=[Stop showing entries on or older than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 14a02eda74..75b23c7144 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -119,6 +119,7 @@ static int arg_boot_offset = 0; static bool arg_dmesg = false; static bool arg_no_hostname = false; static const char *arg_cursor = NULL; +static const char *arg_cursor_file = NULL; static const char *arg_after_cursor = NULL; static bool arg_show_cursor = false; static const char *arg_directory = NULL; @@ -315,6 +316,7 @@ static int help(void) { " -c --cursor=CURSOR Show entries starting at the specified cursor\n" " --after-cursor=CURSOR Show entries after the specified cursor\n" " --show-cursor Print the cursor after all the entries\n" + " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n" " -b --boot[=ID] Show current boot or the specified boot\n" " --list-boots Show terse information about recorded boots\n" " -k --dmesg Show kernel message log from the current boot\n" @@ -396,6 +398,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERIFY_KEY, ARG_DISK_USAGE, ARG_AFTER_CURSOR, + ARG_CURSOR_FILE, ARG_SHOW_CURSOR, ARG_USER_UNIT, ARG_LIST_CATALOG, @@ -450,6 +453,7 @@ static int parse_argv(int argc, char *argv[]) { { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, { "cursor", required_argument, NULL, 'c' }, + { "cursor-file", required_argument, NULL, ARG_CURSOR_FILE }, { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR }, { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR }, { "since", required_argument, NULL, 'S' }, @@ -661,6 +665,10 @@ static int parse_argv(int argc, char *argv[]) { arg_cursor = optarg; break; + case ARG_CURSOR_FILE: + arg_cursor_file = optarg; + break; + case ARG_AFTER_CURSOR: arg_after_cursor = optarg; break; @@ -2077,6 +2085,7 @@ static int wait_for_change(sd_journal *j, int poll_fd) { int main(int argc, char *argv[]) { bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false; + bool use_cursor = false, after_cursor = false; _cleanup_(sd_journal_closep) sd_journal *j = NULL; sd_id128_t previous_boot_id; int n_shown = 0, r, poll_fd = -1; @@ -2420,19 +2429,41 @@ int main(int argc, char *argv[]) { } } - if (arg_cursor || arg_after_cursor) { - r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor); - if (r < 0) { - log_error_errno(r, "Failed to seek to cursor: %m"); - goto finish; + if (arg_cursor || arg_after_cursor || arg_cursor_file) { + _cleanup_free_ char *cursor_from_file = NULL; + const char *cursor = arg_cursor ?: arg_after_cursor; + + if (arg_cursor_file) { + r = read_one_line_file(arg_cursor_file, &cursor_from_file); + if (r < 0 && r != -ENOENT) { + log_error_errno(r, "Failed to read cursor file %s: %m", arg_cursor_file); + goto finish; + } + + if (r > 0) { + cursor = cursor_from_file; + after_cursor = true; + } + } else + after_cursor = !!arg_after_cursor; + + if (cursor) { + r = sd_journal_seek_cursor(j, cursor); + if (r < 0) { + log_error_errno(r, "Failed to seek to cursor: %m"); + goto finish; + } + use_cursor = true; } + } + if (use_cursor) { if (!arg_reverse) - r = sd_journal_next_skip(j, 1 + !!arg_after_cursor); + r = sd_journal_next_skip(j, 1 + after_cursor); else - r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor); + r = sd_journal_previous_skip(j, 1 + after_cursor); - if (arg_after_cursor && r < 2) { + if (after_cursor && r < 2) { /* We couldn't find the next entry after the cursor. */ if (arg_follow) need_seek = true; @@ -2661,14 +2692,26 @@ int main(int argc, char *argv[]) { if (n_shown == 0 && !arg_quiet) printf("-- No entries --\n"); - if (arg_show_cursor) { + if (arg_show_cursor || arg_cursor_file) { _cleanup_free_ char *cursor = NULL; r = sd_journal_get_cursor(j, &cursor); if (r < 0 && r != -EADDRNOTAVAIL) log_error_errno(r, "Failed to get cursor: %m"); - else if (r >= 0) - printf("-- cursor: %s\n", cursor); + else if (r >= 0) { + if (arg_show_cursor) + printf("-- cursor: %s\n", cursor); + + if (arg_cursor_file) { + r = write_string_file(arg_cursor_file, cursor, + WRITE_STRING_FILE_CREATE | + WRITE_STRING_FILE_ATOMIC); + if (r < 0) + log_error_errno(r, + "Failed to write new cursor to %s: %m", + arg_cursor_file); + } + } } break; |