SynchronisationIm Medialekt Blog habe ich kürzlich beschrieben, wie ich von der virtualisierten Entwicklungsumgebung zu Docker Container wechselte.

Zuvor hatte ich im JoomISP Blog meine Entwicklungstools, den Wechsel von Subversion zu Gitlab und Themen wie Continuous Integration erwähnt.

In diesem Beitrag gehe ich auf ein "Randthema" ein, welches sich durch den Wechsel ergab, nämlich der getrennten Repository-Ordner zu den Webserver Ordnern.

 

Bisherige Lösung - FTP Sync via Netbeans

In einer VirtualBox Maschine hatte ich einen vollwertigen Webserver laufen. Diesen habe ich immer dann manuell gestartet, wenn ich ihn benötigt habe. Nachteil dieser Lösung war, dass nach jedem Ruhezustand des Hosts der Webserver abstürzte und ich ihn neu starten musste. Außerdem belegte er ziemlich viel Speicher und RAM, musste natürlich auch stets gewartet werden.

Ich hatte ausschließlich mit der Netbeans IDE gearbeitet, welcher beim Speichern einer Datei automatisch per FTP die geänderte Datei hochlud.

Ich hatte also einen lokalen Ordner in meinem Benutzerprofil, welcher all meine Projektdaten in der Ordnerstruktur abgelegt hat, wie es das eingesetzte Joomla! CMS benötigt.
z.B.

/administrator/components/com_meinprojekt/
/administrator/language/de-DE/de-DE.com_meinprojekt.sys
/administrator/language/en-GB/en-GB.com_meinprojekt.sys
/components/com_meinprojekt/
/language/de-DE/de-DE.com_meinprojekt.sys
/language/en-GB/en-GB.com_meinprojekt.sys

 

Das restliche CMS lag natürlich auf dem Webserver, dadurch, dass meine IDE veränderte Dateien hochgeladen hatte, konnte ich unmittelbar die Änderung ausprobieren.

 

Probleme mit der Struktur der neuen Docker Container

Die Docker-Container sind soweit angelegt, wie das Docker-Projekt es vorschlägt, jeder Dienst sein eigener Container. Also jeweils eigene Container für:

  • Apache
  • PHP
  • MySQL
  • PHPMyAdmin

Es wäre kein Thema, noch einen zustäzlichen FTP Container einzubauen, ich möchte jedoch auch etwas mehr flexibilität in meinen Entwicklungsprozess einbauen und nicht nur mit Netbeans, sondern evtl. auch anderen IDEs arbeiten. Vor allem Visual Studio Code hat es mir momentan etwas angetan.

Manchmal wäre die Änderung aber auch so banal, dass ich nicht gleich die "große" IDE mit all seinen Projekten starten, sondern einfach gleich mit einem Texteditor die Änderung vornehmen möchte?

 

Wenn also mein GIT Überwachter Projektordner in meinem Benutzerverzeichnis liegt, z.B. ~/Entwicklung/com_meinprojekt muss dieses zum Ordner des Webservers kopiert werden z.B. /var/www/mein_projekt.

Vor allem liegen hier auch all die restlichen CMS Dateien, welche
A) das CMS benötigt, aber
B) nicht ins Git-Repository sollen.

 

Ein gewöhnlicher Sync der beiden Ordner ist also hier nicht möglich.

 

Vielmehr muss der Quellordner auf Änderungen geprüft werden und nur bei einer Änderung diese eine kopiert werden.

Zusätzlich möchte ich nicht auf einen Cronjob warten, welcher im dümmsten Fall 59s bis zum nächsten Durchlauf braucht.

 

Einfacher Lösungsweg - Inotify & Rsync Skript als Daemon

Nachdem ich einige Linux Tools angeschaut habe, wie FreeFileSync, SyncD oder DirSyncPro, welches mir noch am Besten gefiel, entschied ich mich für ein eigenes Skript.

Die meisten Tools arbeiten zeitbasiert, die kleinste Einheit ist 1 oder gar 5 Minuten. DirSyncPro war da schon besser, ich bekam es aber nicht hin, mehrere Ordner inkl. derer Dateien sowie Einzeldateien zu überwachen. Eine Antwort des Autors ist noch ausstehend.

 

Für das Skript werden eigentlich lediglich Inotify-Tools sowie Rsync benötigt. Ich betreibe bei mir ein aktuelles Kubuntu 18.10 welches als Basis dient:

sudo apt-get update && sudo apt-get install -y rsync inotify-tools

 

Dann erstelle ich irgendwo im System mein sync.sh Skript, in meinem Fall wo alle meine wichtigen Systemdaten liegen unter /opt:

#!/bin/bash

# Initialize first sync on script startup.
# Rsync syntax: "rsync -options SOURCE TARGET"
rsync -av ~/Entwicklung/com_meinprojekt/administrator/components/com_meinprojekt \
          /var/www/entwicklung/administrator/components/com_meinprojekt/ --delete
rsync -av ~/Entwicklung/com_meinprojekt/administrator/language/de-DE/de-DE.com_meinprojekt.sys \
          /var/www/entwicklung/administrator/language/de-DE/de-DE.com_meinprojekt.sys --delete
rsync -av ~/Entwicklung/com_meinprojekt/administrator/language/en-GB/en-GB.com_meinprojekt.sys \
          /var/www/entwicklung/administrator/language/en-GB/en-GB.com_meinprojekt.sys --delete
rsync -av ~/Entwicklung/com_meinprojekt/components/com_meinprojekt \
          /var/www/entwicklung/components/com_meinprojekt/ --delete
rsync -av ~/Entwicklung/com_meinprojekt/language/de-DE/de-DE.com_meinprojekt.sys \
          /var/www/entwicklung/language/de-DE/de-DE.com_meinprojekt.sys --delete
rsync -av ~/Entwicklung/com_meinprojekt/language/en-GB/en-GB.com_meinprojekt.sys \
          /var/www/entwicklung/language/en-GB/en-GB.com_meinprojekt.sys --delete

while true; do
    # Watch folders & files.
    inotifywait -r -e modify,attrib,close_write,move,create,delete \
        ~/Entwicklung/com_meinprojekt/administrator/components/com_meinprojekt/ \
        ~/Entwicklung/com_meinprojekt/administrator/language/de-DE/de-DE.com_meinprojekt.ini \
        ~/Entwicklung/com_meinprojekt/administrator/language/en-GB/en-GB.com_meinprojekt.ini \
        ~/Entwicklung/com_meinprojekt/components/com_meinprojekt/ \
        ~/Entwicklung/com_meinprojekt/language/de-DE/de-DE.com_meinprojekt.ini \
        ~/Entwicklung/com_meinprojekt/language/en-GB/en-GB.com_meinprojekt.ini \

    # Sync folders & files.
    # Rsync syntax: "rsync -options SOURCE TARGET"
    rsync -av ~/Entwicklung/com_meinprojekt/administrator/components/com_meinprojekt \
          /var/www/entwicklung/administrator/components/com_meinprojekt/ --delete
    rsync -av ~/Entwicklung/com_meinprojekt/administrator/language/de-DE/de-DE.com_meinprojekt.sys \
          /var/www/entwicklung/administrator/language/de-DE/de-DE.com_meinprojekt.sys --delete
    rsync -av ~/Entwicklung/com_meinprojekt/administrator/language/en-GB/en-GB.com_meinprojekt.sys \
          /var/www/entwicklung/administrator/language/en-GB/en-GB.com_meinprojekt.sys --delete
    rsync -av ~/Entwicklung/com_meinprojekt/components/com_meinprojekt \
          /var/www/entwicklung/components/com_meinprojekt/ --delete
    rsync -av ~/Entwicklung/com_meinprojekt/language/de-DE/de-DE.com_meinprojekt.sys \
          /var/www/entwicklung/language/de-DE/de-DE.com_meinprojekt.sys --delete
    rsync -av ~/Entwicklung/com_meinprojekt/language/en-GB/en-GB.com_meinprojekt.sys \
          /var/www/entwicklung/language/en-GB/en-GB.com_meinprojekt.sys --delete
done

 

Kurze Beschreibung des Skripts:
Als erstes initialisiere ich die Ordner und führe einen ersten Abgleich durch.
Anschließend startet die While Schleife und wartet bei "inotifywait" bis auf die eingetragenen Attribute, Ordner & Dateien eine Änderung ansteht.
Erst dann geht das Skript weiter zu den Rsync Teil, welcher eine Kopie der Initialisierung ist.

 

Dies ist ein erstes Skript, kann und wir in jeden Fall ausgebaut und vor allem vereinfacht werden. Mir geht es erstmal ausschließlich um die Funktion.

 

Beim manuellen Aufruf "sh sync.sh" sollte das Skript bereits die Syncs durchführen und keine Fehler melden.

Damit dies auch beim nächsten Start noch so ist, zudem leichter zu handeln ist, erstelle ich dafür einen Dienst.

 

Unter /etc/systemd/system/ erstelle ich einen Service namens sync.service:

[Unit]
Description = SyncService
After = network.target

[Service]
PIDFile = /run/syncservice/syncservice.pid
User = root
Group = root
WorkingDirectory = /opt
ExecStartPre = /bin/mkdir /run/syncservice
ExecStartPre = /bin/chown -R root:root /run/syncservice
ExecStart = /bin/bash /opt/sync.sh
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID
ExecStopPost = /bin/rm -rf /run/syncservice
PrivateTmp = true

[Install]
WantedBy = multi-user.target

 

Anschließend passe ich noch die Dateirechte an und Starte den Daemon neu, damit er den neuen Service kennt:

chmod 755 /etc/systemd/system/sync.service
systemctl daemon-reload

 

Nun kann ich wie gewohnt den Service starten, stoppen, neustarten und er läuft auch beim nächsten Neustart:

service sync start
service sync stop
service sync restart
service sync status

 

Kommentar schreiben
Ich habe den Datenschutz gelesen. Ich stimme zu, dass meine Angaben und Daten zur elektronisch erhoben und gespeichert werden. Alternativ kann ich als Namen auch ein Pseudonym eintragen. Hinweis: Sie können Ihre Einwilligung jederzeit für die Zukunft per E-Mail an widerrufen.

Anzeige