envdir

reinhard@finalmedia.de Wed 16 Nov 2022 07:55:51 AM CET

Warum sollte ich das verwenden?

Du bist es ggf. gewohnt, eine config Datei mit Key/Value Paaren zum Setzen von (Umgebungsvariablen) zu verwenden. Ggf in diesem Stil:


  erbsen=1234
  linsen=5678
  bohnen="lecker schmecker"
  bohnen="immer noch lecker"
  lupinen=1234

Diese übergibst du dann an ein Programm und das setzt diese als Umgebungsvariablen.

Soweit so bekannt. Nun hat so eine config Datei aber u.a. prinzipiell zwei entscheidende Nachteile:

  1. Es ist nicht sichergestellt, dass der Variablenname nur einmal verwendet wird. Es ist die Mehrfachnennung im Dokument möglich. Dann stellt sich die Frage, ob die Erst- oder Letznennung gewinnt. Das kann zu undefinierten Zuständen führen.
  2. Du kannst einzelne Wertzuweisungen innerhalb der configdatei nicht vor Änderungen schützen (unberechtigt oder versehentlich). Wenn du z.B. realisieren willst, dass der Wert von erbsen zwar in der config setzbar sein soll, der Wert von linsen aber hingegen nur von berechtigten Personen überschrieben werden können darf, dann hast du in der gemeinsam geführten config datei dazu keine Möglichkeit, da jedes Paar gleichberechtigt ist und nur die gesamte Datei einer Rechteverwaltung unterliegt.
  3. Du weißt nicht wann welche Zeile geändert wurde, wenn derjenige das nicht selbst in der configdatei dokumentiert/kommentiert hat oder du eine externe Versionierung fährst.

envdir als Lösung

Das Konzept von envdir löst diese Probleme!

envdir hat diese Regeln:

Es ist daher mit Bordmitteln möglich, Zugriffsrechte der einzelnen Dateien individuell und feingranular zu verwalten. Du nutzt einfach chown, chmod, chattr.

Mit chattr +i dateiname kannst du eine Variable also auch im Dateisystem das immutable Flag setzen und es somit vor versehentlichem Überschreiben schützen, sogar vor root selbst.

Desweiteren ist natürlich jeder Dateiname im Ordner prinzipbedingt eindeutig und daher kann eine Variable auch im Ordner nicht mehrfach genannt werden.

Konsistente Sicherungen der Konfiguration erzeugt man durch einen tarball über alle envdir Dateien im Ordner. Damit werden dann auch die metadaten und Zugriffsrechte mitgesichert.

Am Zeitstempel jeder einzelnen Datei siehst du das Änderungsdatum. Du siehst also (im Gegensatz zu einer configdatei) auch direkt wann, welcher Variablenwert geändert wurde. Welchen Wert sie zuvor hatte entnimmst du deiner Sicherung. Tipp: Wenn die Konvention vereinbart wurde, dass die alten Einträge in der Datei einfach eine Zeile tiefer verschoben werden, also jeweils nur die gültigen neusten Werte in der ersten Zeile stehen, dann führst du in der Datei automatisch eine Historie! Denn es ist ja nur die erste Zeile für die Auswertung relevant. (BTW: Das wurde nicht umgekehrt gestaltet, weil es performanter ist, einen head auf 1024 chars zu fahren, als mit tail einen seek zum ende der Datei auszulösen und davon rückwärts auf vorkommen von newline zu parsen)

Und es gibt nun einen weiteren Vorteil: Es besteht bessere Automatisierungsmöglichkeit, da deine Scripte bei automatischer Anpassung einer Konfiguration nun keine config Dateien mehr parsen und verändern müssen (file locking probleme) sondern einfach mit atomaren Operationen (cp und mv) auf einzelnen Dateien selbst arbeiten können.

Zudem ist es nun möglich, mit symlinks zu arbeiten, um doppelte Datenhaltung zu vermeiden, Speicherplatz zu sparen oder damit Logik-Verkettungen zu realisieren.

Wie nutze ich es?

Hier ein Beispiel


  mkdir configdir
  cd configdir
  echo "1234" > erbsen
  echo "3456" > linsen
  chattr +i linsen
  echo "lecker schmecker" > bohnen
  ln -s erbsen lupinen
  cd ..

nun kannst du die Werte und Dateinamen ausgeben mittels


  ls -l configdir
  find configdir -exec head -v -n1 "{}" \;

oder bereits mittels envdir


  envdir configdir env

Zum Verständnis:

envdir liest im angegebenen Verzeichnis configdir von allen Dateien den Dateinamen und dort die erste Zeile. Es setzt daraus die Umgebungsvariablen für den nachfolgend genannten Prozess.

Der im Beispiel nachfolgend genannte Prozess ist "env". env ist ein Tool zum Ausgeben aller aktuellen Umgebungsvariablen.

Die Ausgabe obiger Befehlszeile umfasst also alle geerbten Umgebungsvariablen deiner Shell, ergänzt um die genannten Variablen aus der configdir.

Im Produktiveinsatz nutzt du also


  envdir configdir deinprogramm

und damit hat dein Programm oder Script automatisch das benötigte Environment

Krass. Haben will. Woher nehmen?

Deine Distribution bringt das i.d.R. bereits mit. Unter Ubuntu und Debian verwendest du


  apt-get install daemontools

Wer hat's erfunden?

Nicht die Schweizer. Es ist eine Entwicklung von djb, dem wir auch qmail, dnscurve, Maildir, ed25519, cdb, chacha20, tweetnacl, djbdns, syncookies, publicfile, ucspi-tcp zu verdanken haben.

Alternativen

Alternativ zu envdir kann auch die Reimplementierung "chpst" von G. Pape (Smarden) verwendet werden. diese steht für "change process state" und stelle die einzelfunktionen der daemontools wie setuidgid, envdir, pgrphack, ulimit dann stattdessen via argument/parameter zur Verfügung


  chpst -e configdir deinprogramm

Du müsstest das zuvor ebenso installieren. Sie befindet sich im Paket runit, welches dann die daemontools-run deinstallieren würde. beides geht nicht.


apt-get install runit

Ich empfehle aber derzeit die native "envdir" variante und auch die daemontools.

Wenn du dennoch die runit tools haben willst, baue sie aus den Quellen. Details dazu findest Du auch in meinem howto 0bc1e96d458b