CLI-Adventskalender, Tag 13: cron

CLI-Adventskalender: cron

Avatar von Eric

Hinter dem 13. Türchen unseres CLI-Adventskalenders verbergen sich cron und seine Freunde.

Als ich noch ein Teenager war, hatte ich meine ersten ernsten Computerbücher in meinen Händen: Das Lama-Buch (Learning Pearl) und das Kamel-Buch (Programming Perl), beide von O’Reilly und geschrieben – unter anderem – von Larry Wall, dem Erfinder von Perl. In seiner Einleitung beschrieb er die drei großen Tugenden eines Perl-Programmierers: Faulheit, Ungeduld und Hybris. Ich wusste in diesem Moment, dass ich meinen Beruf gefunden hatte.

Bei allem Humor sind Faulheit, Ungeduld und Hybris die Grundpfeiler der Automatisierung. Ich einzelner Techie glaube ein Problem gut genug verstanden zu haben, dass ich es mit einem Skript lösen kann (kompletter Hybris, jeder Product Owner wird das bestätigen). Ich mache das, weil ich mir repetitive Arbeit sparen will (Faulheit) und weil das Skript das schneller macht als ich (Ungeduld).

Heute reden wir über eine Reihe von Befehlen die Dinge zu bestimmten Zeiten tun. Allen voran ist das cron.

cron

cron führt Befehle (und somit auch Skripte) in regelmäßigen Abständen aus. Es hat die übersichtlichste und intuitivste Syntax der Welt. crontab -e öffnet die crontab-Datei des jeweiligen Users, gefüllt mit Zeilen wie der folgenden.

0 8-22 * * * /home/eric/backups.sh

Führe dieses Skript jeden Tag (*), jeden Monat (*), jedes Jahr (*) von 8 Uhr bis 22 Uhr (8-22) jeweils zur vollen Stunde (0) aus. Es gibt viele Programme, die automatische Backups machen, aber ein Shellskript hat mir die größte Kontrolle gegeben (mehr dazu hinter einem späteren Adventstürchen). Ein kurzes Skript, eine Zeile im Cronjob und ich werde niemals mehr als eine Stunde Arbeit verlieren, wenn meine Festplatte in Rauch aufgehen sollte.

Das beste an cron ist das Einstellen und vergessen. Selbst wenn wir komplett die Kontrolle über unser Leben verlieren, unsere Cronjobs laufen weiter mit der stoischen Ruhe einer Maschine. Die große Herausforderung für Cronjobs ist es, gute Skripte zu finden, die tatsächlich einen Nutzen bringen. Ich habe mal ein paar Ideen gesammelt:

  • Backups. Nichts ist wertvoller als Lebenszeit. Investierte Arbeit gilt es zu schützen.
  • Updates. Nicht nur für den eigenen Computer, sondern auch für diverse andere Geräte die man so hat, die aber keine automatischen Updates fahren.
  • Billig einkaufen. Eine schnelle E-Mail, wenn Dinge, die wir haben wollen, für günstig auf eBay oder in diversen Webshops landen.
  • Effizientes Scraping. Wenn man hunderte von Websites regelmäßig auf Updates abklopfen will, spart ein cron-job viel Lebenszeit.
  • Statistische Datensammlung. Es gibt David Kriese nur einmal, aber manchmal möchten wir wirklich eine belastbare Datenbasis sammeln.
  • Aufräumen. Es sammeln sich an einschlägigen Orten allerhand Müll an.
  • Monitoring. Manchmal möchte man auf Dinge achten, für die es kein supergutes Tooling gibt. Ist die Telefonanlage gerade besetzt? Was sagen die Wettervorhersagen, muss ich heute meine Pflanzen reinholen, um sie vor Frost zu schützen? Und gibt es E-Mails, die ich in letzter Zeit geschickt habe, auf die ich aber noch keine Antwort bekommen habe?

at

Nicht alles muss (oder soll) regelmäßig passieren. Manchmal habe ich einen Einfall am Wochenende und möchte meinem Kollegen eine Nachricht schreiben … aber erst am Montagmorgen.

at 8am next Monday
sendmail -t < email_mit_guter_idee.txt

Den Input beenden mit STRG+D. Um at benutzen zu können, muss man vorher den at-Daemon einschalten.

sudo systemctl start atd
sudo systemctl enable atd

Die Syntax für die Zeiten ist relativ intuitiv:

at 11pm today
sudo shutdown now

… funktioniert genauso wie

at 3am Jul 1
sudo pacman -Syu

Mit atq bekommt man eine Übersicht der geschedulten Jobs und mit ihrer jeweiligen Nummer, mit der man sie beispielsweise wieder entfernen kann: atrm 2.

Ein besonderes Juwel ist das verwandte Tool batch, das Befehle ausführt, wenn die Auslastung des Systems unter einen bestimmten Wert fällt (lässt sich mit dem at-Daemon atd konfigurieren).

So kann z.B. ein Datenbanksynchronisierung passieren, wenn die Auslastung des Systems bei 20 Prozent liegt.

Ideen für at:

  • Resourcenintensiven Kram in die Off-Zeit legen. Ja, ich muss Updates installieren, aber bitte erst nach Feierabend.
  • E-Mails. Geburtstagsglückwünsche, Krankmeldungen („Wenn ich bis 9 Uhr nicht am Computer bin, geht es mir wahrscheinlich nicht gut genug zum Arbeiten“), Statusupdates („Um 17 Uhr schicke ich den aktuellen Stand.“), Reminder an andere Personen.
  • Dead Man’s Switch. Dramatische Lebensversicherungen aus Actionfilmen mal außen vor gelassen („Wenn sie mich umbringen, geht dieses Video an die Presse!“), kann es notwendig sein, dass bestimmte Dienste nicht ohne Aufsicht laufen dürfen. Der Dienst kann dann heruntergefahren oder Vertretungen informiert werden.
  • Social Media Posts, koordiniert auf allen Kanälen.
  • Reminder an einen selbst, auch wenn es da noch ein viel epischeres Tool gibt (siehe unten).


remind

Manche Leute ballern sich ihren Google Kalender voll mit Erinnerungen zu allen möglichen Themen. Andere mögen eine striktere Trennung zwischen verschiedenen Lebensbereichen und Kontexten. Wenn es ein Tool gibt, das komplexe Datumsregeln kann, dann ist es remind.

REM 10 SKIP WE MSG Monatliches Budget Meeting

Um Reminder zu bekommen, packt man den String oben in eine Datei wie reminders.rem und ruf remind auf: remind reminders.rem

Unser (fiktives) Budget-Meeting findet am 10. jedes Monats statt, es sei denn, der 10. fällt auf ein Wochenende, dann ist es der Montag danach. Oder vielleicht findet es stattdessen am vierten Mittwoch eines jeden Monats statt, außer es ist ein Feiertag, dann den Mittwoch drauf?

REM Wednesday SCHED _fourth() OMIT HOLIDAY SKIP FORWARD TO Wednesday IF OMITTED MSG "Meeting Day"

Unsere Feiertage müssen wir in der holidays.rem einpflegen, in einem Format wie …

REM 2023 Oct 3 HOLIDAY "Tag der deutschen Einheit"

Jetzt sind Texterinnerungen zwar ganz nett und vielleicht etwas altmodisch, aber um echte Probleme zu lösen, brauchen wir etwas mehr Funktionalität. Glücklicherweise geht

REM 2023 Dec 25 RUN skript_zum_schicken_von_weihnachtskarten.sh

remind manuell auszuführen ist was für Leute, die alle zehn Minuten ihre E-Mails checken. Stattdessen möchte man vielleicht einen cronjob aufsetzen:

crontab -e
0 8 * * * /usr/bin/remind /home/eric/reminders.rem

Die nächste denkbare Frage die sich stellt ist, wie man remind mit dem eigenen Kalender syncen kann.

rem2ics reminders.rem > termine.ics

Dieses Tool kommt direkt von remind. Es kommt ein iCalendar-Format heraus, das von jeder modernen Kalendersoftware unterstützt wird. Das lässt sich natürlich auch wieder automatisieren und per APIs in die entsprechenden Kalender einpflegen.

Warum benutzen wir eigentlich cron, wenn remind mehr Flexbilität mit Scheduling liefert? Weil cron in den meisten Fällen reicht und die meisten Anwendungsfälle keine komplexe Datumsengine brauchen. Meiner Ansicht nacht geht cron ohne remind, aber remind nicht ohne cron oder eine Integration in eine Statusbar oder ein ähnliches Programm.

Als Output können dann alle gängigen Kanäle genutzt werden. Messenger-APIs, Slack-Bots, Services für Push-Notifications (ein selbst gehostetes ntfy.sh vielleicht?) und natürlich E-Mails und diverse GUIs.

Ideen für remind:

  • Reminder: Es steht im Namen. Mit ein bißchen Geduld ist es mit Abstand die beste Engine, um an Sachen erinnert zu werden.
  • Komplexes scheduling: remind kennt Mondphasen. Vielleicht möchte man sein Teleskop ausrichten? Vielleicht muss man Medikamente genau alle fünf Tage nehmen?
  • Ewige Kalender ohne Vendor-lock. Moderne Ökosysteme helfen gerne mit allen Bereichen des Lebens und machen es damit umso schwieriger, sie zu verlassen. Textdateien und Git-Repositories geben Unabhängigkeit.

watcher

Manchmal möchte man Live-Updates. Vielleicht sollen die Tests bei Praktiken wie TDD und/oder komplizierten Refactorings immer neu ausgeführt werden.

inotifywait -m -r -e modify . | while read -r EVENT
do
  rspec
done

Vielleicht möchte man auch einen Befehl alle zwei Sekunden ausführen, um einen Live-Update über den Inhalts eines Verzeichnisses zu bekommen:

watch -n 2 ls /home/eric/Downloads

Auch sehr gut als Alternative, um Refresh auf dem Browser zu drücken.

watch -n 5 curl https://example.com/status.json | jq '.available'

Ideen hier sind:

  • Tests ausführen: Runner dieser Art sind das Rückgrat von TDD.
  • Builds triggern: Im linken Fenster LaTeX-Code schreiben, im Hintergrund mit inotifywait bauen, im rechten Fenster die gebaute PDF betrachten. #ThisIsTheWay
  • Eigenes REPL: Skript nach jeder Veränderung Ausführen und Output betrachten.
  • Kommandozeilen-Tabellenkalkulation. Siehe Artikel vom 10.12.

Computer sind unsere Freunde

Das moderne Leben ist hektisch und kompliziert. Unsere Generation muss mit mehr Informationen umgehen als je eine vor uns. Je besser wir Dinge automatisieren, desto weniger müssen wir uns selber kümmern, desto freier ist unser Kopf, desto besser bekommen wir unser Leben unter Kontrolle.

Shell-Weisheit des Tages
Serverless. Desktopless.

Diese Shellweisheiten fangen an, aufeinander aufzubauen. Die Shell ist remote. Ein gleich aussehender Prompt kann in einem Roomba in Tokyo sein, genau so gut wie in einem Supercomputer in der Schweiz. Hunderte Skripte unterstützen schon heute unser Leben. Seit Beginn der Smartphones sind wir alle ständig mit dem Internet verbunden und haben einen Satz Programme, die Web-Anfragen machen und Daten für uns vor- und zurückschaufeln.

Es ist aber egal, wo sie laufen.

Genau so wie früher ein Terminal an einem Mainframe hing, so kann jedes Gerät heute entweder selbst rechnen oder eine reine Darstellungsschicht bieten. Für den Nutzer meistens nur indirekt wahrnehmbar, es sei denn, der Empfang wird schlecht. Das einfachste Beispiel hier sind Web-Frontends (Microsoft Office ist inzwischen eine Browser-App), aber es geht bis hin zu gestreamten, hochauflösenden Spielen für alle, die sich teure Grafikkarten lieber mieten wollen statt sie zu kaufen.

Wenn wir an die wichtige Software in unserem Leben denken – nicht nur die Programme die wir zum Arbeiten verwenden, sondern auch die Chatprogramme, mit denen wir mit unserer Familie in Kontakt bleiben und die Taskmanager mit denen wir anfangen, uns selber zu programmieren, unsere Kalender, unsere eBook-Reader – dann können diese Programme inzwischen überall laufen. Noch extremer ist das für all die Automatisierungen, die wirklich im Hintergrund laufen können. Smarthome-Skripte, die nach Sonnenuntergang die Lichter anschalten? Crawler, die auf Angebote in unseren Lieblingsshops lauern?

Inzwischen gibt es das Tooling, Dinge transparent und dynamisch von Server zu Server zu verlagern. Ich kann einen Kubernetes-Cluster aus parallel geschalteten Handies betreiben. Ich kann meinen Docker-Container in meinem Fernseher deployen.

Warum ist das eine Shellweisheit? Weil Shellprogramme keine grafische Oberfläche haben und deshalb um einiges portabler, leichtgewichtiger und resourcenschonender sind. Ich habe mal als Challenge versucht, einen Atari 1040ST zu dem Punkt zu bringen, an dem ich damit moderne Softwareentwicklung machen konnte … und bin an der Verschlüsselung als Bottleneck für Performance gescheitert. Ich kann also nach einem Hardwareausfall notfalls durch den kompletten Stapel meiner alten Laptops durchgehen und ungehindert weiterarbeiten. Nur das Docker-Setup der Software an der ich mitentwickle muss ich irgendwann in die Cloud verlagern.

Meine Schlussfolgerung und Empfehlung ist dieselbe wie immer: Je besser es euch gelingt euer Leben in Code zu gießen, je besser es euch gelingt diesen Code von spezifischen Maschinen loszulösen, desto mehr können Computer euch in eurem Leben unterstützen. Wenn euer Satz Skripte und Konfiguration mit wenigen Befehlen deploybar ist, wird spezifische Hardware irgendwann irrelevant werden.

Avatar von Eric

Kommentare

Eine Antwort zu „CLI-Adventskalender: cron“

  1. […] cron-Artikel dieses Adventskalenders zeigt inotifywait, womit sich Feedback-Loops extrem verkürzen lassen. Ich benutze […]

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.