Ich wollte ein Tageszitat über jedem neuen Terminal. Daran ist technisch nichts Interessantes. Mit einem Einzeiler im Shell-Hook, curl und einer öffentlichen Zitate-API ist das in 30 Sekunden erledigt. Genau das habe ich gemacht, und innerhalb einer Woche hatte ich drei Probleme. Manchmal hat das Öffnen eines Terminals zwei Sekunden geblockt, weil die API langsam war. Im Flugzeug hatte ich gar kein Zitat. Mein Einzeiler hat die unterschiedlichen Shell-Inits über meine Maschinen hinweg nicht überlebt. Also habe ich herald gebaut – die gleiche Idee, langweilig richtig gemacht: ein kleiner Daemon, ein CLI, ein systemd-Timer und eine Cache-Datei. Keiner dieser Bausteine ist clever. Die interessante Arbeit lag darin, zu entscheiden, welche Bausteine es überhaupt geben soll.
Der naive Shell-Hook macht bei jedem Terminalstart einen Netzwerk-Request. Dutzende Anfragen pro Tag für eine Information, die sich einmal ändert. Die API ist kostenlos und der Betreiber großzügig, aber das ist unhöflich. Der Request kann auch fehlschlagen oder langsam sein: entweder die Shell wartet, was schlecht ist, oder du legst es in den Hintergrund und das Zitat erscheint mitten in deinem Prompt, was schlimmer ist. Und das Zitat soll den ganzen Tag über in jedem Terminal dasselbe sein. Wenn ich drei Terminals öffne und drei verschiedene Zitate sehe, stimmt das Erlebnis nicht. Das Zitat soll eine kleine, ruhige Konstante sein.
Den Abruf vom Display zu trennen, löst alle drei Probleme. Der Abruf läuft per Timer im Hintergrund in eine Cache-Datei. Die Anzeige liest die Cache-Datei, das ist schnell, offline-tauglich und über Shells hinweg konsistent.
Ein systemd-Timer (herald-refresh.timer) läuft standardmäßig alle drei Stunden und schreibt ein JSON-Objekt in /var/cache/herald/today.json. Der Abruf trifft zenquotes.io mit einem 1,5-Sekunden-Timeout. Schlägt er fehl, fällt herald auf einen lokalen Pool von rund 30 kuratierten Zitaten zurück, die mit dem Paket ausgeliefert werden – das Tool funktioniert also immer offline. Die Terminal-Begrüßung liest den Cache. Das Login-MOTD liest den Cache. Keiner der beiden macht Netzwerk-Arbeit. Beide sind schnell, beide sind konsistent, beide sind deterministisch.
Die Refresh-Frequenz ist in Stunden konfigurierbar. sudo herald set-refresh 24 für einmal pro Tag, sudo herald set-refresh 168 für einmal pro Woche, sudo herald set-refresh 0, um den Online-Abruf komplett zu deaktivieren und nur den lokalen Pool zu rotieren. sudo herald refresh erzwingt einen Abruf. Der Timer ist ein einzeiliges Override der Unit-Datei, ohne komplizierte Scheduling-Logik.
Ein Zitat über jeder interaktiven Shell auszugeben klingt wie dasselbe Problem wie das Zitat beim SSH-Login auszugeben. Ist es nicht. Interaktive Shells unter Ubuntu sourcen /etc/profile.d/ über den Login-Pfad, aber ein neuer GUI-Terminal-Tab ist oft keine Login-Shell, also wird /etc/profile.d/ nicht gesourct. Ich musste einen kleinen Marker-Block in die ~/.bashrc der Nutzerin einfügen, der den profile.d-Snippet explizit sourct. Dieser Block gehört herald, und sudo herald terminal off entfernt ihn wieder.
SSH-, Konsolen- und Display-Manager-Logins nutzen das update-motd-System – also ein Skript in /etc/update-motd.d/. Das setzt das Paket update-motd voraus, das auf Debian und Ubuntu nur als Suggests, nicht als Recommends markiert ist. Reine Laptop-Nutzer ziehen es daher standardmäßig nicht mit. Das CLI warnt zur Laufzeit, wenn man MOTD auf einem System aktiviert, das es nicht hat.
Beide Oberflächen sind standardmäßig aus. sudo herald terminal on und sudo herald motd on schalten sie unabhängig voneinander um. Diese Unabhängigkeit ist wichtig: Ich will das Zitat in jedem neuen Terminal, aber nicht in meinem SSH-Banner. Jemand anderes will vielleicht genau umgekehrt.
Herald lädt von einem Drittanbieter-Dienst. Die Inhalte kontrolliere ich nicht. Wenn zenquotes ein Zitat ausliefert, das ich geschmacklos finde, taucht es auf irgendjemandes Terminal auf, und das README ist da deutlich. Mit set-refresh 0 lässt sich der Online-Abruf abschalten und nur der lokale Pool nutzen.
Der Online-Abruf ist standardmäßig an, mit klarem Opt-out, statt umgekehrt. Der Offline-Pool allein wird schnell schal: 30 rotierende Zitate fühlen sich nach einer Woche vertraut an, der Online-Refresh sorgt für Frische. Der Kompromiss ist, dass die Installation laut darüber ist, was sie tut, und das Abschalten des Netzwerks genau ein Befehl bleibt.
Was ich immer wieder feststelle, ist, wie viel Komplexität in kleinen Utilities steckt, sobald man ihre nicht-offensichtlichen Fehlermodi ernst nimmt. Die erste Version von herald war ein 20-zeiliges Shell-Skript. Die ausgelieferte Version ist ein Daemon, ein Timer, ein Cache, zwei Integrationspfade, ein Fallback-Pool und ein CLI. Nichts davon ist Overkill. Die Komplexität gibt es, weil Shell-Startup zählt, weil Netzwerkfehler passieren, weil Login-Banner und Shell-Begrüßungen unterschiedliches Klempnerwerk haben, und weil ein Feature, das auf meinem Laptop läuft, aber auf jemand anderes Headless-Server bricht, eigentlich kein Feature ist.
In herald steckt kein neuer Algorithmus. Die interessante Arbeit war die Entscheidung, wann abzurufen, wann anzuzeigen, was zu tun ist, wenn das Netzwerk ausfällt, und wie man zwei Anzeigeflächen im Gleichschritt hält. Langweilige Probleme, gut gelöst, sind der Hauptteil jeder Software, die auf den Maschinen anderer Leute lebt. Wenn dein Terminal dich morgens mit einem Knuth-Zitat begrüßt und du nie darüber nachdenken musst, macht herald seinen Job.
