diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml index 3626e8bc51..f981848cb2 100644 --- a/man/systemd-timedated.service.xml +++ b/man/systemd-timedated.service.xml @@ -31,7 +31,7 @@ systemd-timedated is a system service that may be used as a mechanism to change the system clock and - timezone, as well as to enable/disable NTP time synchronization. + timezone, as well as to enable/disable network time synchronization. systemd-timedated is automatically activated on request and terminates itself when it is unused. @@ -46,25 +46,36 @@ - Environment + List of network time synchronization services - - - $SYSTEMD_TIMEDATED_NTP_SERVICES + systemd-timesyncd will look for files with a .list extension + in ntp-units.d/ directories. Each file is parsed as a list of unit names, one per + line. Empty lines and lines with comments (#) are ignored. Files are read from + /usr/lib/systemd/ntp-units.d/ and the corresponding directories under + /etc/, /run/, /usr/local/lib/. Files in + /etc/ override files with the same name in /run/, + /usr/local/lib/, and /usr/lib/. Files in + /run/ override files with the same name under /usr/. Packages + should install their configuration files in /usr/lib/ (distribution packages) or + /usr/local/lib/ (local installs). - Colon-separated list of unit names of NTP client services. - If not set, then - systemd-timesyncd.service8 - is used. See the entries of NTP related commands of - timedatectl1 - for details about this. + + <filename>ntp-units.d/</filename> entry for <command>systemd-timesyncd</command> + # /usr/lib/systemd/ntp-units.d/80-systemd-timesync.list +systemd-timesyncd.service + + - Example: - SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service - - - + If the environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES is set, + systemd-timesyncd will parse the contents of that variable as a colon-separated list + of unit names. When set, this variable overrides the file-based list described above. + + + An override that specifies that <command>chronyd</command> should be used if available + SYSTEMD_TIMEDATED_NTP_SERVICES=chronyd.service:systemd-timesyncd.service + + See Also diff --git a/man/timedatectl.xml b/man/timedatectl.xml index 262b9126e7..f797e0cd67 100644 --- a/man/timedatectl.xml +++ b/man/timedatectl.xml @@ -23,22 +23,25 @@ - timedatectl OPTIONS COMMAND + timedatectl + OPTIONS + COMMAND Description - timedatectl may be used to query and - change the system clock and its settings. + timedatectl may be used to query and change the system clock and its settings, + and enable or disable time synchronization services. Use systemd-firstboot1 to initialize the system time zone for mounted (but not booted) system images. - timedatectl may be used to show the current status of + timedatectl may be used to show the current status of time synchronization + services, for example systemd-timesyncd.service8. @@ -123,11 +126,8 @@ status - Show current settings of the system clock and RTC, - including whether network time synchronization through - systemd-timesyncd.service is active. Even if it is - inactive, a different service might still synchronize the clock. - If no command is specified, this is the implied default. + Show current settings of the system clock and RTC, including whether network time + synchronization is active. If no command is specified, this is the implied default. @@ -193,11 +193,11 @@ set-ntp [BOOL] - Takes a boolean argument. Controls whether network time synchronization is active - and enabled (if available). If the argument is true, this enables and starts the first existed - service listed in the environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES - of systemd-timedated.service. If the argument is false, then this disables and - stops the all services listed in $SYSTEMD_TIMEDATED_NTP_SERVICES. + Takes a boolean argument. Controls whether network time synchronization is active and + enabled (if available). If the argument is true, this enables and starts the first existing network + synchronization service. If the argument is false, then this disables and stops the known network + synchronization services. The way that the list of services is built is described below. + @@ -250,8 +250,7 @@ Exit status - On success, 0 is returned, a non-zero failure - code otherwise. + On success, 0 is returned, a non-zero failure code otherwise. diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index c602e036eb..96e74a758f 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -247,6 +247,11 @@ static int guess_type(const char **name, bool *is_usr, bool *is_collection, cons if (path_equal(n, "kernel/install.d")) ext = ".install"; + if (path_equal(n, "systemd/ntp-units.d")) { + coll = true; + ext = ".list"; + } + if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) { coll = true; ext = ".preset"; diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 57bbefc0c1..074ba3c079 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -15,7 +15,9 @@ #include "bus-error.h" #include "bus-util.h" #include "clock-util.h" +#include "conf-files.h" #include "def.h" +#include "fd-util.h" #include "fileio-label.h" #include "fileio.h" #include "fs-util.h" @@ -36,6 +38,8 @@ #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" +#define UNIT_LIST_DIRS (const char* const*) CONF_PATHS_STRV("systemd/ntp-units.d") + typedef struct UnitStatusInfo { char *name; char *load_state; @@ -117,20 +121,17 @@ static int context_add_ntp_service(Context *c, const char *s) { return 0; } -static int context_parse_ntp_services(Context *c) { +static int context_parse_ntp_services_from_environment(Context *c) { const char *env, *p; int r; assert(c); env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES"); - if (!env) { - r = context_add_ntp_service(c, "systemd-timesyncd.service"); - if (r < 0) - log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m"); - + if (!env) return 0; - } + + log_debug("Using list of ntp services from environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES."); for (p = env;;) { _cleanup_free_ char *word = NULL; @@ -150,7 +151,62 @@ static int context_parse_ntp_services(Context *c) { log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word); } - return 0; + return 1; +} + +static int context_parse_ntp_services_from_disk(Context *c) { + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + r = conf_files_list_strv(&files, ".list", NULL, CONF_FILES_FILTER_MASKED, UNIT_LIST_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate .list files: %m"); + + STRV_FOREACH(f, files) { + _cleanup_fclose_ FILE *file = NULL; + + log_debug("Reading file '%s'", *f); + + r = fopen_unlocked(*f, "re", &file); + if (r < 0) { + log_error_errno(r, "Failed to open %s, ignoring: %m", *f); + continue; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *word; + + r = read_line(file, LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read %s, ignoring: %m", *f); + continue; + } + if (r == 0) + break; + + word = strstrip(line); + if (isempty(word) || startswith("#", word)) + continue; + + r = context_add_ntp_service(c, word); + if (r < 0) + log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word); + } + } + + return 1; +} + +static int context_parse_ntp_services(Context *c) { + int r; + + r = context_parse_ntp_services_from_environment(c); + if (r != 0) + return r; + + return context_parse_ntp_services_from_disk(c); } static int context_ntp_service_is_active(Context *c) {