summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd-analyze.xml12
-rw-r--r--man/systemd.time.xml7
-rw-r--r--src/analyze/analyze.c68
-rw-r--r--src/basic/calendarspec.h2
4 files changed, 88 insertions, 1 deletions
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index 956790c50c..876f96d559 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -125,6 +125,12 @@
<arg choice="plain">verify</arg>
<arg choice="opt" rep="repeat"><replaceable>FILES</replaceable></arg>
</cmdsynopsis>
+ <cmdsynopsis>
+ <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>
+ </cmdsynopsis>
</refsynopsisdiv>
<refsect1>
@@ -220,6 +226,12 @@
All units files present in the directories containing the command line arguments will
be used in preference to the other paths.</para>
+ <para><command>systemd-analyze calendar</command> will parse and normalize repetitive calendar time events, and
+ will calculate when they will elapse next. This takes the same input as the <varname>OnCalendar=</varname> setting
+ in <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>, following the
+ syntax described in
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
<para>If no command is passed, <command>systemd-analyze
time</command> is implied.</para>
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index a2fff2d101..6cb32f13b7 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -302,6 +302,10 @@ Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
+ <para>Use the <command>calendar</command> command of
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry> to validate
+ and normalize calendar time specifications for testing purposes. The tool also calculates when a specified
+ calendar event would elapse next.</para>
</refsect1>
<refsect1>
@@ -311,7 +315,8 @@ Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 913aa35016..5229b3a082 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -31,6 +31,7 @@
#include "bus-error.h"
#include "bus-unit-util.h"
#include "bus-util.h"
+#include "calendarspec.h"
#include "glob-util.h"
#include "hashmap.h"
#include "locale-util.h"
@@ -1395,6 +1396,70 @@ static int dump_syscall_filters(char** names) {
}
#endif
+static int test_calendar(char **args) {
+ int ret = 0, r;
+ char **p;
+ usec_t n;
+
+ if (strv_isempty(args)) {
+ log_error("Expected at least one calendar specification string as argument.");
+ return -EINVAL;
+ }
+
+ n = now(CLOCK_REALTIME);
+
+ STRV_FOREACH(p, args) {
+ _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL;
+ _cleanup_free_ char *t = NULL;
+ usec_t next;
+
+ r = calendar_spec_from_string(*p, &spec);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to parse calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ r = calendar_spec_normalize(spec);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to normalize calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ r = calendar_spec_to_string(spec, &t);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to fomat calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ if (!streq(t, *p))
+ printf(" Original form: %s\n", *p);
+
+ printf("Normalized form: %s\n", t);
+
+ r = calendar_spec_next_usec(spec, n, &next);
+ if (r == -ENOENT)
+ printf(" Next elapse: never\n");
+ else if (r < 0) {
+ ret = log_error_errno(r, "Failed to determine next elapse for '%s': %m", *p);
+ continue;
+ } else {
+ char buffer[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESTAMP_RELATIVE_MAX)];
+
+ printf(" Next elapse: %s\n", format_timestamp(buffer, sizeof(buffer), next));
+
+ if (!in_utc_timezone())
+ printf(" (in UTC): %s\n", format_timestamp_utc(buffer, sizeof(buffer), next));
+
+ printf(" From now: %s\n", format_timestamp_relative(buffer, sizeof(buffer), next));
+ }
+
+ if (*(p+1))
+ putchar('\n');
+ }
+
+ return ret;
+}
+
static void help(void) {
pager_open(arg_no_pager, false);
@@ -1429,6 +1494,7 @@ static void help(void) {
" dump Output state serialization of service manager\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"
, program_invocation_short_name);
/* When updating this list, including descriptions, apply
@@ -1618,6 +1684,8 @@ int main(int argc, char *argv[]) {
r = get_log_target(bus, argv+optind+1);
else if (streq(argv[optind], "syscall-filter"))
r = dump_syscall_filters(argv+optind+1);
+ else if (streq(argv[optind], "calendar"))
+ r = test_calendar(argv+optind+1);
else
log_error("Unknown operation '%s'.", argv[optind]);
}
diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h
index d2a19dd7dd..124f7f5880 100644
--- a/src/basic/calendarspec.h
+++ b/src/basic/calendarspec.h
@@ -61,3 +61,5 @@ int calendar_spec_to_string(const CalendarSpec *spec, char **p);
int calendar_spec_from_string(const char *p, CalendarSpec **spec);
int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(CalendarSpec*, calendar_spec_free);