Schlaflabor
Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:
Dieser Artikel ist größtenteils für alle Ubuntu-Versionen gültig.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
Dieser Artikel konkretisiert die Übersicht „Schlafender Rechner“[1] und ergänzt die Artikel Bereitschaft[2] und systemd-sleep[3] durch Vorstellung eines Skripts für die Shell[5][6] Bash, welches eine Zeitreihe für die Entladung des Akkus im Schlaf bequem (d.h. z.B. über Nacht) ermittelt.
Der Titel „Schlaflabor“ für dieses Skript soll andeuten, dass damit ein rudimentäres Schlaflabor für Rechner realisiert wird, er hat aber nichts zu tun mit einem Schlaflabor für Menschen.
Dieses Skript ist außerdem ein Anwendungsbeispiel für den Wecker in der Firmware des Rechners und wie dieser mit rtcwake[4] benutzt werden kann.
Das Skript verwendet Befehle an Komponenten wie UPower, systemd-sleep, rtcwake, grep, date und bc, die bei jedem Ubuntu-System üblicherweise zur Grundinstallation gehören und in den genannten Artikeln beschrieben sind.
Installation¶
Das Skript als Textdatei kopieren, an einer beliebigen Stelle ablegen, welche die Ausführung von Programmen erlaubt und die Datei ausführbar machen. Die Datei sollte einem normalen Benutzer und dessen primären Gruppe gehören, und als Dateirechte werden 755
vorgeschlagen.
Zur Deinstallation diese Datei einfach löschen.
Funktionsweise¶
Das Skript ermittelt den aktuellen Ladezustand des Akkus durch Abfrage beim Energiemanager UPower und den aktuellen Zeitpunkt mit date und gibt diese beiden Informationen aus. Danach geht das System für einen begrenzten Zeitraum in den Modus Bereitschaft[2].
Die vorstehende Grundfunktion wird gestartet, sobald der Ladezustand größer als „voll“ gemeldet wird und wird repetiert ausgeführt, solange als Ladezustand größer als „leer“ gemeldet wird. Als Kriterium für „voll“ und „leer“ werden die für UPower definierten Schwellen "Low" (Standard: 20%) und "Critical" (Standard: 5%) abgefragt, die in der Konfigurationsdatei von UPower änderbar sind. Alternativ sind die Schwellen auch als Umgebungsvariablen vorgebbar. Eine weitere Bedingung für die Abarbeitung der Schleife ist natürlich die laufende Entladung des Akkus, die ja gemessen werden soll; sobald diese Bedingung nicht mehr erfüllt ist, wird das Programm beendet.
Bei jedem Schleifendurchlauf wird außerdem mittels rtcwake[4] der Wecker des Rechners gestellt und mittels systemd-sleep[3] die Bereitschaft[2] angefordert. Hierbei wird ein Zähler der Aufwachvorgänge abgefragt um zu verhindern, dass mehrfach der Schlafzustand angefordert wird – leider funktioniert das nicht 100%-ig. Als Zeitpunkt für den Wecker wird der Wert aus der Umgebungsvariable Period
oder als Vorgabe 3600 Sekunden nach dem aktuellen Zeitpunkt verwendet.
Bedienung¶
Man startet das Programm[5] auf der Kommandozeile in einem Terminal[6]. Der Benutzer muss ein Administrator oder root sein. Da einige der im Skript verwendeten Befehle erweiterte Rechte[7] benötigen, prüft das Skript zuerst, ob es als root läuft und wenn dies nicht der Fall ist, startet es sich selber neu als root. Selbstverständlich wird dafür nötigenfalls ein Passwort abgefragt.
Das Programm erfragt vom Kernel aus der Datei /sys/power/mem_sleep die für Bereitschaft[1] möglichen Zustände und erfragt vom Bediener, welcher davon benutzt werden soll. Dieser wird eingestellt.
Das Programm prüft dann, ob die Startbedingungen erfüllt sind:
Der Ladezustand muss (im oben beschriebenen Sinne) „voll“ sein und der Betriebszustand muss „entladend“ sein. Wenn die Bedingungen nicht erfüllt sind, ergehen Aufforderungen an den Bediener, die Netzstromversorgung herzustellen bzw. zu trennen.
Wenn die Startbedingungen erfüllt sind, startet nach einer weiteren Eingabe die oben beschriebene Prüfschleife.
Zur Beendigung des Programms muss der Bediener
die Netzstromversorgung herstellen und ggf.
den Schlaf des Rechners durch kurzes Drücken des Einschalttasters abbrechen.
Zuletzt wird noch ein Wert für die Entladerate berechnet und ausgegeben. Die Berechnung ist nur richtig für Zeiträume unter 24 h.
Beispiellauf:
$ voll=90 leer=30 Period=900 /tmp/Schlaflabor [sudo] Passwort für kB: Schlaflabor – Zeitreihe Akku-Entladung im Schlaf aufnehmen. 1) s2idle 2) deep Welche Methode für Schlaf verwenden? 1 Method=s2idle, Period=900s, voll=90%, leer=30%. 09:15:32: Ladung 98%, fully-charged. Trenne die Netzstromversorgung! 09:15:37: Ladung 98%, discharging. Test startet nach Eingabetaste! 09:15:39: Ladung 97%, discharging. 09:30:43: Ladung 97%, discharging. 09:45:44: Ladung 96%, discharging. … 11:16:25: Ladung 91%, discharging. 11:16:50: Ladung 90%, charging. Für s2idle: dlnE/dt = 3.4 %/h
Das Skript¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #! /bin/bash -e # Copyright (c) 2025 kB @ UbuntuUsers.de # SPDX-License-Identifier: GPL-2.0-or-later test $UID = 0 || exec sudo env Period=${Period:=3600} voll=$voll leer=$leer $0 echo Schlaflabor – Zeitreihe Akku-Entladung im Schlaf aufnehmen. >&2 PS3='Welche Methode für Schlaf verwenden? ' select Method in $( sed 'y/[]/ /' /sys/power/mem_sleep ) do test -n "$Method" && break ; done test -z "$Method" || echo $Method > /sys/power/mem_sleep shopt -s lastpipe grep ^Percentage /etc/UPower/UPower.conf | while read do case $REPLY in (*Low*) : ${voll:=${REPLY#*=}} ;; (*Critical*) : ${leer:=${REPLY#*=}} esac done echo Method=$Method, Period=${Period}s, voll=$voll%, leer=$leer%. >&2 getBatState() { upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -e percentage -e state | while read Name Wert ; do printf -v ${Name%:} '%s' ${Wert%'%'} ; done date "+%T: Ladung $percentage%%, $state." } until getBatState (( voll < percentage )) && test $state = discharging # voll geladen und entladend do if (( voll < percentage )) then test $state = discharging || echo Trenne die Netzstromversorgung! else echo Warte auf über $voll%. ! test $state = discharging || echo Schliesse Netzstromversorgung an! fi sleep 5 done Minutes() { local NOW=$( date +%T ) echo $(( ( 1440 + 60 * 10#${NOW::2} + 10#${NOW:3:2} - ${1:-0} ) % 1440 )) } read -p 'Test startet nach Eingabetaste! ' N_last=-1 rtcwake -m disable >/dev/null while getBatState (( leer < percentage )) && test $state = discharging # noch geladen und entladend do read N </sys/power/suspend_stats/success if (( N_last < 0 )) then Rate=$percentage ; dt=$( Minutes ) fi if (( N_last < N )) then rtcwake -m no -s $Period && systemctl suspend -i && N_last=$N || true fi 1>/dev/null 2>/dev/null sleep 5 done bc <<< "scale = 1 ; ( $Rate - $percentage ) * 60 / $( Minutes $dt )" | read Rate echo "Für $Method: dlnE/dt = $Rate %/h" |