Archiv der Kategorie: Software

Alles was mit Software zu tun hat

Linux: Volle Speicher analysieren und „verlorenen“ Platz wiederfinden

No space left on device

Wer diese Nachricht sieht hat meist etwas Arbeit vor sich. Aber was, wenn der Speicher eigentlich gar nicht so voll sein sollte? Nun, dann muss man auf die Jagd gehen.

Vorab: Ich werde mich hier auf Befehle für die Kommandozeile beschränken, da sich diese sowohl auf Desktop-Rechnern mit GUI als auch Servern nutzen lassen. Auch gehe ich von einem „einfachen“ Dateisystem ohne Kompression, Snapshots oder Subvolumes aus.

Fall 1: Es ist voll – Belegung analysieren.

Die einfachste Variante: Irgendwas belegt tatsächlich den Platz. Dies ist der Fall, wenn die Ausgabe von du -shx / bzw. du -shx /dein/ordner tatsächlich etwa dem „Used“-Wert aus df -h / bzw. df -h /dein/ordner entspricht.

Für diesen Fall gibt es viele Tools, welche bei der Analyse helfen können, z.B. ncdu, welches sich in fast allen Paket-Managern finden sollte. Mit ncdu -x / bzw. ncdu -x /dein/ordner ermittelt es die Dateigrößen und stellt diese in einer TUI dar. Über die Pfeiltasten kann man zwischen den Dateien und Ordnern wechseln, mit Enter kommt man in den Order bzw. bei .. wieder zurück und mit d kann man die Datei direkt löschen.

Fall 2: Es ist noch voll – Gelöschte Dateien

Wenn der Usage-Wert aus df größer als jener aus du ist, dann können gelöschte Dateien im Spiel sein. Zumindest, wenn diese noch geöffnet ist. Nehmen wir ein Beispiel: Wir haben eine 4GB ISO-Datei im Ordner, diese binden wir in eine VM ein. Etwas später stellen wir Fest, dass wir die Datei ja eigentlich nicht mehr brauchen und löschen sie aus dem Ordner. Nun sollte man erwarten, dass im Ordner wieder 4GB frei sind, oder? Sind sie nicht, denn wir haben die ISO ja noch in der VM eingebunden, daher hat Linux nur vorgemerkt, dass die Datei gelöscht werden soll, gibt den Speicher aber erst wieder frei, wenn diese nirgendwo mehr in Verwendung ist. Ähnliches kann auch beim Überschreiben auftreten, da Linux die vorherige Version verfügbar hält, so lange diese von einem Prozess genutzt wird.

Die einfachste Möglichkeit solche Situationen zu beheben ist der Holzhammer: Ein Reboot beendet alle Prozesse, entsprechend ist auch nichts mehr geöffnet und alles Markierte verschwindet tatsächlich. Wer etwas feinfühliger sein möchte kann schauen, welcher Prozess derzeit bereits gelöschte Dateien verwendet. Die volle Liste gibt es mit . Etwas übersichtlicher macht es der Befehl *lufthol*

lsof | grep deleted | awk '{if ($7 > sizes[$9]) {sizes[$9] = $7; cmd = "ps -o comm= -p " $2; cmd | getline name; close(cmd); names[$9] = name; pids[$9] = $2}} END {for (file in sizes) print sizes[file], names[file], pids[file], file}' | sort -nr | numfmt --to=iec

Dieser Zeigt jede gelöschte, aber noch geöffnete Datei 1×, die Größten finden sich ganz oben in der Ausgabe. Hier sind ggf. auch andere Speicherbereiche wie memfs oder /dev/shm/… mit aufgelistet, welche für die Dateisysteme nicht relevant sind.

Hier hat z.B. ein qemu-Prozess mit der PID 32387 einen für uns nicht relevanten memfd mit 32 Gigabyte. Ein systemd-Teil mit der PID 2448 hält wiederum 13MB durch die Datei /usr/lib/udev/hwdb.bin in Beschlag, welche zwischenzeitlich überschrieben wurden. Mit diesen Informationen kann man die zugehörige Software dann gezielt beenden bzw. neu starten um den Speicher wieder freizugeben.

Fall 3: Es ist doch voll – Mount in vollem Ordner

Ein etwas anderer Fall, bei dem sich df und du unterscheiden, kann auftreten, wenn man mit mehreren Partitionen oder Datenträgern arbeitet. Auch hier wieder ein Beispiel: Wir haben eine Festplatte mit installiertem Linux. Unter /mnt/iso/ speichern wir jetzt 5 verschiedene Linux-ISOs mit je ca. 2GB, belegen also 10GB. Nun merken wir, dass wir mehr Platz benötigen, bereiten eine zusätzliche Festplatte vor und hängen diese unter /mnt/iso/ ein. Nun sind die ursprünglichen Dateien ja noch unter /mnt/iso/ gespeichert, da dort aber ein anderes Dateisystem eingehangen ist, wird der Pfad bei du (oder auch ncdu) ignoriert. Ähnliches habe ich auch häufiger bei der Verwendung mäßig stabiler Software wie Docker entdeckt – dies „vergisst“ bei einigen Container-Neustarts einige mounts mitzunehmen und schreibt die Daten dann nicht auf die Datenpartition, sondern, für das Hostsystem erst mal unsichtbar, auf den Datenspeicher des Root-Dateisystems. Um dies zu analysieren verwende ich gerne einen bind-mount, diese nehmen keine anderen Dateisysteme mit und schaffen so eine Stelle, um mit ncdu das komplette Dateisystem zu erfassen.

mkdir /tmp/bind
mount -o bind / /tmp/bind
ncdu -x /tmp/bind
# Nachdem man fertig ist
umount /tmp/bind
rmdir /tmp/bind

Fall 4: Es ist voll kaputt – Dateisystemfehler

Natürlich kann es auch immer mal vorkommen, dass das Dateisystem tatsächlich einen Fehler hat und daher den freien Speicher falsch berechnet. Hier hilft dann oft (vorzugsweise von einem Live-System) die jeweiligen Scan- und Reparaturtools zu starten. Meist sollte ein fsck /dev/yourdevice das passende Programm auswählen.

Windows: Umwandlung einer BIOS/MBR-Installation zu EFI/GPT

Hat man Windows vor $langerzeit installiert, wird das System vermutlich einen MBR und BIOS-Boot nutzen. Auch wenn diese Methode meist noch funktioniert, ist sie doch nicht mehr ganz zeitgemäß und kann in einigen Situationen dazu führen, dass man plötzlich etwas Bootfunktionalität vermisst. Insbesondere mit virtuellen Systemen, oder bei Dual-Boot, ist EFI oft flexibler und GPT im Zweifel resilienter gegen Störungen. Glücklicherweise kann man solche Systeme oft mit ein paar Befehlen, etwas Geduld und vielen gedrückten Daumen erfolgreich umwandeln, ohne dass eine Neuinstallation oder größere Kopiervorgänge notwendig sind.

Vorbedingungen

Um erfolgreich auf das GPT-Partitionsschema und einen EFI-Bootloader umzustellen, müssen einige Vorbedingungen erfüllt sein. Zuallererst muss die drunterliegende Hardware bzw. der Hypervisor natürlich das Booten per EFI unterstützen. Für Hardware sollte alles aus den letzten 10+ Jahren funktionieren. Bei VMs muss ggf. in der Konfiguration der Boot-Modus umgestellt werden.

Screenshot VMWare, VM-Optionen. Startoptionen→Firmware mit der Auswahl zwischen BIOS und EFI

Weiterhin wird etwas Platz benötigt. Etwa 150MB reichen aus. Bei VMs kann man z.B. die virtuelle Festplatte vergrößern, andernfalls kann man in Windows die Datenträgerverwaltung bemühen und die letzte Partition des Datenträgers verkleinern. Für Profis: Zumindest ein paar Byte müssen am ENDE des Datenträgers frei sein.

Screenshot Windows Datenträgerverwaltung. 60GB Datenträger mit 350MB NTFS System-reserviert und 59.66GB NTFS C:. Daneben Dialog „Verkleinern von Laufwerk C:“ mit Vorschlag um 18214MB zu verkleinern.

Verschlüsselungen wie Bitlocker habe ich nicht genutzt, im Zweifel sollte man diese für die Dauer der Umstellung abschalten. Ein Boot-Stick des Betriebssystem (bei aktuellen Systemen als Download, teils über Media Creation Tool) sollte zur Hand sein. Ich nutze Ventoy mit den zugehörigen ISOs.

Zu guter Letzt sollte man natürlich ein getestetes(!) Backup besitzen. Auch wenn die Methode bei mir bisher zuverlässig funktionierte, kann immer etwas schief gehen. Jedes System ist anders.

Part 1: Partitionsschema umwandeln

Erster Schritt ist die Umwandlung von MBR zu GPT. Letzteres ist deutlich neuer, hat Mechanismen um Beschädigungen zu erkennen/reparieren, kann mit größeren Datenträgern umgehen (MBR max. 2TB) und kann mehr als 4 (primäre) Partitionen pro Datenträger verwalten. Um keine Konflikte mit dem eigentlichen System zu provozieren nutze ich ein Linux-Livesystem, namentlich GParted. Technisch sollte auch das Windows-Tool mbr2gpt.exe funktionieren, dieses hat jedoch einige Einschränkungen.

Als Erstes startet man also GParted. Die Standardeinstellungen sind meist OK, bestenfalls das Tastaturlayout sollte man auf QWERTZ ändern, falls man mit QWERTY nicht klar kommt. Die GUI kann direkt über den „Block“ oben rechts geschlossen werden, stattdessen benötigen wir das Terminal. Hier macht man sich über „sudo su“ zum Systemverwalter. Wir wissen ja was wir tun und haben ein Backup – oder so. Mit lsblk kann man die aktuellen Datenträger und Partitionen raussuchen. Hier notiert man sich den Namen der Festplatte/SSD (Type: disk), welche man umwandeln möchte. Für S-ATA ist dies meist „sda„, bei NVME „nvme0n1„.

Nun geht es an die eigentliche Umwandlung. Mit „gdisk /dev/sda“ (name passend Tauschen) öffnet man das Gerät im GPT-Editor. Dieser sollte nun energisch darauf Hinweisen, dass er Magie anwendet und keine Gewähr für fehlende Körperteile oder Daten übernimmt:


Found invalid GPT and valid MBR; converting MBR to GPT format in memory. THIS OPERATION IS POTENTIALLY DESTRUCTIVE! Exit by typing 'q' if you don't want to convert your MBR partitions to GPT format!

Wichtig: Es darf keine Warnung bzgl. überlappenden Partitionen geben.

Warning! Secondary partition table overlaps the last partition by 33 blocks!
You will need to delete this partition or resize it in another utility.

Ist dies der Fall, steht am Ende des Datenträgers nicht genug Speicher zur Verfügung, es wurde also wohl nicht, wie oben beschrieben, passend verkleinert. Eventuell kann man in diesem Fall über die GParted-GUI die dortige Partition nochmal verkleinern bzw. verschieben und es erneut versuchen.

Alles OK? Dann haben wir nichts weiter zu tun. Gdisk hat bereits alle MBR-Partitionen in das GPT-Equivalent umgerechnet. Wer möchte kann mit „p“ einen Blick drauf werfen. Mit „w“ wird – nach Bestätigung – die neue Partitionstabelle auf den Datenträger geschrieben. Der GPT-Part ist somit abgeschlossen.

Part 2: EFI-Boot

Für UEFI benötigen wir jedoch noch etwas: Eine spezielle Boot-Partition. Diese ist vom Typ FAT32 und sollte >=100MB groß sein. Ich nutze für Umstellungen meist 128MB, Standard für Neusysteme ist bei den meisten Betriebssystemen etwa 512MB. Da GParted noch gebootet ist, kann man diese z.B. über die GParted-GUI an einer freien Stelle passend anlegen – ist meist übersichtlicher als auf der Konsole freie Blöcke zu finden. Windows lässt gerne mal ein paar Sektoren zwischendrin frei und verwirrt die Automatiken von fdisk & co. Also: In der GUI einen freien Block suchen, Rechtsklick→New, ggf. bei „New Size“ die gewünschte Größe anpassen und als File System „FAT32“ wählen. Ich schiebe die Partition meist noch oben nach rechts und vergrößere die Partition des Betriebssystems um eventuelle Lücken zu füllen. Über den grünen Haken schreibt man die Änderungen auf den Datenträger. Nach Abschluss des Vorgangs muss die Partition noch als „EFI System Partition“ markiert werden. Dazu macht man einen Rechtsklick auf die frische FAT32-Partition und wählt unter „Manage Flags“ die Einträge „esp“ und „boot„. Der Datenträger ist somit für EFI vorbereitet und GParted kann heruntergefahren werden.

Jetzt muss nur noch das Betriebssystem überzeugt werden mit der neuen Basis zu starten. Hierzu startet man einen passenden Installationsdatenträger, wählt aber über Repair→Troubleshoot die Eingabeaufforderung/Command line.

Hier werden dann erst mal die Laufwerksbuchstaben sortiert – ist mir sonst zu viel Chaos. Mit diskpart gelangt man in den passenden Editor, mit list volume kann man die aktuellen Partitionen und deren Buchstaben anzeigen lassen. Möchte man etwas ändern, wählt man z.B. mit „select partiton 3“ aus und weist mit „assign letter=s“ den Buchstaben zu. Ich habe die Windows-Partition auf C und die kleine EFI-Partition auf S.

Screenshot Eingabeaufforderung mit Diskpart. list Volumes zeigt die zuvor genannten Partitionen sowie die DVD (D). Die OS-Partition hat den Buchstaben C, die EFI-Partition hat keinen Buchstaben. Nach select volume und assign letter zeigt list volume den buchstaben an.

Ist man Fertig kann man das Tool mit exit beenden. Zuletzt wird der Windows-Bootloader neu aufgebaut – dies geschieht über die folgenden Befehle:

Bcdboot C:\Windows /s S:
Bootrec /fixmbr
Bootrec /fixboot
Bootrec /rebuildbcd

Nun kann man mit Exit und den passenden Menüpunkten das System ausschalten. Mit ausreichend gedrückten Daumen sollte beim nächsten Versuch Windows dann wieder starten und das gewohnte System präsentieren. Dieses kann man nun bewundern und die durch Umwandlung statt Neuinstallation gewonnene Zeit nutzen um darüber nachzudenken, wie man die Anwendung zukünftig auf ein freies Betriebssystem umziehen kann.

Gitlab-CE: Passwortwechsel bei nächstem Login erzwingen

GitLab ist – wie der Name schon erahnen lässt – ein Git-basiertes Entwicklungsmanagement auf Ruby-Basis. Zusätzlich zur Versionsverwaltung gibt es auch Issue-Tracker, Wikis, CI/CD und Vieles mehr. Im Gegensatz zu GitHub lässt es sich auch lokal auf eigenen Systemen installieren, in der Community Edition dabei unter freier Lizenz. Als Alternative wäre noch Forgejo zu nennen, welches weniger kommerziell daher kommt.

Auf einer GitLab-Instanz hatte ich nun eine etwas andere Aufgabe: Ein verwendeter Zugang wurde als potentiell unsicher eingestuft. Nichts, was eine direkte Aktion notwendig machte, aber man sollte es auch nicht ignorieren. Normalerweise erzwinge ich in solchen Fällen einen Passwortwechsel beim nächsten Login. So wird der Nutzer zu geeigneter Zeit aktiv auf das Problem hingewiesen und es sind keine alternativen Kommunikationskanäle notwendig. Während GitLab prinzipiell einen erzwungenen Passwortwechsel unterstützt, gibt es offenbar keine Option dies über die üblichen Wege manuell auszulösen.

Der offizielle Weg

Die Offizielle Empfehlung ist recht klar: Als Admin unter Overview→User→Edit und dort ein neues Passwort festlegen. Dies ist temporär, der User muss es beim nächsten Login ändern. Hierbei wird auch sichergestellt, dass die aktuellen Kennwortrichtlinien eingehalten werden.

Für mich in diesem Fall kein sinnvoller Weg, da durch den Kennwort-Wechsel der Zugang umgehend nicht mehr möglich ist und ein separater, sicherer Kommunikationskanal notwendig ist um das neue, temporäre Kennwort zu übermitteln.

Eingeweide

Offiziell geht es also nicht, aber die Funktion selbst ist ja da. Über einige Tricks kann man dafür sorgen, dass der Passwortwechsel mit dem aktuellen Kennwort angefordert wird. Notwendig ist dazu ein Konsolenzugang zum Server, auf dem GitLab ausgeführt wird. Hier startet man eine Rails-Konsole (ggf. mit sudo), sucht den User und setzt das Ablaufdatum des Kennworts auf die aktuelle Zeit.

gitlab-rails console
user = User.find_by_username('bernd')
user.password_expires_at=Time.now
user.save
quit

Beim nächsten Login sollte nun der Passwortwechsel angefordert werden. Tipp: Es gibt auch ein verlockendes user.password_automatically_set. Dieses sorgt nicht für einen Passwortwechsel, sondern sperrt den interaktiven Login vollständig.

Eigentlich schade, dass so eine einfache und technisch vorhandene Möglichkeit nicht in den Dialogen angeboten wird. Auch wenn ich sicherheitstechnisch nachvollziehen kann, dass eine Sperrung und temporäres Passwort oft die bessere Wahl ist, sollte man den Admins nicht die Wahl vorenthalten Prozesse zu nutzen, welche den eigenen Anforderungen bessern entsprechen.

Docker: Container-Zombies blockieren Netzwerk-Löschung

(Achtung, Rant-Character. Wer das nicht mag findet die Lösung in den letzten 3 Absätzen)

Heute also mal wieder Docker. Ein stetiger Quell an Problemen. Ursprünglich war meine Anforderung gar nicht so kompliziert: Per docker-compose soll eine Multi-Container-Applikation aus- und wieder eingeschaltet werden. Also: docker-compose down und warten. Leider scheiterte der Prozess bereits an dieser Stelle aufgrund eines Timeouts. Das Schreiben großer Caches beim Beenden benötigt eben seine Zeit. Sicher, es gäbe -t oder stop_grace_period, aber wie das oft so ist: Wer auch immer vorher damit gearbeitet hat, hat es natürlich nicht dokumentiert oder konfiguriert.

Nunja, der docker-daemon sollte die zugehörigen Container trotz des Timeouts im Frontend noch abarbeiten – entsprechend war nach kurzer Bedenkzeit in docker ps -a auch kein Container mehr zu sehen, der zur Applikation gehört.

Alles gut? Leider nein. Das folgende docker-compose up weigerte sich beharrlich die Container wieder zu starten. Es versuchte immer noch, die Überreste der alten Struktur, insbesondere die Netzwerke, zu löschen, und scheiterte:

ERROR: error while removing network: network application_network id XXX has active endpoints

Active? Interessant, denn in docker ps -a war ja definitiv nichts mehr aktiv. Auch ein manuelles docker network remove application_network behauptete weiterhin, dass es die ID noch gäbe.

Error response from daemon: error while removing network: network application_network id XXX has active endpoints.

Ein docker network inspect application_network verriet: Die nicht mehr gelisteten Container sind wohl doch noch da – zumindest so halb. Also gehen wir auf Zombie-Jagd.

Die Lösung: Erst trägt man mit docker network inspect application_network | grep Name die Namen der verbliebenen Containerreste zusammen. Im Anschluss kann man über docker network disconnect ein Entfernen erzwingen.

for i in application_db_1 application_es_1 application_redis_1 application_nginx_1 ;do docker network disconnect -f application_network $i ;done

Abschließend entfernt man mit docker network remove application_network das Netzwerk. Danach sollte einem erneuten Start nichts mehr im Wege stehen.

Absichtliche Latenz für Pulseaudio

Wieder einmal stoße ich an eigentlich einfache Dinge, die dank Closed-Source aber etwas komplizierter sind: Ich möchte Youtube-Videos von meinem Laptop auf dem Fernseher schauen. Hierzu nutze ich üblicherweise einen Chromecast, welcher sich per Chrom[e|ium] oder Smartphone bedienen lässt. Nun hatte ich jedoch den Wunsch nur Bild zu übertragen, den Ton aber am lokal angebundenen Bluetooth-Kopfhöhrer zu behalten. Das ist so leider nicht vorgesehen, also bleibt nur Improvisation.

Für das Bild ist das schnell erledigt: Ein ungenutzter HDMI-Port wird kurzerhand eingeschaltet und per Chrome geteilt, so wird verhindert, dass der Chromecast auf die interne App zurückfällt. Der Ton bleibt so ebenfalls lokal verfügbar, aber nicht Synchron. Durch die Übertragung ist das bild knapp eine Sekunde hinterher.

Also muss das Audiosignal des Browsers absichtlich verzögert werden. Pavucontrol bietet hierzu eine Latenzeinstellung, dessen Funktion ist jedoch von der verwendeten Soundhardware abhängig. In meinem Fall konnte ich unabhängig der Einstellung keine Latenz feststellen.

Abhilfe schafft die Konsole und ein Tipp von Thomas auf Stackexchange. Es wird ein Dummy-Gerät registriert, welches vom Browser als Ziel genutzt werden kann. Dieses wiederum wird als loopback wieder an das korrekte Ausgabegerät angehangen. Den passenden Namen der Ausgabe findet man mit pactl list cards. Da hier alles in Software emuliert wird, sind nun die Latenzangaben funktionsfähig.

pactl load-module module-null-sink sink_name=delay
pactl load-module module-loopback latency_msec=2000 source=delay.monitor sink=alsa_card.pci-0000_00_1f.3.analog-stereo

Deutlich komplexer als ein HDMI-Kabel, aber was tut man nicht Alles um nicht das passende Kabel suchen gehen zu müssen…

Qt5: LoadLibrary-Fehler mit RDP unter Windows (ATI, OpenGL, Nextcloud)

Das Qt-Framework wird von vielen Projekten genutzt um grafische Oberflächen auf allen Betriebssystemen einheitlich entwickeln zu können. Bekannte Softwarepakete, welche Qt nutzen, sind unter Anderem: Nextcloud-Client, Owncloud-Client, FileZilla, Quassel, Mumble, MiniTube, Bitcoin-Qt, Scribus, LuminanceHDR, Audacious, Clementine, LMMS, VLC, AviDemux-qt, Shotcut, OpenShot, LibreCAD, FreeCAD, OpenSCAD, QOwnNotes, Calibre, KeePassX, KeePassXC, Wireshark und BlueStacks.

Eigentlich eine praktische Sache, jedoch mit einem Haken: Mit Qt5 versuchte man viele grafische Operationen per Hardwarebeschleunigung zu erledigen. Dies sorgt für schnellere Programme und weniger Systemlast. Für die Ansteuerung der Grafikkarte nutzt man hierbei OpenGL, welches auf allen gängigen Betriebssystemen verfügbar ist. Leider tritt man sich hierbei auch einige Probleme ein, so ist z.B. Windows dafür bekannt qualitativ zweifelhafte Treiber zu verteilen, welche stark auf Gaming optimiert sind, aber bei anderen Operationen gerne ins Straucheln kommen.

Ein recht verbreitetes Problem tritt dann auf, wenn eine AMD-Grafikkarte wie z.B. Radeon oder im System steckt, man jedoch auf den Windows-Rechner per Remote Desktop (RDP) zugreift. Windows lädt – auch wenn RDP genutzt wird – die Grafikkartentreiber. Ein Fehler in den ATI-Treibern, welcher bereits seit Ende der 2010er-Jahre bekannt ist, führt jedoch dazu, dass in RDP-Sitzungen Grafikoperationen nicht in Software ausgeführt oder von der Grafikkarte berechnet und zurückgegeben werden, sondern sie versuchen diese Trotzdem komplett in der GPU zu verarbeiten und brechen die Anfrage letztendlich ab. In vielen Anwendungen äußert sich das in fehlenden Grafikelementen oder Fehlermeldungen. So lässt sich z.B. der Nextcloud-Client gar nicht starten und Quittiert den Versuch die GUI per RDP zu öffnen mit einem fatalen Fehler. Es ist somit nicht möglich die Software per RDP zu starten.

Fehlermeldung NextCloud-Client: „LoadLibrary failed with error 87: The parameter is incorrect.“

Glücklicherweise kann man sich hierbei einer Eigenheit von „Shared Libraries“ zu nutze machen, welche peeter123 auf GitHub vorschlägt: Jede App bevorzugt seine eigene Version, nur wenn sie selbst nichts mitliefert wird auf jene des Systems zurückgegriffen. Im Falle des OpenGL-Bugs kann man also einfach statt der Microsoft/ATI-Version eine weniger kaputte nutzen. Hierzu eignet sich z.B. die Variante des Mesa-Projektes, welche die OpenGL-Operationen nicht direkt an die Grafikkarte sendet. Um diese nun einzubinden lädt man auf der Releases-Seite die letzte Release-Version für mingw herunter (mesa3d-xx.yy.zz-release-mingw.7z), öffnet diese (z.B. mit 7Zip) und kopiert aus dem Ordner x64 (für 64-Bit-Systeme) die Datei „opengl32.dll“ in den Ordner des betroffenen Programms, also z.B. C:\Program Files\Nextcloud. Hierdurch greift die Änderung nur für diese eine App und beeinflusst nicht alle installieren Programme. Fortan sollten die Operationen der Software ohne GPU-Treiber laufen und die Applikation somit auch per RDP lauffähig sein.

Durch diese Änderung verliert man zur potentiell etwas Geschwindigkeit in der betroffenen App, dies sollte bei aktuellen Systemen aber nicht groß auffallen – insbesondere, wenn man diese ohnehin nicht häufig aktiv nutzt. Immerhin ist die Software so auch remote nutzbar. Mit fortschreitender Migration auf Qt6 sollte sich das Problem mit der Zeit auch ganz von selbst erledigen: Dies nutzt statt OpenGL die jeweiligen Funktionen des Betriebssystems, welche auch auf Windows nicht ganz so kaputt sind.

Raspian: AbhängigkeitsFehler bei Upgrade von Buster zu Bullseye (unreleased)

Normalerweise ist ein Upgrade von Debian zu einer neueren Version keine große Sache: System in aktuellen Release aktualisieren (apt dist-upgrade), Sources anpassen, full-upgrade, fertig. Leider scheint Raspian hier wieder eine Extrawurst zu benötigen. Nach Ändern der Sources von Buster (Debian 10) zu Bullseye (Debian 11) gab es beim full-upgrade einen Abhängigkeitsfehler:

Calculating upgrade... Error!
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libc6-dev : Breaks: libgcc-8-dev (< 8.4.0-2~) but 8.3.0-6+rpi1 is to be installed
E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.

Manuell festgenagelte Pakete gab es meinerseits nicht, entsprechend hätte ich erwartet, dass die Abhängigkeiten automatisch aufgelöst werden können. Abhilfe schaffte letztendlich das Update von GCC vor dem full-upgrade mittels apt install gcc-8-base per Hand zu installieren. Hierdurch wurden die beteiligten Pakete vorab aktualisiert und das Abhängigkeitsproblem somit aufgelöst.

Vorsicht: Bullseye für Raspian ist auch 2 Monate nach dem Release von Debian 11 noch nicht offiziell freigegeben. Viele Systemteile, die Raspian gegenüber einem „echten“ Debian ändert, sind noch nicht lauffähig. So startet nach dem Update beispielsweise dhcpcd nicht mehr. Schaltet man die Raspian-Anpassungen ab (z.B. in dem man Systemd, Networkmanager o.Ä. nutzt) ist das System jedoch prinzipiell lauffähig.

Windows-Update – Fehler 0x800f0831 beheben

Hinweis: Die Screenshots sind von einem älteren System, die Meldungen, Pfade und Vorgehensweisen sollten sich jedoch auch auf aktuelle Versionen übertragen lassen.

Und wieder das übliche Bild: Auf einem Windows-System sind nicht alle Updates installiert. Keine gute Idee, insbesondere bei Systemen, die an einem Netzwerk betrieben werden. Also schnell in die Einstellungen und Updates installieren – in der Theorie. Leider passiert es nach meiner Beobachtung immer wieder, dass Updates quer sitzen und sich nicht installieren lassen. Auch im aktuellen Fall sah man bereits: „Failed“ war im letzten Installationsversuch zu erkennen.

8 offene Windows-Updates, letzter Installationsversuch fehlgeschlagen

Auch ein manueller Versuch über „Install updates“ brachte kein Erfolg. Der Assistent schien fehlerfrei zu laufen, nach dem im Anschluss angeforderten Reboot war jedoch das Bild wieder identisch: Die Updates standen erneut als offen drin. Also erster Blick: Welche waren überhaupt betroffen. In den Details fanden sich neben den meist wenig aussagekräftigen Bezeichnungen auch die KB-Nummern, welche bei Microsoft die zugehörigen Dokumentationen beschreiben.

Liste der offenen Updates mit KB-Nummern

Hier kam dann der Microsoft Catalog unter https://www.catalog.update.microsoft.com/ ins Spiel: Über diese Webseite lassen sich per KB-Nummer einzelne Updates suchen und per Hand herunterladen. Hierbei etwas aufpassen: Oft sind die Updates für verschiedene Betriebssystemversionen und CPU-Architekturen mit der selben KB-Nummer eingestellt, beim Download lohnt es sich also doppelt hin zu schauen.

Microsoft Update Katalog-Webseite mit einzelnen Updates

Die zum Download angebotenen MSU-Dateien sollten sich direkt per Doppelklick öffnen lassen und einen Setup-Assistenten zeigen. Leider brachte auch die händische Installation keine Besserung – am Ende des Assistenten vermeldete das Ergebnis ein wenig aussagekräftiges „The following updates were not installed„. Auch die Ereignisanzeige des Betriebssystems verriet nicht mehr als eben jene wenig hilfreiche Statusmeldung.

An dieser Stelle wird oft eine Reparatur mit DISM.exe /Online /Cleanup-image /Restorehealth bzw. Sfc /scannow oder gar eine Neuinstallation empfohlen. Ist jedoch klar, dass das System keine weiteren Probleme hat, ist eine gezielte Reparatur jedoch oft weniger Zeitintensiv als eine vollständige Neuinstallation, insbesondere wenn die betroffenen Systeme nicht über ein Konfigruationsmanagement/Orchestration zur automatischen Installation verfügen.

Glücklicherweise erstellt Windows Update an diversen Stellen erweiterte Protokolle, welche die Fehlersuche erleichtern. Bei Installationsfehlern sind die CBS-Logs meist die hilfreichste Anlaufstelle. Die Korrekte Datei findet sich unter %systemroot%\Logs\CBS\CBS.log. Eine Suche nach “ Error “ (mit ein paar Leerzeichen dahinter) sollte die relevante Stelle schnell sichtbar machen. In diesem Fall handelte es sich um eine Inkonsistenz im Updatespeicher, die zugehörige KB-Nummer ist in solchen Fällen in der Fehlermeldung erkennbar. Wer diese vergleicht wird feststellen, dass es sich hierbei nicht um eins der zur Installation vorgemerkten Updates handelte. Stattdessen betraf es ein älteres Update, welches für die aktuelle Installation benötigt wurde. Das genannte, ältere Update war laut System installiert, fehlte in Realität jedoch. Ein solcher Zustand ist oft zu finden, wenn bei einem vorherigen Update der Rechner abstürzte.

Ausschnitt CBS-Log. Vorausgesetzte KB-Nummer in der Fehlermeldung erkennbar

Also zurück zum Catalog, dort kann man das defekte Update manuell herunterladen und nochmals installieren. Ist dies Erfolgreich sind Updatespeicher und Realität an dieser Stelle wieder auf einem konsistenten Stand und die Installation der neueren Updates kann fehlerfrei erfolgen. Möglicherweise muss der Vorgang für mehrere ältere Updates wiederholt werden. Hier kann es helfen in der Updatehistorie zu prüfen, welche Updates mit dem Betroffenen zeitgleich installiert wurden und diese – sofern nicht ersetzt – präventiv ebenfalls neu zu installieren. Am Ende sollten sich alle Updates installieren und das System so auf einen aktuellen Stand bringen lassen.

Windows 10: Fehlende Audioausgabe nach April 2020-Updates (Realtek)

Nach installation der April 2020 Updates für Windows 10 19.09 kam es auf einigen von mir betriebenen Systemen zum Verschwinden der Audio-Treiber. Somit war eine Ton Ein- und Ausgabe nicht mehr möglich. In Zeiten von dauerhaften Videoschalten eher ungünstig. Selbes wurde von anderen Nutzern berichtet. Allen gemein: Es handelt sich um PCs und Laptops mit Realtek-Sound auf Basis von Intel HD Audio.

Treiber-Updates zeigen keine Änderung, das Booten eines vernünftigenanderen Betriebssystems bingt funktionierenden Ton mit sich. Interessant dabei: Die Audio-Devices tauchen nicht einmal mehr im Gerätemanager auf. In den ausgeblendeten Geräten wird das Gerät noch angezeigt, jedoch mit der Info „Dieses Hardwaregerät ist zurzeit nicht an den Computer angeschlossen. (Code 45)“.

Sucht man etwas weiter findet man unter „Systemgeräte“ einen Eintrag für „Intel(R) Smart Sound Technologie-OED“, welcher als „nicht gestartet“ (Code 10) markiert ist.

Auch an diesem kann man sich lange erfolglos abarbeiten. Ursache ist der vermeintlich fehlerfreie eintrag drüber: „Intel(R) Smart Sound Technologie-Audiocontroller“. Hier klickt man in den Details auf Treiber ? Treiber aktualisieren. Im Assistenten wählt mach „Auf dem Computer nach Treibersoftware suchen“ und dort „Aus einer Liste verfügbarer Treiber auf meinem Computer auswählen“.

Nun erhält man eine Liste aktueller und älterer Treiber. Statt der Smart-Sound-Technologie (SST) wählt man „High Definition Audio-Controller“ und installiert diesen. Im Anschluss erkennt Windows alle Geräte am Audio-bus neu und die Sound-Ausgabe sollte wieder wie gewohnt funktionieren.

PostgreSQL-Update im Docker-Stil

Docker. Eigentlich ja ganz praktisch, wenn man „mal schnell“ ein Softwarepaket trotz überschaubarer Wartbarkeit mit überschaubarem Aufwand ausrollen möchte, ab und an aber auch ein zuverlässiger Quell für Facepalm-Momente. So auch Heute: Nach dem Update einer mit docker-compose zusammengesetzten Anwendung ging nichts mehr. Der Maintainer hatte dort von postgres:10 auf postgres:11 aktualisiert. Kleines Update sollte man meinen, die PostgreSQL-Images für Docker sind jedoch technisch nicht in der Lage Daten älterer Installationen zu migrieren. Folglich zeigte sich im Log vor dem Absturz folgende Meldung:

postgres_1 | FATAL: database files are incompatible with server
postgres_1 | DETAIL: The data directory was initialized by PostgreSQL version 10, which is not compatible with this version 11.6.

Was auf „normalen“ Servern mit pg_upgrade schnell geregelt und bei einigen Distributionen gar automatisiert ist, wird mit Docker ein paar Nummern komplizierter. Der Offizielle Weg: Backup machen, neu aufsetzen, importieren. Eigentlich wollte ich durch Docker Arbeit sparen, nicht mir weitere aufhalsen.

Glück im Unglück: Tianon Gravi hat auf GitHub und Docker Hub ein passendes System bereitgestellt, mit welchem man die Daten schnell zwischen verschiedenen PostgreSQL-Versionen migrieren kann.

Im Folgenden gehe ich davon aus, dass ein Named Volume „postgres-data“ existiert und alle darauf zugreifenden Container gestoppt sind.

Achtung, Fallstrick: Nutzt man docker-compose, so ändern sich die Volume-Namen. Ein Named Volume „postgres-data“ der Applikation „foobar“ heißt in Wahrheit „foobar_postgres-data„. Im Zweifel nochmal mit „docker volume ls“ prüfen.

  1. Fangen wir mit dem üblichen an: Backups. Bei Bind-Mounts kopiert man einfach den Quellordner passend zurecht, bei Named Volumes kann man diese üblicherweise unter /var/lib/docker/volumes/ finden oder mit docker-clone-volume duplizieren. Ich hatte postgres-data hierzu auf postgres-data-src und postgres-data-bck dupliziert.
  2. Weiter geht es mit dem Umwandeln der Datenbank. Hierzu nimmt man das Image mit den passenden Versionsnummern für Quell- und Zielversion.
    docker run --rm -v postgres-data-src:/var/lib/postgresql/10/data -v postgres-data-dst:/var/lib/postgresql/11/data tianon/postgres-upgrade:10-to-11
    Hiermit wird ein neues, mit PostgreSQL 11 kompatibles, Volume erzeugt, welches alle bisherigen Daten enthalten sollte.
  3. Leider gibt es in der aktuellen Version einen bekannten Bug, welche die Zugriffe in pg_hba.conf abweichend von den Dateien der offiziellen Images konfiguriert. Dies führt mit vielen Images zu Zugriffsfehlern. Um die Datei per hand zu editieren startet man entweder einen passenden Container oder greift über das Dateisystem des Hosts auf diese zu. In meinem Fall nutzte ich letztere Methode über die Datei /var/lib/docker/volumes/postgres-data-dst/_data/pg_hba.conf. An das Ende dieser wird folgende Zeile angefügt:
    host all all all md5
  4. Am Ende ändert man entweder den Volume-Eintrag seiner docker-compose.yml oder kopiert das neue Image passend zurück. In meinem Fall klang letzteres sinnvoller. Einen Befehl zum Umbenennen von Volumes ist Docker bis Heute nicht bekannt, daher bleibt hier nur das ursprüngliche Volume mit docker volume rm postgres-data zu löschen und postgres-data-dst – wie zuvor – mit docker-clone-volume oder im Dateisystem zum korrekten Volume-Namen zu klonen.

Warum man das nicht automatisiert erschließt sich mir nicht so ganz. Vermutlich beschränkt sich der Benutzerkreis hauptsächlich auf Entwickler, die ohnehin immer von 0 starten, und Enterprise-Häuser, die gemäß Fire-and-forget Systeme ohne Update bis zur Explosion betreiben.