Mit wachsender Anzahl potentieller Arbeitscomputer in verschiedenen (Uni) Systemen und auf meinen eigenen Computern, wurde das aktuell halten meiner Konfigurationsdaten auf allen Systemen langsam etwas aufwendig. Die Lösung für dieses Problem wurde schon von diversen Personen vor mir genutzt, dennoch hat mein Ansatz einige Besonderheiten, welche ich hier ausführen möchte.
Die Grundidee ist einfach, git als Werkzeug der Synchronisierung nutzen und alle Dateien mittels ln als Links an den erwarteten Stellen verlinken.
Der entscheidende Punkt ist nun, wie man die Links möglichst bequem anlegt und dies auf beliebig vielen Systemen installieren kann.
- In einem Skript einfach X Zeilen der Form ln -s $quelle $ziel nutzen, unbequem zu pflegen und unflexibel.
- Mit einer Schleife ln für jede Datei in einem Ordner aufrufen, bequem, aber unflexibel
- Listen als Quelle für ln nutzen, etwas aufwand in der Pflege, dafür aber sehr flexibel
Meine Lösung gehört offensichtlich in die 3. Kategorie, dabei kommen auf jedem Host 3 Listen zum Einsatz.
files enthält alle Dateien, welche ich auf allen Computern nutzen möchte$HOSTNAME enthält Dateien, welche ich speziell auf diesem System haben möchte."$HOSTNAME"-not enthält Dateien, welche eigentlich in der Liste stehen, dennoch auf diesem System nicht installiert werden sollen.Da die Listen alle eigene Dateien sind, lassen sie sich auch ohne Editor erweitern.Die allgemeine Logik, wie mit der Liste umgegangen wird, stammt aus onthoughtbots dotfiles, meine derzeitige Version gibt es hier oder zum lesen jetzt auch einfach im Anschluss=1: #!/bin/bash
=2:
=3: #read content of files to decide, which files should be installed
=4: #files contains files for all hosts
=5: #$HOSTNAME contains host specific files
=6: #$HOSTNAME-not contains files excluded for this host,
=7: #overwrites everything else
=8:
=9: DOTFILES="cat files
"
10:
11:
12: if [ -f $HOSTNAME ]; then
13: DOTFILES="$DOTFILEScat $HOSTNAME
"
14: else
15: touch $HOSTNAME
16: fi
17:
18: if [ -f "$HOSTNAME"-not ]; then
19: if [ -f $HOSTNAME ]; then
20: DOTFILES=$(comm -3 cat files $HOSTNAME|sort) sort "$HOSTNAME"-not))
21: else
22: DOTFILES=$(comm -3 sort "files") sort "$HOSTNAME"-not))
23: fi
24: else
25: touch "$HOSTNAME"-not
26: fi
27:
28:
29:
30: cutstring="DO NOT EDIT BELOW THIS LINE"
31:
32: for name in $DOTFILES; do
33: target="$HOME/.$name"
34: #echo "trying to install $HOME/.$name"
35: if [ -e "$target" ]; then
36: if [ ! -L "$target" ]; then
37: cutline=grep -n -m1 "$cutstring" "$target" | sed "s/:.*//"
38: if [ -n "$cutline" ]; then
39: cutline=$((cutline-1))
40: echo "Updating $target"
41: head -n $cutline "$target" > update_tmp
42: startline=sed '1!G;h;$!d' "$name" | grep -n -m1 "$cutstring" | sed "s/:.*//"
43: if [ -n "$startline" ]; then
44: tail -n $startline "$name" >> update_tmp
45: else
46: cat "$name" >> update_tmp
47: fi
48: mv update_tmp "$target"
49: else
50: echo "WARNING: $target exists but is not a symlink."
51: fi
52: fi
53: else
54: if [ "$name" != 'install.sh' ]; then
55: echo "Creating $target"
56: if [ -n "$(grep "$cutstring" "$name")" ]; then
57: cp "$PWD/$name" "$target"
58: else
59: ln -s "$PWD/$name" "$target"
60: fi
61: fi
62: fi
63: done
64:
65: