Linux: bei Änderung einer / mehrerer Dateien ein Kommando starten

Mittwoch, 16. Oktober, 2019

Ich brauchte da mal was für unsere Systemlandschaft: der Webservice soll neu gestartet werden, wenn sich eine vordefinierte Datei ändert. Wenn es ein Update der Web-Applikation gibt, dann kann jenes Update ein touch [Dateiname] auslösen.

Wenn das Check-Skript mit einem User läuft, der den Webservice starten darf - sei es mit root oder einem User, dem sudo auf systemctl erlaubt ist - dann kann ein Entwickler niedrige Applikationsrechte haben, ihn aber eine spezifische höhere Rechte erforderliche Aktion ausführen lassen, ohne ihm selbst root oder sudo Rechte geben zu müssen.

Mein Skript habe ich onfilechange.sh genannt.
Es benötigt minimal Parameter zum Erfassen der zu überwachenden Trigger-Dateien und das auszuführende Kommando.
Mit einem “-v” schaltet man den Verbose-Modus ein - dann sieht man mehr, was das Skript gerade macht.

Parameter:

-c [command]
    command to execute on a file change
-f [filename(s)]
    filenames to watch; separate multiple files with space and put all in quotes
-h
    show this help
-i
    force inotifywait command
-s
    force stat command
-v
    verbose mode; enable showing debug output
-w [integer]
    for stat mode: wait time in seconds betweeen each test or on missing file; default: 5 sec

Ein erstes einfaches Beispiel:
Es wird der Text Hallo ausgegeben, sobald man (z.B. in einem 2. Terminal) die Datei /tmp/mytestfile toucht oder beschreibt.

onfilechange.sh -f "/tmp/mytestfile" -c 'echo "Hallo" '

Mit einem zusätzlichen Parameter -v kann man etwas genauer reinschauen, wie das Skript onfilechange.sh arbeitet.

Auf der Kommandozeile macht das Skript wenig Sinn. Um es permanent laufen zu lassen, sollte man es als Dienst einrichten. Wie man mit dem Skript einen Systemd Service einrichtet, ist in der Readme enthalten. Folge ganz unten dem Link zum Sourcecode.

Lizenz: Free software; GNU GPL 3.0

Und noch etwas zu den Interna, wie man die Datei-Überwachung bewerkstelligen kann:

(1)
Das gibt es zum einen inotifywait . Das Tool erhält man in vielen Distros mit Installation der “inotify-tools”.

Nachteile:
- Die Datei / alle zu prüfende Dateien müssen immer existieren. Wenn es einen Prozess gibt, der das Löschen der Trigger-Datei zulässt, ist diese Kommando ungünstig
- Installation der “inotify-tools” ist erforderlich

Vorteile:
+ Man kann mehrere Dateien zum Überwachen andocken
+ Man kann spezifisch definieren, welche Events man überwachen möchte
+ Ohne einen Loop zu verwenden, kann man nach Beendigung mit Returncode 0 ein Kommando starten. Die Ausführung erfolgt sofort

(2)
Das Kommando stat liefert etliche Datei-Attribute, wie Namen, letzer Zugriff, letzte Änderung, Rechte, …

Nachteile
- man kann nur 1 Datei prüfen. Bei mehreren muss man sich einen Loop über n Dateien bauen
- es braucht eine while Schleife und ein sleep N, um zyklisch einen Zustand zu überwachen
- der Kommando-Aufruf erfolgt nicht sofort, sondern ist entspr. sleep in dessen Wartezeiten etwas verzögert.

Vorteile:
+ Man kann obige Nachteile weitestgehend umgehen - dann ist die Prüfung mit stat auch die zuverlässigere Variante
+ Es ist in jeder Distribution in der Standard-Installation enthalten

weiterführende Links:

  1. Download/ Readme: git-repo.iml.unibe.ch: onfilechange

Xampp: Port 3306 belegt - durch Firefox

Mittwoch, 2. Oktober, 2019

Schon komisch: ein Programm krallt sich einen Port. Ich dachte, das wäre die Domäne von Skype.

2019-10-02-xampp-port-3306-durch-firefox-belegt.png

Abhilfe:

  1. Firefox beenden
  2. Mysql im Xampp starten
  3. Firefox starten

preDispatcher - speed up my slow Concrete5 website

Dienstag, 20. August, 2019

Meine Concrete5 Webseite wurde langsamer und langsamer. Sie wird auf einem Shared Hosting betrieben (was ohnehin nicht die schnellste Option sein kann) - hier kann ich zudem keinen Varnish oder auch nur irgendeinen anderen Caching Dienst installieren und davorschalten, sondern muss mich mit .htaccess und Standard-PHP-Mitteln behelfen können.

Das Initialisieren eines Requests in Concrete5 (Bootstrapping) braucht scheinbar sehr lange. Selbst statische Inhalts-Seiten, die ein aktives Fullpage Cache haben, benötigen für die Verarbeitung am Server mehr als 200 ms. Hinzu kommen für einen kompletten Request dann noch Netzwerkzeiten für Namensauflösung (DNS), Anfrage zum Server senden … und das Ergebnis zum Browser zurücksenden, was der Browser dann rendert. Meine schnellsten Seiten aus dem CMS waren bei 300 ms. Andere brauchten 3 Sekunden und mehr. Concrete5 ist einfach langsam.

Ich habe einen Cache geschrieben, der Concrete5 vorgeschaltet ist und im Filesystem seine Caching-Daten ablegt. Kurz er hat minimalste Anforderungen und arbeitet mit einem Shared Hoster. Dieses “Vorschalten” umgeht die lange Initialisierungszeit von Concrete5 - dies macht die Seite schnell.

Vor einigen Tagen habe ich eine erste Version meines preDispatchers eingespielt. Erwartungsgemäss muss man ein paar Kinderkrankheiten ausmerzen. Aber erste Ergebnisse in der Webseiten-Statistik (Matomo) zeigen, dass es eine gute Entscheidung war: die mittleren Seiten-Generierungs-Zeiten sanken von über 2s auf unter 0.4s

2019-08-20-predispatcher-generation-time-in-matomo.png

Der PreDispatcher besitzt eine Debugging-Ausgabe, die die Arbeitsweise veranschaulicht und den Unterschied deutlich macht. Das ist ein ungecachter Aufruf einer Seite mit Fullpage Cache in C5 - also inkl. Bootstrapping + Auslieferung einer in C5 gecachten Seite:

2019-08-20-predispatcher-uncached-concrete5-request-of-fullpage-cached-page.png

Der PreDispatcher speichert den Request, der nicht im Cache ist (oder dessen Caching Zeit abgelaufen ist). Der nächste Request auf dieselbe Seite wird dann schnell. Richtig schnell:

2019-08-20-predispatcher-cached-request.png

Wie lange eine Seite aus einem Cache kommt? Man definiert einen Default für alle Seiten. Mit einer Liste von Regex für aufzurufende URLS kann man die Standard-Vorgabe übersteuern und einen neuen Wert zuweisen.

Zudem gibt es eine Erkennung, was nicht gecacht werden darf - oder wo ein Cache verworfen werden muss. Ich kann mich im C5 Backend einloggen - und der Cache jeder mit Login aufgerufenen Seite wird verworfen.

Ich bin wohl auf dem richtigen Weg. Aber ein wenig Feintuning braucht es noch. Bei Interesse, schaut auf Github … oder fragt mich an :-)

Der PreDispatcher ist Freie Software - unter GNU GPL 3!

weiterführende Links:

  1. Github: pre-dispatcher for more speed
  2. Concrete5 webseite

jsclasses.org - Top user rated classes

Donnerstag, 16. Mai, 2019

Oh, was für eine kleine nette Überraschung: Das da bin ja ich :-)

2019-05-16-jsclasses-top-rated-classes.png

Mit dieser Klasse wird bei einem Passwort-Feld ein Div eingeblendet. Darin wird die Erfüllung der vorgegebenen Bedingungen (z.B. Anzahl Zeichen, Gross-/ Kleinschreibung, Anzahl Sonderzeichen) dargestellt - on the fly während der Passworteingabe.

Diese Klasse ist Freie Software und Open Source.

weiterführende Links:

  1. Axels Webseite: ahPwcheck
  2. Docs: Password checker (en)
  3. jsclasses.org: AH JavaScript Password Strength Check: Calculate and display the strength of a password (en)

PHP: komisch grosse Zeiten in Curl

Mittwoch, 8. Mai, 2019

Ich hatte wirklich seltsame Antwortzeiten mit der Curl-Bibliothek in PHP in meiner eigenen Monitoring-Anwendung.
Bei Verwendung von curl_getinfo($curl) ist der Wert von “total_time” ein Wert in Sekunden. Eigentlich. Bei einer Reaktionszeit von 16ms sollte es 0,016 sein, ich erhielt aber 16000.

Das Problem ist, dass sich die Werte der Curl-Funktion bei Verwendung von PHP mit mod_php korrekt verhalten - nur im FCGI Modus gibt es Zahlenwerte, die Faktor 1 Mio. zu gross sind.

Bei einer Antwort-Zeit von 16 ms sollte der Wert im Feld total_time 0.016 sein - unter FCGI kommt aber 16000 zurück.

2019-05-08-curl-time-values.png

Nach einer kurzen Suche, fand ich einen bestehenden Bugreport, wo ich meine Daten ergänzte. Mal schauen, ob da wohl was geht …

weiterführende Links:

  1. bugs.php.net- 76438: wrong curl_getinfo time values
  2. php.net: Funktion curl_getinfo()
  3. Github: IML AppMonitor