mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-12 08:58:20 +03:00
Merge pull request #12597 from keszybz/analyze-timestamp
Analyze timestamps
This commit is contained in:
commit
1c99d2e0c5
@ -93,7 +93,13 @@
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">calendar</arg>
|
||||
<arg choice="plain" rep="repeat"><replaceable>SPECS</replaceable></arg>
|
||||
<arg choice="plain" rep="repeat"><replaceable>SPEC</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">timestamp</arg>
|
||||
<arg choice="plain" rep="repeat"><replaceable>TIMESTAMP</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
@ -360,7 +366,8 @@ $ eog targets.svg</programlisting>
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>. By
|
||||
default, only the next time the calendar expression will elapse is shown; use
|
||||
<option>--iterations=</option> to show the specified number of next times the expression
|
||||
elapses.</para>
|
||||
elapses. Each time the expression elapses forms a timestamp, see the <command>timestamp</command>
|
||||
verb below.</para>
|
||||
|
||||
<example>
|
||||
<title>Show leap days in the near future</title>
|
||||
@ -382,13 +389,47 @@ Normalized form: *-02-29 00:00:00
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze timestamp <replaceable>TIMESTAMP</replaceable>...</command></title>
|
||||
|
||||
<para>This command parses a timestamp (i.e. a single point in time) and outputs the normalized form and
|
||||
the difference between this timestamp and now. The timestamp should adhere to the syntax documented in
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||
section "PARSING TIMESTAMPS".</para>
|
||||
|
||||
<example>
|
||||
<title>Show parsing of timestamps</title>
|
||||
|
||||
<programlisting>$ systemd-analyze timestamp yesterday now tomorrow
|
||||
Original form: yesterday
|
||||
Normalized form: Mon 2019-05-20 00:00:00 CEST
|
||||
(in UTC): Sun 2019-05-19 22:00:00 UTC
|
||||
UNIX seconds: @15583032000
|
||||
From now: 1 day 9h ago
|
||||
|
||||
Original form: now
|
||||
Normalized form: Tue 2019-05-21 09:48:39 CEST
|
||||
(in UTC): Tue 2019-05-21 07:48:39 UTC
|
||||
UNIX seconds: @1558424919.659757
|
||||
From now: 43us ago
|
||||
|
||||
Original form: tomorrow
|
||||
Normalized form: Wed 2019-05-22 00:00:00 CEST
|
||||
(in UTC): Tue 2019-05-21 22:00:00 UTC
|
||||
UNIX seconds: @15584760000
|
||||
From now: 14h left
|
||||
</programlisting>
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze timespan <replaceable>EXPRESSION</replaceable>...</command></title>
|
||||
|
||||
<para>This command parses a time span and outputs the normalized form and the equivalent value in
|
||||
microseconds. The time span should adhere to the same syntax documented in
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
Values without associated magnitudes are parsed as seconds.</para>
|
||||
<para>This command parses a time span (i.e. a difference between two timestamps) and outputs the
|
||||
normalized form and the equivalent value in microseconds. The time span should adhere to the syntax
|
||||
documented in
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||
section "PARSING TIME SPANS". Values without units are parsed as seconds.</para>
|
||||
|
||||
<example>
|
||||
<title>Show parsing of timespans</title>
|
||||
|
@ -173,6 +173,10 @@ tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00
|
||||
<programlisting>2 months 5 days ago</programlisting>
|
||||
|
||||
<para>Note that a relative timestamp is also accepted where a timestamp is expected (see above).</para>
|
||||
|
||||
<para>Use the <command>timestamp</command> command of
|
||||
<citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry> to
|
||||
validate and normalize timestamps for testing purposes.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -1673,6 +1673,18 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan) {
|
||||
if (calendar && calendar_spec_from_string(p, NULL) >= 0)
|
||||
log_notice("Hint: this expression is a valid calendar specification. "
|
||||
"Use 'systemd-analyze calendar \"%s\"' instead?", p);
|
||||
if (timestamp && parse_timestamp(p, NULL) >= 0)
|
||||
log_notice("Hint: this expression is a valid timestamp. "
|
||||
"Use 'systemd-analyze timestamp \"%s\"' instead?", p);
|
||||
if (timespan && parse_time(p, NULL, USEC_PER_SEC) >= 0)
|
||||
log_notice("Hint: this expression is a valid timespan. "
|
||||
"Use 'systemd-analyze timespan \"%s\"' instead?", p);
|
||||
}
|
||||
|
||||
static int dump_timespan(int argc, char *argv[], void *userdata) {
|
||||
char **input_timespan;
|
||||
|
||||
@ -1682,12 +1694,18 @@ static int dump_timespan(int argc, char *argv[], void *userdata) {
|
||||
char ft_buf[FORMAT_TIMESPAN_MAX];
|
||||
|
||||
r = parse_time(*input_timespan, &output_usecs, USEC_PER_SEC);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan);
|
||||
parsing_hint(*input_timespan, true, true, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
printf("Original: %s\n", *input_timespan);
|
||||
printf(" %ss: %" PRIu64 "\n", special_glyph(SPECIAL_GLYPH_MU), output_usecs);
|
||||
printf(" Human: %s\n", format_timespan(ft_buf, sizeof(ft_buf), output_usecs, usec_magnitude));
|
||||
printf(" Human: %s%s%s\n",
|
||||
ansi_highlight(),
|
||||
format_timespan(ft_buf, sizeof(ft_buf), output_usecs, usec_magnitude),
|
||||
ansi_normal());
|
||||
|
||||
if (input_timespan[1])
|
||||
putchar('\n');
|
||||
@ -1696,18 +1714,65 @@ static int dump_timespan(int argc, char *argv[], void *userdata) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_timestamp_one(const char *p) {
|
||||
usec_t usec;
|
||||
char buf[FORMAT_TIMESTAMP_MAX];
|
||||
int r;
|
||||
|
||||
r = parse_timestamp(p, &usec);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse \"%s\": %m", p);
|
||||
parsing_hint(p, true, false, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
printf(" Original form: %s\n", p);
|
||||
printf("Normalized form: %s%s%s\n",
|
||||
ansi_highlight_blue(),
|
||||
format_timestamp(buf, sizeof buf, usec),
|
||||
ansi_normal());
|
||||
|
||||
if (!in_utc_timezone())
|
||||
printf(" (in UTC): %s\n", format_timestamp_utc(buf, sizeof buf, usec));
|
||||
|
||||
printf(" UNIX seconds: @%"PRI_USEC"%s%0*"PRI_USEC"\n",
|
||||
usec / USEC_PER_SEC,
|
||||
usec % USEC_PER_SEC ? "." : "",
|
||||
usec % USEC_PER_SEC ? 6 : 0,
|
||||
usec % USEC_PER_SEC);
|
||||
|
||||
printf(" From now: %s\n", format_timestamp_relative(buf, sizeof buf, usec));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_timestamp(int argc, char *argv[], void *userdata) {
|
||||
int ret = 0, r;
|
||||
char **p;
|
||||
|
||||
STRV_FOREACH(p, strv_skip(argv, 1)) {
|
||||
r = test_timestamp_one(*p);
|
||||
if (ret == 0 && r < 0)
|
||||
ret = r;
|
||||
|
||||
if (*(p + 1))
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_calendar_one(usec_t n, const char *p) {
|
||||
_cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int r;
|
||||
|
||||
r = calendar_spec_from_string(p, &spec);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse calendar specification '%s': %m", p);
|
||||
|
||||
r = calendar_spec_normalize(spec);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to normalize calendar specification '%s': %m", p);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse calendar specification '%s': %m", p);
|
||||
parsing_hint(p, false, true, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = calendar_spec_to_string(spec, &t);
|
||||
if (r < 0)
|
||||
@ -1891,8 +1956,9 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" unit-paths List load directories for units\n"
|
||||
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
|
||||
" verify FILE... Check unit files for correctness\n"
|
||||
" calendar SPEC... Validate repetitive calendar time events\n"
|
||||
" service-watchdogs [BOOL] Get/set service watchdog state\n"
|
||||
" calendar SPEC... Validate repetitive calendar time events\n"
|
||||
" timestamp TIMESTAMP... Validate a timestamp\n"
|
||||
" timespan SPAN... Validate a time span\n"
|
||||
" security [UNIT...] Analyze security of unit\n"
|
||||
"\nSee the %s for details.\n"
|
||||
@ -2093,8 +2159,9 @@ static int run(int argc, char *argv[]) {
|
||||
{ "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters },
|
||||
{ "verify", 2, VERB_ANY, 0, do_verify },
|
||||
{ "calendar", 2, VERB_ANY, 0, test_calendar },
|
||||
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
|
||||
{ "timestamp", 2, VERB_ANY, 0, test_timestamp },
|
||||
{ "timespan", 2, VERB_ANY, 0, dump_timespan },
|
||||
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
|
||||
{ "security", VERB_ANY, VERB_ANY, 0, do_security },
|
||||
{}
|
||||
};
|
||||
|
@ -575,7 +575,6 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
*/
|
||||
|
||||
assert(t);
|
||||
assert(usec);
|
||||
|
||||
if (t[0] == '@' && !with_tz)
|
||||
return parse_sec(t + 1, usec);
|
||||
@ -803,8 +802,8 @@ finish:
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
*usec = ret;
|
||||
|
||||
if (usec)
|
||||
*usec = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -861,7 +860,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
||||
if (munmap(shared, sizeof *shared) != 0)
|
||||
return negative_errno();
|
||||
|
||||
if (tmp.return_value == 0)
|
||||
if (tmp.return_value == 0 && usec)
|
||||
*usec = tmp.usec;
|
||||
|
||||
return tmp.return_value;
|
||||
@ -923,7 +922,6 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
bool something = false;
|
||||
|
||||
assert(t);
|
||||
assert(usec);
|
||||
assert(default_unit > 0);
|
||||
|
||||
p = t;
|
||||
@ -935,7 +933,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
if (*s != 0)
|
||||
return -EINVAL;
|
||||
|
||||
*usec = USEC_INFINITY;
|
||||
if (usec)
|
||||
*usec = USEC_INFINITY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1007,8 +1006,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
}
|
||||
}
|
||||
|
||||
*usec = r;
|
||||
|
||||
if (usec)
|
||||
*usec = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -862,7 +862,6 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
assert(spec);
|
||||
|
||||
c = new(CalendarSpec, 1);
|
||||
if (!c)
|
||||
@ -1076,7 +1075,8 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
|
||||
if (!calendar_spec_valid(c))
|
||||
return -EINVAL;
|
||||
|
||||
*spec = TAKE_PTR(c);
|
||||
if (spec)
|
||||
*spec = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user