Files
systemd/test/units/TEST-30-ONCLOCKCHANGE.sh
T
Valentin David 0dc39dffbd Use paths specified from environment variables for /etc configuration files
Some configuration files that need updates are directly under in /etc. To
update them atomically, we need write access to /etc. For Ubuntu Core this is
an issue as /etc is not writable. Only a selection of subdirectories can be
writable. The general solution is symlinks or bind mounts to writable places.
But for atomic writes in /etc, that does not work. So Ubuntu has had a patch
for that that did not age well.

Instead we would like to introduce some environment variables for alternate
paths.

 * SYSTEMD_ETC_HOSTNAME: /etc/hostname
 * SYSTEMD_ETC_MACHINE_INFO: /etc/machine-info
 * SYSTEMD_ETC_LOCALTIME: /etc/localtime
 * SYSTEMD_ETC_LOCALE_CONF: /etc/locale.conf
 * SYSTEMD_ETC_VCONSOLE_CONF: /etc/vconsole.conf
 * SYSTEMD_ETC_ADJTIME: /etc/adjtime

While it is for now expected that there is a symlink from the standard, we
still try to read them from that alternate path. This is important for
`/etc/localtime`, which is a symlink, so we cannot have an indirect symlink or
bind mount for it.

Since machine-id is typically written only once and not updated. This commit
does not cover it. An initrd can properly create it and bind mount it.
2025-06-23 15:32:11 +02:00

67 lines
1.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
systemd-analyze log-level debug
systemctl disable --now systemd-timesyncd.service
timedatectl set-timezone Europe/Berlin
# A future timestamp needs to be used, otherwise 'timedatectl set-time' fails
# if a timestamp older than the TIME_EPOCH is specified.
current_time=$(date)
future_time=$(date -d "$current_time + 1 year" +"%Y-%m-%d %H:%M:%S")
timedatectl set-time "$future_time"
systemd-run --on-timezone-change touch /tmp/timezone-changed
systemd-run --on-clock-change touch /tmp/clock-changed
test ! -f /tmp/timezone-changed
test ! -f /tmp/clock-changed
timedatectl set-timezone Europe/Kyiv
while test ! -f /tmp/timezone-changed ; do sleep .5 ; done
future_time=$(date -d "$current_time + 1 year + 1 month" +"%Y-%m-%d %H:%M:%S")
timedatectl set-time "$future_time"
while test ! -f /tmp/clock-changed ; do sleep .5 ; done
mkdir -p /etc/alternate-path
rm -f /etc/alternate-path/localtime
cat <<EOF >/run/systemd/system.conf
[Manager]
ManagerEnvironment=SYSTEMD_ETC_LOCALTIME=/etc/alternate-path/localtime
EOF
mkdir -p /run/systemd/system/systemd-timedated.service.d
cat >/run/systemd/system/systemd-timedated.service.d/override.conf <<EOF
[Service]
Environment=SYSTEMD_ETC_LOCALTIME=/run/alternate-path/mylocaltime
Environment=SYSTEMD_ETC_ADJTIME=/run/alternate-path/myadjtime
EOF
systemctl daemon-reload
systemd-run --on-timezone-change touch /tmp/timezone-changed-alternate-path-1
timedatectl set-timezone Europe/Berlin
while test ! -f /tmp/timezone-changed-alternate-path-1 ; do sleep .5 ; done
systemd-run --on-timezone-change touch /tmp/timezone-changed-alternate-path-2
timedatectl set-timezone Europe/Kyiv
while test ! -f /tmp/timezone-changed-alternate-path-2 ; do sleep .5 ; done
rm /run/systemd/system.conf /run/systemd/system/systemd-timedated.service.d/override.conf
systemctl daemon-reload
systemd-analyze log-level info
touch /testok