Wie man die TMP Ramdisk entfernt

Auf normalen Desktopsystemen ist es eine gute Sache, wenn der /tmp/ Ordner im RAM liegt. Auf /tmp/ wird sehr häufig und meistens eher kleinteilig zugegriffen, so das man diese Zugriffe  am besten von der Festplatte oder der SSD fern hält. Auf einem Server kann das aber auch von Nachteil sein.

[root@server ~]# df -h
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
devtmpfs        5,0G       0  5,0G    0% /dev
tmpfs           5,0G       0  5,0G    0% /dev/shm
tmpfs           5,0G    532K  5,0G    1% /run
tmpfs           5,0G       0  5,0G    0% /sys/fs/cgroup
/dev/xvda1      245G    178G   56G   77% /
tmpfs           5,0G     38M  5,0G    1% /tmp
tmpfs          1012M       0 1012M    0% /run/user/0

Im obigen Beispiel von einem unserer Server, kann man sehen, daß für die „tmpfs“ Laufwerke 5 GB maximale Größe angegeben ist. DEV, RUN, SYS werden das niemals erreichen, die sind eher im KB Bereich angesiedelt. Über die Sinnhaftigkeit, dann 5 GB als MAX Größe zu nehmen, kann man sicher streiten. Ist aber für die Betrachtung egal, denn es handelt sich um eine dynamische Speicherbelegung, deswegen auch „maximale Größe“. In Real sind die genau so groß, wie die Daten darin das brauchen. Lege ich dort 1 MB ab, ist es 1 MB und ein bisschen was für die Verwaltung groß.

An der „Verwendung“ in Prozent bzw. „Benutzt“ kann man auch sehen, das oben keins der TmpFS Ramdrives übermäßig belegt war. Die Ramdrives haben also bei dem Stand zusammen grade mal 39 MB echten Speicher belegt.

So weit, so gut.

Das obige Serversystem hat 10 GB Speicher zur Verfügung, was es üblicherweise auch braucht. d.h. es sind permanent mehrere GB an RAM in realer Benutzung.

Datenbankserver wie MariaDB erlauben es den Benutzern bei Abfragen sogenannte TEMP-Tables zu erstellen. Das wird vorzugsweise im RAM gemacht. Wenn aber das RAM nicht reicht, weil jemand einen TEMP-Table zusammen baut, der mehrere GB groß ist, dann wird das in den /tmp/ Ordner ausgelagert. Und man glaubt gar nicht wie unsensible mache Anwendungsentwickler im Umgang mit solchen Temp-Tables sind. „Killer SQL-Anweisungen“ in Shops, die „ein bisschen mehr und schneller“  gewachsen sind, als die Hersteller das erwartet haben, sind keine Seltenheit. Schlechtes Datenbankdesign sowieso nicht 😉  Und damit fängt der Ärger dann üblicherweise auch an.

Was bei einem Killer-SQL passieren kann …

Der Hauptspeicher des Datenbankserver hatte schon nicht ausgereicht um den Temp-Table anzulegen, und über die Ramdisk wird jetzt versucht den Speicher zusätzlich nochmal zu belegen, der vorher schon nicht ausreichend da war. Der Kernel wird jetzt versuchen diese Datenmengen zu swappen und kann das vielleicht nicht, weil die SWAP Partition zu klein ist. Nun kommt es zum „OOM“ dem Out-of-Memory-Error. d.h. der Kernel fängt an, scheinbar wahllos Prozesse zu killen, die viel Speicher belegen, aber noch nicht lange laufen. Eine genauere Analyse nimmt der Kernel leider nicht vor.

Wie kommt man jetzt aus der Falle wieder raus ?

Verantwortlich für das Erzeugen der Ramdisk ist diese Systemd Unit : /usr/lib/systemd/system/tmp.mount

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Temporary Directory
Documentation=man:hier(7)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
ConditionPathIsSymbolicLink=!/tmp
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target

[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime

Die kann man mit einem kurzen Befehl an den Systemd abschalten, allerdings erst ab dem nächsten Bootvorgang:

# systemctl mask tmp.mount
Created symlink from /etc/systemd/system/tmp.mount to /dev/null.
# ls -la /etc/systemd/system/tmp.mount
lrwxrwxrwx 1 root root 9 14. Nov 11:45 /etc/systemd/system/tmp.mount -> /dev/null

Danach muß man das also Rebooten. Am Ende ist /tmp/ dann wieder ein normaler Ordner auf der Festplatte, der keiner Größenbeschränkung unterliegt und in dem der Datenbankserver dann auch wieder fast beliebig große Temp-Tables erzeugen kann, ohne das gleich ein unschuldiger Prozess dran glauben muß.

 

PANIC: fatal region error detected; run recovery

Ok, vorweg, es geht nicht um GeoIPs, Zeitzonen oder andere Sachen die mit geografischen Regionen zutun hat 🙂

PANIC: fatal region error detected; run recovery

Das ist eine Meldung der BerkeleyDB, einer filebasierten einfachen Datenbank, die Programme gern benutzen, wenn Sie keinen richtigen Datenbankbackend brauchen/wollen. Eins der Programme ist der Webalizer, ein Analysetool , das jedem statistiksüchtigen  Apachenutzer  ein Begriff sein dürfte.

Es kann vorkommen, daß diese Datenbank beschädigt wird. Die Anwendung gibt dann die obige Fehlermeldung aus, oder auch nicht, weil nach >dev/null umgeleitet.

Woran merkt man das also, wenn dieser Fehler auftritt ?

Zunächst mal, macht Webalizer nichts mehr, er kommt nicht mehr voran, weil … keine Ahnung wie man so fehlerintolerant programmieren kann, ich weiß es nicht. Also das Teil bleibt einfach stehen. Das sieht dann so aus:

           |-sshd(878)-+-sshd(3593)---sshd(3619)---bash(3631)---webalizer(13066)---java(13074)-+-webalizer(16621)-+-webalizer(16623+
           |           |                                                                       |                  |-webalizer(16624+
           |           |                                                                       |                  |-webalizer(16625+
           |           |                                                                       |                  |-webalizer(16626+
           |           |                                                                       |                  |-webalizer(16627+
           |           |                                                                       |                  |-webalizer(16628+
           |           |                                                                       |                  |-webalizer(16629+
           |           |                                                                       |                  |-webalizer(16630+
           |           |                                                                       |                  |-webalizer(16631+
           |           |                                                                       |                  `-webalizer(16632+

im TOP und IOTOP sieht man Webalizer kann auch nicht mehr auftauchen, weil die Prozesse in einem QuasiSleep sind.

Wenn man jetzt auf den Hauptprozess (oben die PID 16621 ) ein strace anwendet mit „strace -s 1024 +f +p 16621“ bekommt man das zu sehen:

strace: Process 16621 attached
write(2, "BDB0060 PANIC: fatal region error detected; run recovery", 56

und nichts passiert mehr. In dem Fall kann man strace einfach abbrechen und getrost die dns_cache.db löschen:

rm -f /var/lib/webalizer/dns_cache.db

Dann bricht man den Webalizer Hauptprozess mit kill ab, und startet das Ganze von vorn. Fertig.

WordPress: Let’s Encrypt Zertifikate und PHP CURL

Let’s Encrypt Zertifikate und PHP CURL sind wie es scheint eine unheilige Verbindung, denn sie wollen nicht zusammen arbeiten. Aber der Reihe nach:

Am Anfang war das Update…

… und nach dem WordPressupdate, kommt auch die WordPress-Netzwerk-Updatefunktion, die, wenn man wie Bloggt-in-Braunschweig.de eine MultiSite betreibt, alle Blogs auf Stand bringt. Das war bislang kein Problem, weil die ohne SSL im Spiel zu haben, updated WordPress die Subinstallationen per HTTP aufruf. Nun, wenn man wie unsere Admins aber ein Lets Encrypt Zertifikat für die WordPressseite benutzt, ruft man den WP-Admin auch mit HTTPS auf, weil sonst das Zertifikat vollkommen umsonst wäre.

Solange man selbst den Adminteil aufruft, ist alles ok, weil der Browser kennt das LE Root Zert schon. Will man jetzt aber das Netzwerk updaten, ruft WordPress die Subseiten auch per HTTPS auf, auch wenn die gar nicht per HTTPS erreichbar sind, weil sie mit Subdomains arbeiten, für die der Webserver auch konfiguriert sein muß. Ab 100 Subdomains spielt LE auch bei der Zertifikaterstellung nicht mehr mit, was bedeutet, MultiSites mit über hundert Blogs müssen ein Wildcard-Zertifikat kaufen und das kann ins Geld gehen.

Jetzt gibt es zwei Wege das Problem mit LE zu lösen, ohne Geld auszugeben :

Man wechselt unschön auf HTTP und aktualisiert die Blogs so, oder man manipuliert den ROOT.CA Speicher von PHP und parkt das LE Root CA dort. Der letztere Teil rein technisch nicht weiter tragisch:

  1. Firefox aufmachen -> Einstellungen -> Erweitert -> Zertifikate  und das LE ROOT unter DST suchen und als /home/username/LEROOTCA.cert abspeichern.
  2. im PHP Code vor das curl_exec() folgende Anweisung schreiben:
    curl_setopt ($ch, CURLOPT_CAINFO, ‚/home/username/LEROOTCA.cert‘);
  3. Dann sollte das PHP Script auch das LE Zertifikat akzeptieren

Hier ein paar Wege um an so ein Zertifikat zu kommen:

Im FireFox auf der Seite mit dem benötigten Zertifikat einfach die Seiteninformationen aufrufen, dann Sicherheit und Zertifikat ansehen ( Details ) :

Wie man Zertifikate Exportiert Ein Klick auf Export und

Und speichern...

Jetzt der Haken an der Sache: im WordPress sind einfach zu viele Curl Calls drin, als das man als Laie mal eben die obige Operation durchführen kann. Ergo: Melden wir WP-User uns jetzt mal bei WP, auf das die den Support für LE bei WordPress einfach mitbringen 🙂