Skip to content

Commit

Permalink
journalctl: make --list-boots support -n/--lines= option
Browse files Browse the repository at this point in the history
Also mention that -r/--reverse is supported by the command.
  • Loading branch information
yuwata committed May 10, 2024
1 parent 5da5d84 commit d0936a7
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 16 deletions.
14 changes: 10 additions & 4 deletions man/journalctl.xml
Original file line number Diff line number Diff line change
Expand Up @@ -851,10 +851,16 @@
<varlistentry>
<term><option>--list-boots</option></term>

<listitem><para>Show a tabular list of boot numbers (relative to the current boot), their IDs, and
the timestamps of the first and last message pertaining to the boot.</para>

<xi:include href="version-info.xml" xpointer="v209"/></listitem>
<listitem>
<para>Show a tabular list of boot numbers (relative to the current boot), their IDs, and the
timestamps of the first and last message pertaining to the boot. When specified with
<option>-n/--lines=<optional>+</optional><replaceable>N</replaceable></option> option, only the
first (when the number prefixed with <literal>+</literal>) or the last (without prefix)
<replaceable>N</replaceable> entries will be shown. When specified with
<option>-r/--reverse</option>, the list will be shown in the reverse order.</para>

<xi:include href="version-info.xml" xpointer="v209"/>
</listitem>
</varlistentry>

<varlistentry>
Expand Down
28 changes: 22 additions & 6 deletions src/journal/journalctl-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ int action_list_boots(void) {
if (r < 0)
return r;

r = journal_get_boots(j, &boots, &n_boots);
r = journal_get_boots(
j,
/* advance_older = */ arg_lines_needs_seek_end(),
/* max_ids = */ arg_lines >= 0 ? (size_t) arg_lines : SIZE_MAX,
&boots, &n_boots);
if (r < 0)
return log_error_errno(r, "Failed to determine boots: %m");
if (r == 0)
Expand All @@ -132,13 +136,25 @@ int action_list_boots(void) {
(void) table_set_sort(table, (size_t) 0);
(void) table_set_reverse(table, 0, arg_reverse);

FOREACH_ARRAY(i, boots, n_boots) {
for (int i = 0; i < (int) n_boots; i++) {
int index;

if (arg_lines_needs_seek_end())
/* With --lines=N, we only know the negative index, and the older ID is located earlier. */
index = -i;
else if (arg_lines >= 0)
/* With --lines=+N, we only know the positive index, and the newer ID is located earlier. */
index = i + 1;
else
/* Otherwise, show negative index. Note, in this case, newer ID is located earlier. */
index = i + 1 - (int) n_boots;

r = table_add_many(table,
TABLE_INT, (int)(i - boots) - (int) n_boots + 1,
TABLE_INT, index,
TABLE_SET_ALIGN_PERCENT, 100,
TABLE_ID128, i->id,
TABLE_TIMESTAMP, i->first_usec,
TABLE_TIMESTAMP, i->last_usec);
TABLE_ID128, boots[i].id,
TABLE_TIMESTAMP, boots[i].first_usec,
TABLE_TIMESTAMP, boots[i].last_usec);
if (r < 0)
return table_log_add_error(r);
}
Expand Down
2 changes: 1 addition & 1 deletion src/journal/journalctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Please specify either --reverse or --follow, not both.");

if (arg_lines >= 0 && arg_lines_oldest && (arg_reverse || arg_follow))
if (arg_action == ACTION_SHOW && arg_lines >= 0 && arg_lines_oldest && (arg_reverse || arg_follow))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--lines=+N is unsupported when --reverse or --follow is specified.");

Expand Down
32 changes: 31 additions & 1 deletion src/libsystemd/sd-journal/test-journal-interleaving.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,10 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) {
setup();

assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_se(journal_get_boots(j, &boots, &n_boots) >= 0);
assert_se(journal_get_boots(
j,
/* advance_older = */ false, /* max_ids = */ SIZE_MAX,
&boots, &n_boots) >= 0);
assert_se(boots);
assert_se(n_boots == n_boots_expected);

Expand All @@ -492,6 +495,33 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) {
}
}

for (size_t i = 0; i <= n_boots_expected + 1; i++) {
_cleanup_free_ BootId *boots_limited = NULL;
size_t n_boots_limited;

assert_se(journal_get_boots(
j,
/* advance_older = */ false, /* max_ids = */ i,
&boots_limited, &n_boots_limited) >= 0);
assert_se(boots_limited || i == 0);
assert_se(n_boots_limited == MIN(i, n_boots_expected));
assert_se(memcmp_safe(boots, boots_limited, n_boots_limited * sizeof(BootId)) == 0);
}

for (size_t i = 0; i <= n_boots_expected + 1; i++) {
_cleanup_free_ BootId *boots_limited = NULL;
size_t n_boots_limited;

assert_se(journal_get_boots(
j,
/* advance_older = */ true, /* max_ids = */ i,
&boots_limited, &n_boots_limited) >= 0);
assert_se(boots_limited || i == 0);
assert_se(n_boots_limited == MIN(i, n_boots_expected));
for (size_t k = 0; k < n_boots_limited; k++)
assert_se(memcmp(&boots[n_boots - k - 1], &boots_limited[k], sizeof(BootId)) == 0);
}

test_done(t);
}

Expand Down
18 changes: 15 additions & 3 deletions src/shared/logs-show.c
Original file line number Diff line number Diff line change
Expand Up @@ -1986,7 +1986,13 @@ int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t
}
}

int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) {
int journal_get_boots(
sd_journal *j,
bool advance_older,
size_t max_ids,
BootId **ret_boots,
size_t *ret_n_boots) {

_cleanup_free_ BootId *boots = NULL;
size_t n_boots = 0;
int r;
Expand All @@ -1997,7 +2003,10 @@ int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) {

sd_journal_flush_matches(j);

r = sd_journal_seek_head(j); /* seek to oldest */
if (advance_older)
r = sd_journal_seek_tail(j); /* seek to newest */
else
r = sd_journal_seek_head(j); /* seek to oldest */
if (r < 0)
return r;

Expand All @@ -2010,7 +2019,10 @@ int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) {
for (;;) {
BootId boot;

r = discover_next_boot(j, previous_boot_id, /* advance_older = */ false, &boot);
if (n_boots >= max_ids)
break;

r = discover_next_boot(j, previous_boot_id, advance_older, &boot);
if (r < 0)
return r;
if (r == 0)
Expand Down
7 changes: 6 additions & 1 deletion src/shared/logs-show.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ void json_escape(
OutputFlags flags);

int journal_find_boot(sd_journal *j, sd_id128_t boot_id, int offset, sd_id128_t *ret);
int journal_get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots);
int journal_get_boots(
sd_journal *j,
bool advance_older,
size_t max_ids,
BootId **ret_boots,
size_t *ret_n_boots);

0 comments on commit d0936a7

Please sign in to comment.