port the sleep and suspend section
The original ran unconditionally, so a laptop that went through it stopped suspending — a hot bag and a flat battery. It is a server concern: dev is skipped with the reason printed, like the ballast. Four things wrong with it beyond the role: HandleLidSwitchDocked was never set. A laptop used as a homelab server, docked and closed, still suspends — which is the exact machine this setting exists for. Added. RuntimeDirectorySize=10% was set alongside the sleep handlers. It is the size of /run, has nothing to do with sleeping, and 10% is systemd's own default, so the line never did anything. Dropped. systemd-logind was restarted on every pass whether or not anything changed, disturbing live sessions for nothing. The step now checks first and does not reach the restart when the machine is already configured. (The platform's own scripts/setup-old/setup.sh already had this guard; the machine script did not.) The settings were sed'd into logind.conf in place. They are a drop-in at /etc/systemd/logind.conf.d/99-machine-setup.conf now, so what this script set is one file that can be read or removed on its own. Current state is printed before anything is asked — whether the targets are masked, and what the lid, idle and power-key handlers actually do. logind_effective reads the main file and every drop-in and takes the last match, since a drop-in overrides logind.conf; reading only the main file reports a configured machine as unconfigured. The power-button consequence is stated rather than left to be discovered: after this, pressing power physically does nothing and a clean shutdown is `sudo poweroff`. WSL has no logind and cannot suspend, and says so. Verified both roles on this host, which the old script had already configured — correctly reports the targets masked and the handlers set, and correctly reports itself not fully configured because HandleLidSwitchDocked is missing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -355,6 +355,89 @@ EOF
|
||||
sysctl -q -w "fs.inotify.max_user_instances=${INOTIFY_INSTANCES}"
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Sleep and suspend
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# A server that suspends is a server that is off. The machine stops answering,
|
||||
# and on a box with no keyboard attached there is nothing to wake it — which is
|
||||
# the whole failure: it looks like a crash, and the only fix is physical.
|
||||
#
|
||||
# Two independent mechanisms, and both have to be dealt with:
|
||||
#
|
||||
# the sleep targets what suspend/hibernate hang off. Masking them means
|
||||
# nothing can trigger a sleep, including a stray
|
||||
# `systemctl suspend`
|
||||
# logind's handlers what closing a lid, pressing the power button or going
|
||||
# idle DO. These are what a desktop image sets, and they
|
||||
# act before anything reaches a target
|
||||
#
|
||||
# Written as a drop-in rather than by editing logind.conf in place, so what this
|
||||
# script set is one file that can be read or deleted on its own.
|
||||
|
||||
SLEEP_TARGETS=(sleep.target suspend.target hibernate.target hybrid-sleep.target)
|
||||
LOGIND_DROPIN=/etc/systemd/logind.conf.d/99-machine-setup.conf
|
||||
|
||||
# The value actually in force for a logind setting, or empty for the default.
|
||||
# Drop-ins override the main file and later ones override earlier, so the last
|
||||
# match wins — reading only logind.conf would miss a setting made by a drop-in
|
||||
# and report the machine as unconfigured when it is not.
|
||||
logind_effective() {
|
||||
local key="$1"
|
||||
{
|
||||
[[ -r /etc/systemd/logind.conf ]] && grep -hE "^${key}=" /etc/systemd/logind.conf
|
||||
for f in /etc/systemd/logind.conf.d/*.conf; do
|
||||
[[ -r "$f" ]] && grep -hE "^${key}=" "$f"
|
||||
done
|
||||
} 2>/dev/null | tail -1 | cut -d= -f2-
|
||||
}
|
||||
|
||||
sleep_targets_masked() {
|
||||
local t
|
||||
for t in "${SLEEP_TARGETS[@]}"; do
|
||||
[[ "$(systemctl is-enabled "$t" 2>/dev/null)" == "masked" ]] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
# What the machine should be set to. RuntimeDirectorySize is deliberately NOT
|
||||
# here: the original set it to 10% alongside these, which is both unrelated to
|
||||
# sleeping — it is the size of /run — and systemd's own default, so the line
|
||||
# never did anything.
|
||||
logind_wanted() {
|
||||
cat <<'EOF'
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchExternalPower=ignore
|
||||
HandleLidSwitchDocked=ignore
|
||||
HandlePowerKey=ignore
|
||||
IdleAction=none
|
||||
EOF
|
||||
}
|
||||
|
||||
# Is every wanted setting already in force?
|
||||
logind_is_configured() {
|
||||
local line key value
|
||||
while IFS= read -r line; do
|
||||
key="${line%%=*}"
|
||||
value="${line#*=}"
|
||||
[[ "$(logind_effective "$key")" == "$value" ]] || return 1
|
||||
done < <(logind_wanted)
|
||||
}
|
||||
|
||||
disable_sleep() {
|
||||
systemctl mask "${SLEEP_TARGETS[@]}" >/dev/null 2>&1
|
||||
|
||||
mkdir -p "$(dirname "$LOGIND_DROPIN")"
|
||||
{
|
||||
echo "# Written by machine-setup: this machine is a server and must not sleep."
|
||||
echo "[Login]"
|
||||
logind_wanted
|
||||
} >"$LOGIND_DROPIN"
|
||||
|
||||
# Only restart when something actually changed — a needless restart of logind
|
||||
# disturbs live sessions, and this step runs on every pass.
|
||||
systemctl restart systemd-logind
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Timezone
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user