Restic – initiales Backup geschafft

Etwas über 10 Tage später war es dann soweit …

Dieser eine Server benötigte besonders lange für das initiale Restic-Backup – der Grund ist mir aktuell noch unklar. Das Remote-Repository wird per SFTP auf Gigabit-Link angesprochen; andere Server waren mit Repositories im Bereich 3 TiB und ähnlich vielen Files deutlich schneller.

Linux-Shell: Prozess starten sobald ein anderer beendet ist

Ich hatte zuletzt das Problem zu lösen, dass ich einen neuen Prozess auf der Linux-Shell starten wollte, sobald ein anderer, bereits laufender Prozess beendet wurde.

Hintergrund: beide Prozesse verarbeiten Videos mit ffmpeg und haben eine Laufzeit in der Größenordnung von Tagen. Hier macht es aufgrund des Ressourcenverbrauchs wenig Sinn, beide parallel laufen zu lassen.

Hätte ich vorher gewusst, dass beide nacheinander arbeiten sollen, wäre die Lösung mit

% php encode_videos.php directory1 && \
  php encode_videos.php directory2

sehr einfach gewesen.

Der erste Prozess lief nun aber bereits. Wie startet man also den zweiten Prozess sobald der erste beendet ist?

Die Lösung heißt tail(1):

% tail -f --pid=$(pidof php) /dev/null && \
  php encode_videos.php directory2

tail hat eine Option --pid, welche die Angabe einer PID erfordert. Sobald der betreffenden Prozess beendet wird, beendet sich tail ebenfalls (mit Status-Code 0), sodass der zweite Teil des Kommandos ausgeführt wird.

(Das tail auf macOS hat diese Option nicht, das Feature ist vermutlich eine GNU-Eigenart :-))

find, xargs, sleep

Gegeben

  • Linux-Server
  • RAID-1 aus zwei SATA-Platten (spinning rust)
  • ext4 Filesystem
  • ein Directory-Tree mit vielen Millionen Files + Sub-Directories

Aufgabe

In diesem Tree rekursiv leere Sub-Directories finden und diese löschen.

Bonusaufgabe

Das Ganze soll auf einem Produktionsserver laufen, die I/O muss niedrig gehalten werden, um die eigentlichen Aufgaben des Servers nicht zu beeinträchtigen.

Hinweis

Es handelt sich um etwa 1 Million leere Directories, welche zum Schluss gelöscht werden müssen.

Ansatz 1

find + xargs

find . -type d -empty -print0 | xargs -0 rmdir -v

Löst die Aufgabe, allerdings geht die die Average Queue Depth für die Platten hier nach kürzester durch die Decke und der Maschine kann mit ihrem Storage nicht mehr viel anfangen. Die Bonusaufgabe wird damit zumindest nicht bestanden.

Ansatz 2

find + xargs + sleep: Nach dem Löschen von n Directories kurz warten, damit die Platten genügend Zeit haben, um ihre Aufgaben abzuarbeiten.

find . -type d -empty -print0 | \
xargs -0 -n 100 bash -c '{ rmdir "$@" ; sleep 3 ; }'

Löst Aufgabe + Bonus zufriedenstellend und reicht mir für die einmalige Anwendung.

HTML-Directory-Listing mit tree

Die meisten Webserver bringen eine Funktion mit, welche Directory-Listings dynamisch erzeugen und als HTML ausgeben kann.

Manchmal ist es aber nicht möglich, das eingebaute Feature des Webservers zu nutzen und man benötigt einen anderen Weg, um schnell eine Liste der Dateien in HTML auszugeben.

tree hilft in diesem Fall weiter – es hat nämlich neben der Ausgabe eines Plain-Text-Directory-Listings auch die Möglichkeit, das Listing als HTML zu rendern.

tree ist bei allen wichtigen Linux-Distribution verfügbar, auf macOS kann man es einfach per Homebrew installieren.

Ich habe es benutzt, um eine Liste von Bildern in einem Verzeichnis zu erstellen:

tree -H '.' -L 1 --noreport --charset utf-8 > index.html

Alle Optionen sind in der Manpage von tree ausführlich erklärt. Obiger Befehl erzeugt folgende HTML-Ausgabe:

GNU Stow: Dotfiles bequem managen

GNU Stow löste zuletzt bei mir eine selbstgebaute zentrale Verwaltung von Konfigurations-Dateien ab. Etwas Kontext: Ich habe für viele Programme Konfigurationsdateien in meinem Home-Directory zu liegen. Diese Dateien – meist einfach Dotfiles genannt – möchte ich auf mehreren Rechnern synchron halten. Dies ermöglicht es, dass sich die damit konfigurierten Programme wie tmux, Vim oder auch Git überall gleich und vorhersagbar verhalten. Weitere Kandidaten neben reinen Konfigurationsdateien sind z. B. Shell-Skripte für die tägliche Arbeit.

Die erste Idee, die man haben würde: einfach ein Git-Repository[1] erstellen, in dem man die Konfigurations-Details verwaltet. Das unmittelbar auftauchende Problem: Man möchte/kann/soll kein VCS-Repository im Home-Verzeichnis haben, da dies eine ganze Menge Probleme mit sich bringt und schlicht nicht praktikabel ist.

Der nächste Schritt ist dann, alle diese Dateien in einem Unterverzeichnis zu sammeln und dieses mit einem VCS managen. Das Installieren der Dateien ins Home-Verzeichnis kann man dann mit einem simplen Shell-Skript oder auch mit einem Makefile erledigen. Diese Variante habe ich jetzt jahrelang erfolgreich im Einsatz gehabt. Sobald ich ein neues Dotfile benötigte, erstellte ich dieses zusammen mit einem Make-Target in meinem dotfiles-Verzeichnis. Der simple Aufruf von make kopierte die Datei dann ins Homeverzeichnis (bzw. erstellte dort einen Symlink).

Vor ein paar Tagen scrollte dann dieser Tweet an mir vorbei:

Relearning GNU stow to apply to dotfiles, as one does when @fink_ says to. (E.g. http://brandon.invergo.net/news/2012-05-26-using-gnu-stow-to-manage-your-dotfiles.html …) — @jpmens

Das klang interessant und wurde noch besser als ich den verlinkten Blogpost las. GNU Stow ermöglicht es auf einfachste Weise die Dotfiles zentral zu verwalten und mit simplen Befehlen die gewünschten Dateien ins Home-Verzeichnis zu linken. Die Einsparung gegenüber dem vorhandenen Makefile sieht im ersten Moment nicht allzu groß aus, aber wenn ich mir das Schreiben von Make-Targets sparen kann, dann kostet das zum Einen weniger Zeit und eliminiert zum Anderen natürlich mögliche Fehlerquellen.

Ich musste in meinem dotfiles-Verzeichnis nur ein paar Sachen umbenennen bzw. verschieben und war innerhalb kürzester Zeit in der Lage meine Dotfiles mit Stow ins Home-Directory zu befördern.

Der im Tweet verlinkte Blog-Artikel erklärt sehr gut und abschließend, wie man seine Dotfiles Stow-kompatibel organisiert.

Bonus: Arbeitet man mit mehreren User-Accounts auf einer Maschine, reicht ein zentrales Dotfiles-Directory, aus welchem man dann mit der --target-Option von Stow Symlinks auf die Config-Files in die verschiedenen Home-Directories platziert.

[1] Jede andere Versionsverwaltungs-Software ist ebenfalls geeignet.