<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>bisko.be - Dev</title><description>Technik, Entwicklung, Hardware und Experimente.</description><link>https://bisko.be/de/posts/dev/</link><language>de</language><item><title>Ollama mit älteren GPUs unter CachyOS betreiben</title><link>https://bisko.be/de/posts/dev/running-ollama-with-older-gpus-on-cachyos/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/running-ollama-with-older-gpus-on-cachyos/</guid><description>Heute habe ich meine Windows-11-VM auf Linux migriert, um flexibler bei den Diensten zu sein, die darauf laufen, und bin dabei auf ein Problem gestoßen: Ollama lief nicht auf meinen alten GPUs – GTX1070 und GTX970</description><pubDate>Sat, 28 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;tldr&quot;&gt;TL;DR;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ollama-cuda&lt;/code&gt; unterstützt unter CachyOS (zum jetzigen Zeitpunkt) nur &lt;code&gt;compute &gt;= 7.5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Wenn du ältere GPUs mit niedrigerem &lt;code&gt;compute&lt;/code&gt; hast, MUSST du eines von 2 Dingen tun:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ollama-cuda&lt;/code&gt; aus dem Quellcode bauen, mit Unterstützung für die älteren Compute-Targets&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ollama-vulkan&lt;/code&gt; installieren&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ich habe mich für &lt;code&gt;ollama-vulkan&lt;/code&gt; entschieden und es läuft einwandfrei!&lt;/p&gt;
&lt;h3 id=&quot;storytime&quot;&gt;Storytime&lt;/h3&gt;
&lt;p&gt;Heute kam mir die Eingebung, endlich meine Windows-11-VM abzuschalten und auf Linux zu migrieren.&lt;/p&gt;
&lt;p&gt;Die Anforderungen waren, dass Folgendes laufen muss:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ollama – für lokale Modell-Magie&lt;/li&gt;
&lt;li&gt;Docker – für Remote-Entwicklung&lt;/li&gt;
&lt;li&gt;Steam – zum Zocken&lt;/li&gt;
&lt;li&gt;Jellyfin – für das Heimvideo-Archiv&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ich konzentriere mich jetzt nur auf Ollama, denn es war eine interessante Erfahrung und hat mich zum Nachdenken gebracht, warum die Dinge nicht offensichtlicher sind.&lt;/p&gt;
&lt;p&gt;In der Maschine stecken 2 GPUs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GTX 1070 – 8 GB&lt;/li&gt;
&lt;li&gt;GTX 970 – 4 GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ich wollte Ollama darauf laufen lassen, um mit lokalen Modellen herumzuspielen und zu schauen, wie ich sie in ein paar Projekte integrieren könnte. Zum Beispiel: Daten lokal anonymisieren, eine nicht-destruktive OpenClaw-Implementierung bauen, die zu meinen Anwendungsfällen passt, lokale OCR für Dokumente, die ich mit dem Handy scanne, und einige Dinge im Alltag der Haushaltsverwaltung automatisieren.&lt;/p&gt;
&lt;p&gt;Also habe ich ganz selbstverständlich &lt;code&gt;ollama&lt;/code&gt; und &lt;code&gt;ollama-cuda&lt;/code&gt; installiert, da ich 2 Nvidia-GPUs drin habe, und erwartet, dass das problemlos funktioniert, schließlich lief es unter Windows ja noch ein paar Minuten zuvor.&lt;/p&gt;
&lt;p&gt;Ich habe Ollama gestartet, &lt;code&gt;qwen3:8b&lt;/code&gt; für ein schnelles Experiment geladen und… es lief auf der CPU 🤔&lt;/p&gt;
&lt;p&gt;Die GPUs wären völlig in der Lage gewesen, das Modell im VRAM zu halten, aber aus irgendeinem Grund entschied sich Ollama, es auf der CPU laufen zu lassen.&lt;/p&gt;
&lt;p&gt;Nachdem ich versucht hatte, es anhand der Logs herauszufinden, habe ich Claude um Hilfe gebeten, und der kam mit einem ziemlich entmutigenden Ergebnis um die Ecke:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; logs&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; tell&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; story&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clearly.&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Both&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; your&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; GPUs&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; are&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; detected&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; but&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; then&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; filtered&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; out&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; because&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; they&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; fail&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; CUDA&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; initialization:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  &quot;filtering device which didn&apos;t fully initialize&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; id=GPU-eb132a13-b9f4-40e3-d85d-60f211dfd21e&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; library=CUDA&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  &quot;filtering device which didn&apos;t fully initialize&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; id=GPU-550263c8-37e2-2a25-c0b6-10cc7511ed20&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; library=CUDA&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  The&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; reason&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; is&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; CUDA&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; library&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; bundled&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Ollama&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0.17.4&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; was&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; compiled&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; these&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; architectures&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; only:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  CUDA.0.ARCHS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;=750,800,860,870,880,890,900,1000,1030,1100,1200,1210&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  The&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; minimum&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; supported&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; compute&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; capability&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; is&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 7.5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (Turing &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; RTX&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; 20xx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; series&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;). Your GPUs are older than that:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  ┌──────────┬────────────────────┬──────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;   GPU&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Compute&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Capability&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Architecture&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  ├──────────┼────────────────────┼──────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; GTX&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1070&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; │&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6.1&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Pascal&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;       │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  ├──────────┼────────────────────┼──────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; GTX&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 970&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  │&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5.2&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                │&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Maxwell&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  └──────────┴────────────────────┴──────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  Neither&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; is&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; supported&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; list,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; so&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; CUDA&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; initialization&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; fails&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; both,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; and&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Ollama&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; falls&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; back&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; CPU-only&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; inference.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  Your&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; options:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  1.&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Downgrade&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Ollama&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; an&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; older&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; that&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; still&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; included&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Pascal/Maxwell&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; support&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pre-0.6.x &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;era&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; had&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; broader&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; arch&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; coverage,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; but&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; check&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; release&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; notes&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; specifics&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  2.&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Build&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Ollama&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; source&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; CUDA_ARCHITECTURES=&quot;52;61;75;80;86&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; include&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; your&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; GPU&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; architectures.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  3.&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Upgrade&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; GPUs&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; at&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; least&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; an&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; RTX&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2060&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; or&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; newer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (compute &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;7.5+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das war ehrlich gesagt ein ziemlicher Dämpfer, denn ich wollte die GPUs so lange wie möglich nutzen, bevor ich auf eine neue umsteige.&lt;/p&gt;
&lt;p&gt;Ich wollte Ollama nicht tatsächlich aus dem Quellcode neu bauen, denn es sollte eigentlich out of the box funktionieren, und ich war sehr verwirrt, warum es das nicht tat, obwohl die Windows-Installation diese Architekturen unterstützt hat.&lt;/p&gt;
&lt;p&gt;Diese Karten wurden auf der Ollama-Website außerdem als unterstützt aufgeführt!&lt;/p&gt;
&lt;p&gt;Um die lange Google-Odyssee abzukürzen:&lt;/p&gt;
&lt;p&gt;Es stellt sich heraus, dass &lt;code&gt;ollama-cuda&lt;/code&gt; nur mit den oben genannten Anforderungen kommt… und der Tipp lautete, &lt;code&gt;ollama-vulkan&lt;/code&gt; zu installieren.&lt;/p&gt;
&lt;p&gt;Nachdem ich das gemacht hatte, lief alles butterweich!&lt;/p&gt;</content:encoded><category>linux</category><category>llm</category><category>ollama</category><category>cachyos</category><category>vulcan</category><category>cuda</category></item><item><title>[Linux] Eine getrennte `apt dist-upgrade`-Sitzung wiederherstellen</title><link>https://bisko.be/de/posts/dev/linux-recovering-a-disconnected-apt-dist-upgrade-session/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/linux-recovering-a-disconnected-apt-dist-upgrade-session/</guid><description>Heute habe ich meine Proxmox-Installation aus der Ferne über die integrierte Konsole aktualisiert, dabei aber vergessen, was ich gerade tat, und den Tab mittendrin geschlossen. Dadurch konnte ich mich nicht mehr verbinden, denn die Pakete wurden bereits im Hintergrund aktualisiert und das Upgrade hatte eine Frage zum Ersetzen einer Datei gestellt und wartete auf Antwort</description><pubDate>Wed, 23 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Heute habe ich meine Proxmox-Installation aus der Ferne über die integrierte Konsole aktualisiert, dabei aber vergessen, was ich gerade tat, und den Tab mittendrin geschlossen.&lt;/p&gt;
&lt;p&gt;Das führte dazu, dass ich mich nicht mehr verbinden konnte, da die Pakete bereits im Hintergrund aktualisiert wurden und das Upgrade eine Frage zum Ersetzen einer Datei gestellt hatte und nun auf meine Eingabe wartete.&lt;/p&gt;
&lt;p&gt;Ich konnte mich also per SSH einloggen, aber nichts tun, da es immer noch auf eine Eingabe in einer Konsole wartete, mit der ich mich nicht verbinden konnte, weil sich die Oberfläche nicht öffnen ließ.&lt;/p&gt;
&lt;p&gt;Nach kurzem Umschauen bin ich auf einen &lt;a href=&quot;https://serverfault.com/questions/19634/how-to-reconnect-to-a-disconnected-ssh-session&quot;&gt;Serverfault-Thread&lt;/a&gt; gestoßen, in dem erwähnt wurde, &lt;code&gt;reptyr&lt;/code&gt; zu benutzen, um die Terminalsitzung per SSH zu übernehmen.&lt;/p&gt;
&lt;p&gt;Ich halte hier fest, was genau ich gemacht habe, um die Sitzung zurückzubekommen und das Upgrade abzuschließen:&lt;/p&gt;
&lt;p&gt;Aus &lt;a href=&quot;https://serverfault.com/questions/19634/how-to-reconnect-to-a-disconnected-ssh-session#comment1506308_979180&quot;&gt;diesem Kommentar&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; https://github.com/nelhage/reptyr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; reptyr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damit wurde &lt;code&gt;reptyr&lt;/code&gt; auf dem Rechner installiert.&lt;/p&gt;
&lt;p&gt;Dann habe ich mit &lt;code&gt;ps ax | grep pts&lt;/code&gt; nach allen offenen Sitzungen gesucht, um den gesuchten Prozess zu finden.&lt;/p&gt;
&lt;p&gt;Danach habe ich den obersten Elternprozess im Prozessbaum gefunden, dem ein &lt;code&gt;pts&lt;/code&gt; zugewiesen ist, und mich über seine PID daran angehängt:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reptyr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -T&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1390511&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann konnte ich das Upgrade abschließen! 🎉&lt;/p&gt;</content:encoded><category>Uncategorized</category></item><item><title>[Linux] Syncthing – Dateisystem schreibgeschützt, wenn es als Service läuft</title><link>https://bisko.be/de/posts/dev/linux-syncthing-read-only-file-system-when-running-as-service/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/linux-syncthing-read-only-file-system-when-running-as-service/</guid><description>Ich benutze Syncthing jetzt schon seit ein paar Monaten, um meine Arbeitskopie mit einem lokalen Dev-Server zu synchronisieren. Anfangs habe ich es genutzt, indem ich mich eingeloggt und es manuell über die CLI gestartet habe. Das lief gut, also habe ich mir keine weiteren Gedanken gemacht, als ich es auf den Betrieb als Service umgestellt habe.</description><pubDate>Wed, 06 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ich benutze &lt;a href=&quot;https://syncthing.net/&quot;&gt;Syncthing&lt;/a&gt; schon eine Weile, um meine Arbeitskopie mit einem lokalen Dev-Server zu synchronisieren, genauer gesagt seit ein paar Monaten.&lt;/p&gt;
&lt;p&gt;Anfangs habe ich es genutzt, indem ich mich eingeloggt und es manuell über die CLI gestartet habe. Das lief gut, also habe ich mir keine weiteren Gedanken gemacht, als ich es auf den Betrieb als Service umgestellt habe. Es startete, es synchronisierte ein paar Daten, alles war in Ordnung.&lt;/p&gt;
&lt;p&gt;Bis es das natürlich nicht mehr war! 🙂&lt;/p&gt;
&lt;p&gt;Wie sich herausstellte, hatte ich eine ganze Reihe von Fehlern in den Logs übersehen, die besagten, dass das Dateisystem auf dem Dev-Server schreibgeschützt ist, und deshalb synchronisierte Syncthing überhaupt nichts.&lt;/p&gt;
&lt;p&gt;Ich dachte, es wäre ein Bug und es würde bei den Ordnern nur &lt;code&gt;Out of Sync&lt;/code&gt; anzeigen, aber eigentlich würde es synchronisieren. Tja, falsch gedacht.&lt;/p&gt;
&lt;p&gt;Nach ein paar Stunden Debugging und ein paar Google-Suchen, bei denen ich in den Foren absolut keine Hinweise fand, landete ich bei einem &lt;a href=&quot;https://wiki.archlinux.org/title/syncthing#read-only_file_system_error_on_/etc_although_run_as_root&quot;&gt;Syncthing-Artikel im ArchWiki&lt;/a&gt;, der genau meinen Fall beschrieb:&lt;/p&gt;
&lt;p&gt;read-only file system error on /etc although run as root&lt;/p&gt;
&lt;p&gt;Das war exakt mein Anwendungsfall, nur dass der problematische Ordner nicht &lt;code&gt;/etc&lt;/code&gt; war, sondern &lt;code&gt;/usr/local/src&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nach dem Lesen stellte sich heraus: Wenn man Syncthing (oder irgendetwas anderes) über &lt;code&gt;systemd&lt;/code&gt; laufen lässt und für den Service &lt;code&gt;ProtectSystem&lt;/code&gt; auf &lt;code&gt;full&lt;/code&gt; gesetzt ist, werden standardmäßig einige Verzeichnisse schreibgeschützt. &lt;code&gt;/usr&lt;/code&gt; ist eines dieser Verzeichnisse.&lt;/p&gt;
&lt;p&gt;Um das zu beheben, muss man in der Service-Konfiguration eine neue Zeile hinzufügen und den Service neu starten (und &lt;code&gt;daemon-reload&lt;/code&gt; ausführen):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ReadWritePaths=/usr/local/src&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Danach sollte Syncthing einwandfrei funktionieren.&lt;/p&gt;</content:encoded><category>Homelab</category><category>linux</category><category>permissions</category><category>read-only</category><category>syncthing</category><category>systemd</category></item><item><title>[Linux] Mehrere Befehle parallel auf mehreren Servern ausführen</title><link>https://bisko.be/de/posts/dev/linux-running-multiple-commands-on-multiple-servers-in-parallel/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/linux-running-multiple-commands-on-multiple-servers-in-parallel/</guid><description>Ich habe zu Hause einen Cluster aus Raspberry Pis, auf dem Docker Swarm läuft. Damit alles im Gleichschritt bleibt, verwenden sie dieselbe Konfiguration – Benutzer, Docker-Versionen usw. Manche Updates erfordern, dass auf allen Knoten des Clusters dasselbe ausgeführt wird – zum Beispiel das Anlegen eines neuen Docker-macvlan-Netzwerks. Um</description><pubDate>Mon, 19 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ich habe zu Hause einen Cluster aus Raspberry Pis, auf dem Docker Swarm läuft. Damit alles im Gleichschritt bleibt, verwenden sie dieselbe Konfiguration – Benutzer, Docker-Versionen usw.&lt;/p&gt;
&lt;p&gt;Manchmal erfordern Updates, dass auf allen Knoten des Clusters dasselbe ausgeführt wird – zum Beispiel das Anlegen eines neuen Docker-macvlan-Netzwerks.&lt;/p&gt;
&lt;p&gt;Dafür muss man entweder dieselben Befehle auf allen Knoten manuell ausführen, indem man sich per &lt;strong&gt;ssh&lt;/strong&gt; auf jeden einzelnen einloggt, die Befehle laufen lässt und dann zum nächsten weitergeht.&lt;/p&gt;
&lt;p&gt;Da ich versuche, langfristig meinen Aufwand zu reduzieren und alles so ordentlich wie möglich zu halten, habe ich angefangen, nach Möglichkeiten zu suchen, Befehle auf allen Knoten gleichzeitig auszuführen.&lt;/p&gt;
&lt;h3 id=&quot;iteration-1-eigenes-python-skript&quot;&gt;Iteration 1: Eigenes Python-Skript&lt;/h3&gt;
&lt;p&gt;Die erste Iteration bestand darin, ein eigenes Python-Skript zu schreiben. Einerseits wollte ich dabei Python etwas besser lernen, andererseits fand ich keinen guten Weg, Befehle auf eine eher native Art auszuführen.&lt;/p&gt;
&lt;p&gt;Wie zu erwarten war (ich habe schließlich noch wenig Erfahrung mit der Sprache 🙂 ), wurde es ziemlich schnell ein aufgeblähtes Durcheinander und war sehr anfällig für Fehler.&lt;/p&gt;
&lt;p&gt;Ich musste einen anderen Weg finden, ohne mir ständig neu erarbeiten zu müssen, was ich vor drei Wochen gemacht hatte und was beim letzten Mal kaputtgegangen ist.&lt;/p&gt;
&lt;h3 id=&quot;iteration-2-pssh&quot;&gt;Iteration 2: &lt;code&gt;pssh&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Beim Herumgooglen bin ich auf &lt;code&gt;[pssh](https://linux.die.net/man/1/pssh)&lt;/code&gt; gestoßen, das Dinge parallel über SSH ausführen kann.&lt;/p&gt;
&lt;p&gt;Alles in allem war es ziemlich einfach, das Ganze zum Laufen zu bekommen.&lt;/p&gt;
&lt;p&gt;Das Problem war, dass ich einige Dinge per &lt;code&gt;sudo&lt;/code&gt; ausführen musste. Passwörter herumzureichen war nicht gerade ideal, also musste ich wieder suchen, wie ich das &lt;code&gt;sudo&lt;/code&gt;-Passwort senden kann, wenn der entfernte Server danach fragt.&lt;/p&gt;
&lt;p&gt;Es stellt sich heraus, dass es ziemlich einfach ist, wenn man über den richtigen &lt;a href=&quot;https://unix.stackexchange.com/a/487558/134974&quot;&gt;StackOverflow-Kommentar&lt;/a&gt; stolpert.&lt;/p&gt;
&lt;h3 id=&quot;die-kurzfassung-tldr&quot;&gt;Die Kurzfassung (TL;DR):&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stty&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -echo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;printf&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Password: &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; PASS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stty&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;PASS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pssh&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;HOSTFIL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;E&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/output&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -t&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -I&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;`&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ./commands.sh`&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das &lt;code&gt;-I &quot;`cat ./commands.sh`&quot;&lt;/code&gt; muss genau so geschrieben werden (in Anführungszeichen und Backticks eingefasst), sonst werden die Befehle nicht richtig ausgeführt. Das Passwort wird als separater Befehl gesendet und nicht als Eingabe für &lt;strong&gt;sudo&lt;/strong&gt; aufgenommen.&lt;/p&gt;
&lt;p&gt;Der andere Haken ist, dass man wegen dieser Konstruktion &lt;code&gt;sudo&lt;/code&gt; mit dem Parameter &lt;code&gt;-S&lt;/code&gt; ausführen muss, damit die Passworteingabe korrekt entgegengenommen wird.&lt;/p&gt;</content:encoded><category>Uncategorized</category></item><item><title>Das Passwort einer numerischen ZIP-Datei nur mit Kommandozeilen-Werkzeugen erraten</title><link>https://bisko.be/de/posts/dev/guessing-a-numeric-zip-file-password-only-with-command-line-utilities/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/guessing-a-numeric-zip-file-password-only-with-command-line-utilities/</guid><description>Heute habe ich meine monatliche Rechnung von meinem Internetanbieter erhalten und etwas kam mir seltsam vor. Die Rechnung, die in der E-Mail enthalten war, befand sich in einer passwortgeschützten ZIP-Datei. Ganz zu schweigen davon, wie merkwürdig es in der heutigen Zeit ist, einen Anhang als ZIP-Datei zu erhalten (Spam, Malware, Phishing usw.), das</description><pubDate>Mon, 14 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Heute habe ich meine monatliche Rechnung von meinem Internetanbieter erhalten und etwas kam mir seltsam vor.&lt;/p&gt;
&lt;p&gt;Die Rechnung, die in der E-Mail enthalten war, befand sich in einer ZIP-Datei mit Passwort.&lt;/p&gt;
&lt;p&gt;Ganz zu schweigen davon, wie merkwürdig es in der heutigen Zeit ist, einen Anhang als ZIP-Datei zu erhalten (Spam, Malware, Phishing usw.), kam mir das gewählte Passwort ziemlich schwach vor.&lt;/p&gt;
&lt;p&gt;Es ist der Geburtstag des Kontoinhabers im Format &lt;code&gt;YYMMDD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ich habe im Fitnessstudio eine sehr grobe Berechnung im Kopf angestellt und bin auf sehr wenige mögliche Kombinationen gekommen. Nachdem ich mit einem Online-Tool berechnet habe, wie viele Tage seit dem 1900-01-01 vergangen sind (da nicht alle Kombinationen ein gültiges Datum ergeben würden), stellte sich heraus, dass es nur 44.075 Kombinationen sind (bis 2020-09-14).&lt;/p&gt;
&lt;p&gt;Da ich weiß, dass optimierte Tools, die GPU-Leistung zum Knacken von Hashes nutzen, Millionen von Versuchen pro Sekunde durchführen können, wollte ich sehen, wie schnell das Passwort ohne solche Tools geraten werden kann, nur mit der Linux/macOS-Kommandozeile (da ich im Fitnessstudio nur Zugriff auf einen VPS hatte).&lt;/p&gt;
&lt;p&gt;Ich habe folgenden Code entwickelt, der unter macOS funktioniert:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;echo {1..44000} | xargs -P 16 -n 1 -I{} date -v &quot;-{}d&quot; +&quot;%y%m%d&quot; | xargs -P 16 -I{} sh -c &apos;unzip -qqoP &quot;{}&quot; 0417160508.zip &amp;#x26;&amp;#x26; echo &quot;{}&quot; &amp;#x26;&amp;#x26; exit 255&apos;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Der Befehl ist von seiner Funktionsweise her ziemlich einfach, auch wenn er kompliziert erscheint.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;echo {1..44000}&lt;/code&gt; erzeugt die Zahlen von 1 bis 44.000 und gibt sie an den nächsten Schritt weiter.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xargs -P 16 -n 1 -I{} date -v &quot;-{}d&quot; +&quot;%y%m%d&quot;&lt;/code&gt; – nimmt die Eingabe aus dem ersten Schritt und erzeugt Daten im Format &lt;code&gt;YYMMDD&lt;/code&gt;, indem die Funktionalität von &lt;code&gt;date&lt;/code&gt; genutzt wird, ein Datum um einen bestimmten Betrag zu „ergänzen“. In diesem Fall würde es X Tage vom aktuellen Datum abziehen, wobei X die im ersten Schritt erzeugte Zahl ist. Auf diese Weise können wir Daten vom heutigen Tag zurück bis in die 1900er Jahre erzeugen.&lt;/p&gt;
&lt;p&gt;Der dritte Schritt ist der interessantere, daher werde ich ihn in zwei Teile aufteilen:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xargs -P 16 -I{} sh -c &apos;...&apos;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Dies nimmt die in Schritt 2 erzeugten Daten und führt für jedes dieser Daten einen Befehl aus. &lt;code&gt;-P 16&lt;/code&gt; bedeutet hier, dass dies in 16 parallelen Prozessen ausgeführt wird, um das Durchsuchen der Daten zu beschleunigen. Derselbe Trick wird auch in Schritt 2 angewendet, um die Datumserzeugung zu beschleunigen.&lt;/p&gt;
&lt;p&gt;Der zweite Teil ist der Ort, an dem die Rateversuche stattfinden:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;unzip -qqoP &quot;{}&quot; 0417160508.zip &amp;#x26;&amp;#x26; echo &quot;{}&quot; &amp;#x26;&amp;#x26; exit 255&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Dabei wird zunächst versucht, die ZIP-Datei mit dem in Schritt 2 erzeugten Passwort zu entpacken. Wenn es erfolgreich ist, wird das erratene Passwort ausgegeben (&lt;code&gt;echo&lt;/code&gt;), und dann erzwingt &lt;code&gt;exit 255&lt;/code&gt;, dass &lt;code&gt;xargs&lt;/code&gt; die Ausführung stoppt. Wir wollen nicht weiter raten, wenn das Passwort bereits gefunden wurde.&lt;/p&gt;
&lt;p&gt;Alles in allem war es eine ziemlich schlechte Entscheidung, dies als Passwort für die Datei zu wählen, denn das Ausführen des obigen Befehls dauert nur etwa 10 Sekunden, um das richtige Passwort für meine Rechnung zu erraten. Für jeden anderen auch nicht viel länger.&lt;/p&gt;</content:encoded><category>Uncategorized</category></item><item><title>Umgang mit Spaghetti-Code in PHP: Anonyme Funktionen nutzen, um Teile von Template-Code zu extrahieren</title><link>https://bisko.be/de/posts/dev/dealing-with-spaghetti-code-in-php-using-anonymous-functions-to-extract-pieces-of-template-code/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/dealing-with-spaghetti-code-in-php-using-anonymous-functions-to-extract-pieces-of-template-code/</guid><description>Kürzlich habe ich einem Freund geholfen, Code zu verstehen und so zu ändern, dass er gut mit asynchronen Aufrufen ans Backend funktioniert. Ein Bonus wäre, ihn modularer und wiederverwendbarer schreiben zu können. Der Code ist ein WordPress-Plugin, das geschrieben wurde</description><pubDate>Sat, 08 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kürzlich habe ich einem Freund geholfen, Code zu verstehen und so zu ändern, dass er gut mit asynchronen Aufrufen ans Backend funktioniert. Ein Bonus wäre, ihn modularer und wiederverwendbarer schreiben zu können.&lt;/p&gt;
&lt;p&gt;Der Code ist ein WordPress-Plugin, das mit einem sehr altmodischen Ansatz geschrieben wurde – Business- und Frontend-Logik an einer Stelle vermischt. Datenmanipulationen mitten im Template-Code und so weiter.&lt;/p&gt;
&lt;p&gt;Im Grunde das, was man Anfang der 2000er auf PHP-Seiten gesehen hat, bevor all die großartigen OOP-Erweiterungen in die Sprache kamen und es eine Reihe ausgereifter Frameworks gab.&lt;/p&gt;
&lt;p&gt;Der Fall, an dem ich heute geknabbert habe, sah so aus: Du hast eine Tabelle, die eine Menge Einträge anzeigt. Wir mussten der Tabelle mehrere Filter hinzufügen und sie per AJAX funktionieren lassen, damit sich die Oberfläche schnell aktualisiert, ohne die ganze WordPress-Admin-Seite neu zu laden.&lt;/p&gt;
&lt;p&gt;Das Filtern der Daten war einfach – ein schnelles Inline-&lt;code&gt;array_filter&lt;/code&gt;, um die Daten zu filtern, bevor sie an den Template-Code übergeben wurden (um den Code-Stil beizubehalten, stand das ebenfalls in der Template-Datei 😇).&lt;/p&gt;
&lt;p&gt;Das Problem begann, als wir daran gingen, die Tabelle über AJAX renderbar zu machen.&lt;/p&gt;
&lt;p&gt;Sie steckt mitten in einem Haufen anderen Template- und Business-Codes. Wenn wir die Ausgabe per AJAX nur auf die Tabelle beschränken wollten, hatten wir nur ein paar Möglichkeiten.&lt;/p&gt;
&lt;p&gt;Die erste wäre, das HTML vor und nach der Tabelle in RIESIGE &lt;code&gt;if&lt;/code&gt;-Anweisungen zu packen, damit es nicht gerendert wird.&lt;/p&gt;
&lt;p&gt;Eine andere wäre, das Template in eine separate Datei auszulagern und sie in der AJAX-Action einzubinden, die wir im Code des Plugins definieren würden.&lt;/p&gt;
&lt;p&gt;Anonyme Funktionen to the rescue!&lt;/p&gt;
&lt;p&gt;Als ich überlegte, wie sich das am einfachsten lösen lässt, versuchte ich, eine normale PHP-Funktion zu definieren, die den Tabellencode enthält, aber da gab es ein Problem.&lt;/p&gt;
&lt;p&gt;Der Code läuft innerhalb einer Klassenmethode. Im Tabellen-Template gibt es Verweise auf &lt;code&gt;$this&lt;/code&gt;. Wenn wir den Code nicht zu sehr ändern wollen, müssten wir &lt;code&gt;$this&lt;/code&gt; als Funktionsargument übergeben. Tja, das funktioniert nicht so ganz, denn &lt;code&gt;$this&lt;/code&gt; kann man nicht als Parameter übergeben 🤷‍♂️.&lt;/p&gt;
&lt;p&gt;Ich war ein bisschen enttäuscht, dass wir einen Haufen im Template umschreiben müssten, und es gab ziemlich viele Verweise, die wir im Blick behalten wollten, damit alles weiter funktioniert.&lt;/p&gt;
&lt;p&gt;Dann fiel mir ein, dass die Seite nicht auf PHP 5.2 läuft, sondern auf PHP 7 und anonyme Funktionen somit unterstützt würden.&lt;/p&gt;
&lt;p&gt;Und die haben dieses praktische Feature, mit dem man festlegen kann, welche Variablen aus dem aufrufenden Scope an die Funktion weitergereicht werden, wenn sie aufgerufen wird. Zum Beispiel:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;php&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$table_function &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ( $pages, $current_page, $items ) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ... Table render code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dadurch kannst du direkt im Funktionskörper auf &lt;code&gt;$pages&lt;/code&gt; oder &lt;code&gt;$items&lt;/code&gt; zugreifen.&lt;/p&gt;
&lt;p&gt;Das Großartige daran: Du kannst auch &lt;code&gt;$this&lt;/code&gt; als Variable in den Funktions-Scope übergeben!&lt;/p&gt;
&lt;p&gt;Jetzt konnten wir den Code zum Rendern der Tabelle komplett in eine separate Funktion auslagern, die wir beim AJAX-Aufruf isoliert aufrufen können!&lt;/p&gt;
&lt;p&gt;Natürlich muss man bei den Variablen im Funktionskörper sehr vorsichtig sein, da sie definiert sein müssen. Man sollte also genau darauf achten, wo die AJAX-Funktion aufgerufen werden kann.&lt;/p&gt;
&lt;p&gt;Für uns bedeutet das, dass wir in der Hauptklasse eine winzige Action hinzufügen, die die Datei weiterhin einbindet, wir aber mehr Kontrolle darüber haben, alle anderen Ausgaben zu unterbinden, die sonst stattfinden würden.&lt;/p&gt;</content:encoded><category>Snippets</category><category>lambda-functions</category><category>php</category><category>WordPress</category></item><item><title>Arduino/ESP32: Den Task-Watchdog deaktivieren</title><link>https://bisko.be/de/posts/dev/arduino-esp32-disabling-the-task-watchdog/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/arduino-esp32-disabling-the-task-watchdog/</guid><description>Kürzlich habe ich ein bisschen mit der Multicore-Funktionalität des ESP32 und dem Pinning von Tasks auf bestimmte Kerne herumgespielt. Ich habe AutoConnect verwendet, um eine WLAN-Verbindung ohne im Code gespeicherte Zugangsdaten zu unterstützen und OTA-Updates über die Web-Oberfläche anzubieten. Das war für ein Projekt, das einige 4-Pin-PWM-CPU-Lüfter steuern sollte, die in</description><pubDate>Wed, 29 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kürzlich habe ich ein bisschen mit der Multicore-Funktionalität des ESP32 und dem Pinning von Tasks auf bestimmte Kerne herumgespielt.&lt;/p&gt;
&lt;p&gt;Ich habe &lt;a href=&quot;https://github.com/Hieromon/AutoConnect&quot;&gt;AutoConnect&lt;/a&gt; verwendet, um eine WLAN-Verbindung ohne im Code gespeicherte Zugangsdaten zu unterstützen und OTA-Updates über die Web-Oberfläche anzubieten.&lt;/p&gt;
&lt;p&gt;Das war für ein Projekt, das einige 4-Pin-PWM-CPU-Lüfter in meinem Serverschrank steuern sollte, um die Luft darin zu kühlen. Dafür wollte ich die Logik auf zwei Tasks aufteilen.&lt;/p&gt;
&lt;p&gt;Ein Task für APIs, Sensorauslesung, Updates, WLAN usw. und ein Task für den Interrupt und die PWM-Steuerung der Lüfter.&lt;/p&gt;
&lt;p&gt;Alles war gut, die Tasks wurden erstellt, aber beim Ausführen des Codes zeigte sich ein seltsames Verhalten, sobald ich den ESP32 in den Modus brachte, in dem man sich mit ihm verbinden muss, um ihm zu sagen, mit welchem WLAN er sich verbinden soll: Er startete alle paar Sekunden den Controller neu, und ich bekam die Verbindung nicht zum Laufen.&lt;/p&gt;
&lt;p&gt;Das war eine nervige Zeit, denn ich musste den Controller von seinem Platz abmontieren und per USB anschließen, um eine neue Firmware zu flashen.&lt;/p&gt;
&lt;p&gt;Nachdem ich das getan hatte, bemerkte ich, dass der Fehler vom Watchdog kam:&lt;/p&gt;
&lt;p&gt;Task watchdog got triggered. The following tasks did not feed the watchdog in time:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;IDLE (CPU 1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Tasks currently running:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CPU 0: ManageTask&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CPU 1: ControllerTask&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Beim Recherchieren stellte sich heraus, dass das vom Task-Watchdog des ESP32 ausgelöst wird, der sicherstellt, dass alle Tasks ihre Rechenzeit auf der CPU bekommen.&lt;/p&gt;
&lt;p&gt;Außerdem schien AutoConnect in einem Task-Kontext nicht besonders flexibel zu sein, verglichen mit der Ausführung außerhalb eines Tasks, direkt zusammen mit dem restlichen Code und den anderen Funktionen.&lt;/p&gt;
&lt;p&gt;Nach etwas Herumstöbern und Ausprobieren scheint der einfachste Ausweg zu sein, den Watchdog einfach zu deaktivieren und zu hoffen, dass alles rechtzeitig ausgeführt wird 🙂 Der Task ist nicht geschäftskritisch, also ist es in Ordnung, wenn er etwas länger braucht, um fertig zu werden.&lt;/p&gt;
&lt;p&gt;Um den Watchdog zu deaktivieren, musst du zwei Dinge tun:&lt;/p&gt;
&lt;p&gt;Erstens: den Header &lt;code&gt;esp_task_wdt.h&lt;/code&gt; einbinden. Füge dazu &lt;code&gt;#include &amp;#x3C;esp_task_wdt.h&gt;&lt;/code&gt; zu deinem Include-Bereich hinzu.&lt;/p&gt;
&lt;p&gt;Zweitens: den Watchdog so einstellen, dass er den Controller nicht zurücksetzt und länger wartet. Dafür musst du &lt;code&gt;esp_task_wdt_init(30, false);&lt;/code&gt; am Anfang deines Task-Codes einfügen.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; manage_core_task&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;pv_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    esp_task_wdt_init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // .... rest of the code ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das setzt das Watchdog-Timeout auf 30 &lt;strong&gt;SEKUNDEN&lt;/strong&gt; und deaktiviert den Controller-Reset, wenn er ausgelöst wird.&lt;/p&gt;
&lt;p&gt;Wenn du möchtest, dass der Controller nach dem Auslösen des Watchdogs trotzdem zurückgesetzt wird, ändere den zweiten Parameter des Funktionsaufrufs von &lt;code&gt;false&lt;/code&gt; auf &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;</content:encoded><category>Uncategorized</category><category>arduino</category><category>code</category><category>esp32</category><category>espressif</category><category>multi-core</category><category>multi-threading</category></item><item><title>Einen YubiKey für das Signieren von Git-Commits einrichten</title><link>https://bisko.be/de/posts/dev/setting-up-a-yubikey-for-git-commit-signing/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/setting-up-a-yubikey-for-git-commit-signing/</guid><description>Ich benutze einen YubiKey als Zwei-Faktor-Authentifizierungs-Schlüssel und um meine Git-Commits zu signieren. Bis vor ein paar Tagen war das ein YubiKey 4. Da mein aktueller Rechner keine USB-A-Anschlüsse hat, habe ich ständig USB-A-auf-USB-C-Adapter in meinem Rucksack herumgeschleppt, und den Key zu benutzen war ein Krampf für das</description><pubDate>Wed, 08 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ich benutze einen YubiKey als &lt;a href=&quot;https://de.wikipedia.org/wiki/Mehr-Faktor-Authentisierung&quot;&gt;Zwei-Faktor-Authentifizierungs&lt;/a&gt;-Schlüssel und um meine Git-Commits zu signieren. Bis vor ein paar Tagen habe ich einen YubiKey 4 benutzt. Da mein aktueller Rechner keine USB-A-Anschlüsse hat, habe ich ständig USB-A-auf-USB-C-Adapter in meinem Rucksack herumjongliert, und den Key zu benutzen war im letzten Jahr ein ziemlicher Krampf. Deshalb habe ich beschlossen, dass es Zeit ist, auf meinen „neuen“ YubiKey 5C umzusteigen, damit ich nicht mehr mit diesen Adaptern hantieren muss.&lt;/p&gt;
&lt;p&gt;Eigentlich habe ich den Key schon eine Weile, denn ich hatte ihn zusammen mit einem Ersatz-YubiKey-4 bestellt, wegen des &lt;a href=&quot;https://www.yubico.com/2017/10/infineon-rsa-key-generation-issue/&quot;&gt;Infineon-TPM&lt;/a&gt;-Problems, das sie damals festgestellt haben. Aber erst jetzt habe ich entschieden, dass es Zeit für den Wechsel auf den neuen Key ist.&lt;/p&gt;
&lt;p&gt;Der andere Grund, es jetzt zu tun: Meine alten GPG-Keys sind abgelaufen und ich musste sie neu ausstellen, also kann ich den Key gleich zum Signieren meiner Git-Commits benutzen.&lt;/p&gt;
&lt;h3 id=&quot;gpg-wahnsinn&quot;&gt;GPG-Wahnsinn&lt;/h3&gt;
&lt;p&gt;Wenn du schon einmal mit GPG-Keys zu tun hattest (oder gerade hast), weißt du, dass es ziemlich schwer sein kann, alles richtig und sicher zum Laufen zu bringen, wenn man es noch nie gemacht hat. Master-Keys offline halten, öffentliche Schlüssel hin- und herschieben, Keys nach dem Ablauf neu ausstellen, sie eventuell mit früheren Keys signieren, um sie zu verifizieren, Keys widerrufen … Selbst in der Theorie ist es nicht leicht, die Best Practices zu befolgen. In der Praxis wird es extrem kompliziert.&lt;/p&gt;
&lt;p&gt;Die meisten Tutorials im Netz sagen, du sollst die CLI zum Erzeugen deiner Keys benutzen, dich durch Menüs mit einem ungewöhnlichen Bedienkonzept hangeln, und generell ist es eine Qual, das alles zum Laufen zu bringen. Die meisten Tutorials empfehlen einen Offline-Rechner wie einen Raspberry Pi und/oder Master-Key und Subkeys offline zu erzeugen und den Master-Key nicht auf deinem Rechner zu lassen.&lt;/p&gt;
&lt;p&gt;🤯&lt;/p&gt;
&lt;p&gt;Damit schlage ich mich jetzt seit fast 4 Jahren jeden Januar herum. Ich fürchte den Moment, in dem ich folgenden Fehler bekomme, der mir sagt, dass meine Signing-Keys abgelaufen sind.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;error: gpg failed to sign the data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;fatal: failed to write commit object&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dieses Jahr habe ich beschlossen, dass es Zeit ist, diesen Prozess deutlich einfacher zu machen und die eingebaute Schlüsselerzeugung zu nutzen, um den ganzen Ärger mit der GPG-Key-Generierung und Co. zu vermeiden.&lt;/p&gt;
&lt;h3 id=&quot;schlüsselerzeugung-direkt-auf-dem-yubikey&quot;&gt;Schlüsselerzeugung direkt auf dem YubiKey&lt;/h3&gt;
&lt;p&gt;Auch hier müssen wir die CLI-Oberfläche benutzen, aber sie ist etwas übersichtlicher, weil es weniger Schritte gibt.&lt;/p&gt;
&lt;p&gt;Zuerst müssen wir unsere Karte bzw. unser Gerät einrichten.&lt;/p&gt;
&lt;h3 id=&quot;einrichtung-von-kartegerät&quot;&gt;Einrichtung von Karte/Gerät&lt;/h3&gt;
&lt;p&gt;Führe &lt;code&gt;gpg --card-status&lt;/code&gt; im Terminal aus und du solltest in etwa Folgendes sehen:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Reader ………..: Yubico Yubikey 4 OTP U2F CCID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Application ID …: &amp;#x3C;Serial number&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Version ……….: 2.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Manufacturer …..: Yubico&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Serial number ….: &amp;#x3C;Device serial number&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Name of cardholder: unspecified&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Language prefs …: en&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Sex …………..: unspecified&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;URL of public key : \[not set\]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Login data …….: &amp;#x3C;e-mail or nothing&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Signature PIN ….: not forced&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Key attributes …: rsa4096 rsa4096 rsa4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Max. PIN lengths .: 127 127 127&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;PIN retry counter : 3 0 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Signature counter : 9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn du etwas Ähnliches siehst und keine Fehler auftauchen, kannst du weitermachen.&lt;/p&gt;
&lt;p&gt;Führe &lt;code&gt;gpg --card-edit&lt;/code&gt; aus.&lt;/p&gt;
&lt;p&gt;Du landest in einer CLI-Oberfläche, die zu Beginn dieselben Informationen anzeigt und unten eine Eingabeaufforderung &lt;code&gt;gpg/card&gt;&lt;/code&gt; hat.&lt;/p&gt;
&lt;p&gt;Tippe &lt;code&gt;admin&lt;/code&gt; und drücke Return/Enter.&lt;/p&gt;
&lt;p&gt;Mit &lt;code&gt;help&lt;/code&gt; kannst du jetzt herausfinden, wie du die Besitzerinformationen und die PINs der Karte änderst.&lt;/p&gt;
&lt;p&gt;Eines &lt;strong&gt;&lt;em&gt;MUSST&lt;/em&gt;&lt;/strong&gt; du tun: die Standard-PINs der Karte ändern. Es gibt zwei davon. Die erste ist die PIN, mit der du auf die Keys auf der Karte zugreifst. Die zweite ist die „Admin“-PIN oder PUK (Personal Unblocking Code).&lt;/p&gt;
&lt;p&gt;Dazu tippst du &lt;code&gt;passwd&lt;/code&gt; und siehst ein Menü:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gpg/card&gt; passwd  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gpg: OpenPGP card no. &amp;#x3C;Serial number&gt; detected&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1 - change PIN  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2 - unblock PIN  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3 - change Admin PIN  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;4 - set the Reset Code  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Q - quit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tippe &lt;code&gt;1&lt;/code&gt; und folge den Anweisungen, um deine PIN zu ändern. Die Standard-PIN ist &lt;code&gt;123456&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Wähle danach &lt;code&gt;3&lt;/code&gt;, um die Admin-PIN zu ändern. Der Standardwert ist &lt;code&gt;12345678&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Wenn beide PINs geändert sind, gehe zurück ins Hauptmenü, um die Key-Informationen fertig zu aktualisieren.&lt;/p&gt;
&lt;p&gt;Die verfügbaren Befehle sind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt; – um den Namen des Karteninhabers zu ändern&lt;/li&gt;
&lt;li&gt;&lt;code&gt;login&lt;/code&gt; – um die E-Mail-Adresse oder den Login des Karteninhabers zu ändern&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Danach können wir mit der eigentlichen Schlüsselerzeugung weitermachen.&lt;/p&gt;
&lt;h3 id=&quot;schlüsselerzeugung&quot;&gt;Schlüsselerzeugung&lt;/h3&gt;
&lt;p&gt;Jetzt ist es Zeit, die Keys tatsächlich zu erzeugen.&lt;/p&gt;
&lt;p&gt;Tippe dazu &lt;code&gt;generate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Du wirst gefragt: &lt;code&gt;Make off-card backup of encryption key? (Y/n)&lt;/code&gt;. Wie in der Dokumentation von YubiKey erwähnt, ist das aber nur ein Schein-Backup und erstellt kein vollständiges Backup der geheimen Schlüssel, daher spielt es keine Rolle, ob du mit &lt;code&gt;Yes&lt;/code&gt; oder &lt;code&gt;No&lt;/code&gt; antwortest. Ich antworte mit &lt;code&gt;No(n)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Falls bereits Keys auf der Karte gespeichert sind, wirst du gefragt, ob du sie ersetzen willst:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gpg: Note: keys are already stored on the card!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Replace existing keys? (y/N)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Stelle sicher, dass du nichts Wichtiges ersetzt, wovon du kein Backup hast, und fahre mit &lt;code&gt;Y&lt;/code&gt; fort. Wenn etwas Wichtiges drauf ist, brich den ganzen Vorgang besser mit &lt;code&gt;Ctrl+C&lt;/code&gt; ab.&lt;/p&gt;
&lt;p&gt;Du wirst nach der Karten-PIN gefragt, die du vorhin gesetzt hast.&lt;/p&gt;
&lt;p&gt;Danach musst du auswählen, wie lange die Keys gültig sein sollen:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Please specify how long the key should be valid.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        0 = key does not expire&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;n&gt; = key expires in n days&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &amp;#x3C;n&gt;w = key expires in n weeks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &amp;#x3C;n&gt;m = key expires in n months&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &amp;#x3C;n&gt;y = key expires in n years&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Key is valid for? (0)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn die Keys nur 1 Jahr gültig sein sollen, tippe &lt;code&gt;1y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Du wirst gebeten, das Ablaufdatum zu bestätigen. Prüfe, ob alles stimmt, und bestätige.&lt;/p&gt;
&lt;p&gt;Danach wirst du aufgefordert, Informationen zum Key-Besitzer einzugeben:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Is this correct? (y/N) y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GnuPG needs to construct a user ID to identify your key.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Real name: &amp;#x3C;Your name&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Email address: &amp;#x3C;Your e-mail&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Comment: &amp;#x3C;Comment is optional&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; You selected this USER-ID:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &quot;&amp;#x3C;Your name&gt; &amp;#x3C;comment&gt; &amp;#x3C;your e-mail&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Type `O` to confirm if everything seems correct.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann wirst du nach deiner Admin-PIN bzw. PUK gefragt. Die wird gebraucht, weil auf die Karte geschrieben wird.&lt;/p&gt;
&lt;p&gt;Wenn alles stimmt, beginnt der YubiKey zu blinken und tut das eine ganze Weile (bei mir etwa fünf Minuten).&lt;/p&gt;
&lt;p&gt;Wenn er fertig ist, siehst du die folgende Meldung:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gpg: key &amp;#x3C;Short ID&gt; marked as ultimately trusted&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;gpg: revocation certificate stored as &apos;/Users/bisko/.gnupg/openpgp-revocs.d/&amp;#x3C;LONG ID&gt;.rev&apos; public and secret key created and signed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notiere dir die &lt;code&gt;&amp;#x3C;Short ID&gt;&lt;/code&gt;, wir brauchen sie später noch.&lt;/p&gt;
&lt;p&gt;An diesem Punkt kannst du die GPG-Eingabeaufforderung mit &lt;code&gt;quit&lt;/code&gt; oder &lt;code&gt;Ctrl+C&lt;/code&gt; verlassen.&lt;/p&gt;
&lt;p&gt;Jetzt ist es Zeit, den öffentlichen Schlüssel zu sichern, damit wir den Key auch auf einem anderen Rechner verwenden können.&lt;/p&gt;
&lt;p&gt;Führe dazu den folgenden Befehl aus:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gpg&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --armor&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Short&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Short&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.asc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das exportiert den öffentlichen Schlüssel in eine Datei namens &lt;code&gt;&amp;#x3C;Short ID&gt;.asc&lt;/code&gt;. Die brauchst du später, wenn du den YubiKey auf einem anderen Rechner nutzen willst oder wenn du deine GPG-Konfiguration verlierst.&lt;/p&gt;
&lt;p&gt;Um den öffentlichen Schlüssel in deinem Schlüsselbund wiederherzustellen, musst du Folgendes tun:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gpg&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --import&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Short&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.asc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gpg:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Short&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; public&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Your Name &amp;#x3C;your@email&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; imported&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gpg:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Total&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; processed:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gpg:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; imported:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ein sehr wichtiger Hinweis.&lt;/em&gt;&lt;/strong&gt; Wenn es eine frische GPG-Installation oder ein anderer Rechner ist, erkennt GPG die Keys auf der Karte nicht von selbst. Du musst &lt;code&gt;gpg --card-status&lt;/code&gt; ausführen, damit GPG die Karte ausliest und die Keys darauf erkennt.&lt;/p&gt;
&lt;h3 id=&quot;git-für-das-signieren-einrichten&quot;&gt;Git für das Signieren einrichten&lt;/h3&gt;
&lt;p&gt;Damit Git deine Commits signiert, musst du Folgendes zu deiner &lt;code&gt;~/.gitconfig&lt;/code&gt; hinzufügen.&lt;/p&gt;
&lt;p&gt;Im Abschnitt &lt;code&gt;[user]&lt;/code&gt; musst du die folgende Zeile hinzufügen (oder aktualisieren):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;signingkey = 0x&amp;#x3C;Short ID&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Wenn du alle deine Commits signieren willst, füge am Ende der Datei Folgendes hinzu:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;[gpg]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  program&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; = /usr/local/bin/gpg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;[commit]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  gpgsign&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; = true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damit signiert Git alle deine Commits.&lt;/p&gt;
&lt;p&gt;Um GitHub einzurichten, musst du deinen öffentlichen Schlüssel zu deinem Profil hinzufügen. Gehe dazu auf &lt;code&gt;GitHub -&gt; Settings -&gt; SSH and GPG keys -&gt; New GPG key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dann siehst du ein Textfeld, in das du den gesamten Inhalt der oben erzeugten Datei &lt;code&gt;&amp;#x3C;Short ID&gt;.asc&lt;/code&gt; einfügen musst.&lt;/p&gt;
&lt;p&gt;Wenn du den Inhalt der Datei kopieren willst (unter macOS), kannst du das hier tun:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cat &amp;#x3C;Short ID&gt;.asc | pbcopy&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Das kopiert den Inhalt der ganzen Datei in die Zwischenablage.&lt;/p&gt;
&lt;p&gt;Füge ihn in das Textfeld auf GitHub ein und klicke auf den Button &lt;code&gt;Add GPG key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Danach kannst du einen Commit machen und zu GitHub pushen, und du solltest das hübsche &lt;code&gt;Verified&lt;/code&gt;-Label sehen.&lt;/p&gt;
&lt;h3 id=&quot;debugging&quot;&gt;Debugging&lt;/h3&gt;
&lt;p&gt;Manchmal klappt nicht gleich alles. Um mehr Informationen zu sammeln, kannst du Folgendes versuchen:&lt;/p&gt;
&lt;h3 id=&quot;signieren-mit-gpg&quot;&gt;Signieren mit GPG&lt;/h3&gt;
&lt;p&gt;Versuche zuerst, mit dem Key etwas zu signieren:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gpg -s &amp;#x3C;file&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Wenn das fehlschlägt, versuche herauszufinden, warum. Ich bin kein Experte und kann da nicht weiterhelfen.&lt;/p&gt;
&lt;p&gt;Sieh dir die Ausgabe von Git anGIT_TRACE=1 git commit -am “test”&lt;/p&gt;
&lt;p&gt;Das zeigt dir genau, was Git tut, während es versucht, den Commit durchzuführen und zu signieren. Es gibt dir einen Hinweis darauf, warum das Signieren fehlschlagen könnte.&lt;/p&gt;
&lt;p&gt;Daran kannst du auch sehen, dass Git den folgenden Befehl ausführt:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;/usr/local/bin/gpg&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --status-fd=2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -bsau&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Key&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Du kannst versuchen, ihn manuell auszuführen, um vielleicht eine aussagekräftigere Fehlermeldung zu bekommen.&lt;/p&gt;</content:encoded><category>Snippets</category><category>Technology</category><category>git</category><category>github</category><category>gpg</category><category>key</category><category>public-key</category><category>secrets</category><category>sign</category><category>yubikey</category></item><item><title>e1000e  eth0: Detected Hardware Unit Hang</title><link>https://bisko.be/de/posts/dev/e1000e-device-id-eth0-detected-hardware-unit-hang/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/e1000e-device-id-eth0-detected-hardware-unit-hang/</guid><description>Vor Kurzem hat mein Heimserver und VM-Host angefangen, zufällig die Netzwerkverbindung zu verlieren. Von außen sieht es so aus, als würde er noch laufen, aber ich kam auf keinem Weg mehr aus der Ferne an ihn heran. Der Ethernet-Adapter war laut Switch eingeschaltet, also musste das Problem irgendwo in der Software liegen. Es wäre nicht</description><pubDate>Wed, 18 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Vor Kurzem hat mein Heimserver und VM-Host angefangen, zufällig die Netzwerkverbindung zu verlieren. Von außen sieht es so aus, als würde er noch laufen, aber ich kam auf keinem Weg mehr aus der Ferne an ihn heran. Der Ethernet-Adapter war laut Switch eingeschaltet, also musste das Problem irgendwo in der Software liegen.&lt;/p&gt;
&lt;p&gt;Es wäre nicht das erste Mal, dass ein Treiber für eine hängende Netzwerkverbindung verantwortlich ist. In der Vergangenheit haben mich schon fehlerhafte WLAN-Treiber unter Linux und Windows geärgert.&lt;/p&gt;
&lt;p&gt;Nachdem ich ein bisschen in den Systemlogs gegraben hatte, bin ich auf Folgendes gestoßen:&lt;/p&gt;
&lt;p&gt;vmhost kernel: e1000e 0000:00:1f.6 eth0: Detected Hardware Unit Hang:&lt;br&gt;
vmhost kernel:   TDH                  &amp;#x3C;0&gt;&lt;br&gt;
vmhost kernel:   TDT                  &amp;#x3C;1&gt;&lt;br&gt;
vmhost kernel:   next_to_use          &amp;#x3C;1&gt;&lt;br&gt;
vmhost kernel:   next_to_clean        &amp;#x3C;0&gt;&lt;br&gt;
vmhost kernel: buffer_info[next_to_clean]:&lt;br&gt;
vmhost kernel:   time_stamp           &amp;#x3C;10fbc2f81&gt;&lt;br&gt;
vmhost kernel:   next_to_watch        &amp;#x3C;0&gt;&lt;br&gt;
vmhost kernel:   jiffies              &amp;#x3C;10fbc3871&gt;&lt;br&gt;
vmhost kernel:   next_to_watch.status &amp;#x3C;0&gt;&lt;br&gt;
vmhost kernel: MAC Status             &amp;#x3C;40080083&gt;&lt;br&gt;
vmhost kernel: PHY Status             &amp;#x3C;796d&gt;&lt;br&gt;
vmhost kernel: PHY 1000BASE-T Status  &amp;#x3C;7800&gt;&lt;br&gt;
vmhost kernel: PHY Extended Status    &amp;#x3C;3000&gt;&lt;br&gt;
vmhost kernel: PCI Status             &amp;#x3C;10&gt;&lt;br&gt;
vmhost kernel: e1000e 0000:00:1f.6 eth0: Reset adapter unexpectedly&lt;br&gt;
vmhost kernel: vmbr0: port 1(eth0) entered disabled state&lt;/p&gt;
&lt;p&gt;Danach setzt er den Netzwerkadapter zurück und macht nach einer Weile wieder dasselbe, bis die Maschine komplett offline geht.&lt;/p&gt;
&lt;p&gt;Bei der Suche nach Antworten im Netz bin ich auf &lt;a href=&quot;https://serverfault.com/questions/616485/e1000e-reset-adapter-unexpectedly-detected-hardware-unit-hang&quot;&gt;diesen ServerFault-Thread&lt;/a&gt; gestoßen.&lt;/p&gt;
&lt;p&gt;Ursache&lt;/p&gt;
&lt;p&gt;Nach dem Lesen verschiedener Quellen und Bug-Reports scheint der beste Weg, das Problem zu reproduzieren, eine Situation mit hoher Bandbreite auf dem Gerät zu sein, also etwa das Streamen großer Datenmengen, die die Schnittstelle auslasten.&lt;/p&gt;
&lt;p&gt;Bei mir passierte es meistens, wenn ich Medien vom lokalen Plex-Server auf ein Gerät streame. Wegen der Art, wie das Netzwerk aufgebaut ist, muss die Windows-VM, auf der die Plex-Instanz läuft, die Mediendatei von einer NFS-Freigabe auf einem separaten Gerät holen, in der VM transkodieren und sie dann an das Wiedergabegerät schicken.&lt;/p&gt;
&lt;p&gt;Das summiert sich zu einer Menge Netzwerkverkehr, meist ~40–100 Mbit/s, je nach Wiedergabegerät und Qualität der Quelldatei.&lt;/p&gt;
&lt;p&gt;Dasselbe Problem trat auch beim Streamen von Spielen per Steam Link auf unseren Apple TV auf. Die Verbindung ist kabelgebunden, aber es ist nicht ungewöhnlich, dass das Netzwerk abbricht. Ich vermute, dass es mit demselben Problem zusammenhängt, werde aber ein Auge darauf haben, ob es nach dem Fix in Zukunft noch passiert.&lt;/p&gt;
&lt;p&gt;Möglicher Fix&lt;/p&gt;
&lt;p&gt;Ein möglicher Fix scheint zu sein, &lt;strong&gt;GSO&lt;/strong&gt; &lt;em&gt;(Generic Segmentation Offload)&lt;/em&gt;, &lt;strong&gt;TSO&lt;/strong&gt; &lt;em&gt;(TCP Segmentation Offload)&lt;/em&gt; und &lt;strong&gt;GRO&lt;/strong&gt; &lt;em&gt;(Generic Receive Offload)&lt;/em&gt; auf der Netzwerkschnittstelle zu deaktivieren*:&lt;/p&gt;
&lt;p&gt;ethtool -K eth0 gso off gro off tso off&lt;/p&gt;
&lt;p&gt;Ich habe das bei mir angewendet und warte nun ab, ob es das Problem auf lange Sicht wirklich löst.&lt;/p&gt;
&lt;p&gt;Fußnoten&lt;/p&gt;
&lt;p&gt;* Diese Optionen betreffen das Auslagern der Paketsegmentierung an den Netzwerk-Controller, um die CPU-Last auf der Maschine zu verringern. Mehr Details gibt es in &lt;a href=&quot;https://en.wikipedia.org/wiki/Large_send_offload&quot;&gt;diesem Wikipedia-Artikel&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Homelab</category><category>bandwidth</category><category>bug</category><category>network</category><category>nic</category><category>plex</category><category>proxmox</category><category>steam</category><category>streaming</category></item><item><title>Snippets: Eine lokale/private Docker-Image-Registry für den Swarm betreiben</title><link>https://bisko.be/de/posts/dev/snippets-running-a-local-private-swarm-docker-image-registry/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/snippets-running-a-local-private-swarm-docker-image-registry/</guid><description>Heute wollte ich aus einem Node.js-Projekt ein Docker-Image erzeugen und es auf meinem lokalen Test-Swarm deployen. Leider wird ein lokal gebautes Docker-Image nur auf dem Node gespeichert, auf dem es erstellt wurde, und die anderen Swarm-Nodes können nicht darauf zugreifen. Die</description><pubDate>Fri, 11 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Heute wollte ich aus einem Node.js-Projekt ein Docker-Image erzeugen und es auf meinem lokalen Test-Swarm deployen.&lt;/p&gt;
&lt;p&gt;Leider wird ein lokal gebautes Docker-Image nur auf dem Node gespeichert und ist auch nur dort verfügbar, auf dem es erstellt wurde. Die anderen Swarm-Nodes kommen nicht heran.&lt;/p&gt;
&lt;p&gt;Die Lösung: das Image in eine Docker-Registry pushen, aus der es dann alle Nodes im Swarm pullen können.&lt;/p&gt;
&lt;p&gt;Die Registry erstellen&lt;/p&gt;
&lt;p&gt;Um einen Registry-Service im Swarm zu starten, führe Folgendes aus:&lt;/p&gt;
&lt;p&gt;docker service create —name registry —publish 5000:5000 registry:latest&lt;/p&gt;
&lt;p&gt;Das erstellt den Registry-Service und lässt ihn im Swarm laufen, sodass er für alle Nodes im Swarm erreichbar ist.&lt;/p&gt;
&lt;p&gt;Ein Image in die Registry pushen&lt;/p&gt;
&lt;p&gt;Um ein Image in die Registry zu pushen, musst du zwei Dinge tun – das Image taggen und dann pushen.&lt;/p&gt;
&lt;p&gt;Hier ein Beispiel, wie man das Image in einem Rutsch baut und taggt:&lt;/p&gt;
&lt;p&gt;docker build . -t localhost.localdomain:5000/&lt;image-name&gt;:latest&lt;/image-name&gt;&lt;/p&gt;
&lt;p&gt;Und so pusht man es in die Registry:&lt;/p&gt;
&lt;p&gt;docker push localhost.localdomain:5000/&lt;image-name&gt;:latestDas Image in einem Service/Container/etc. verwenden&lt;/image-name&gt;&lt;/p&gt;
&lt;p&gt;Um das Image in einem Service oder Container zu verwenden, gibst du den vollständigen Pfad von oben an, also &lt;code&gt;localhost.localdomain:5000/&amp;#x3C;image-name&gt;:latest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Die Swarm-Nodes haben dann Zugriff auf das Image und können es pullen und ausführen.&lt;/p&gt;
&lt;p&gt;Wichtiger Hinweis zur Registry-Adresse&lt;/p&gt;
&lt;p&gt;In den meisten Tutorials im Netz wird die Registry-URL als &lt;code&gt;localhost:5000&lt;/code&gt; angegeben. Leider funktioniert das nicht, und meistens läuft die Verbindung in einen Timeout. Wenn wir das zu &lt;code&gt;localhost.localdomain&lt;/code&gt; ändern, klappt es!&lt;/p&gt;
&lt;p&gt;Keine Ahnung, warum das passiert, wo doch sowohl &lt;code&gt;localhost&lt;/code&gt; als auch &lt;code&gt;localhost.localdomain&lt;/code&gt; zu &lt;code&gt;127.0.0.1&lt;/code&gt; aufgelöst werden.&lt;/p&gt;</content:encoded><category>Homelab</category><category>Snippets</category><category>Technology</category><category>docker</category><category>docker-swarm</category><category>registry</category><category>swarm</category></item><item><title>Snippets: Die Apple-Tastatur-Taste „Paragraphzeichen“ auf Backquote umbelegen ( § zu ` )</title><link>https://bisko.be/de/posts/dev/snippets-map-apple-keyboard-section-sign-key-to-back-quote-%C2%A7-to/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/snippets-map-apple-keyboard-section-sign-key-to-back-quote-%C2%A7-to/</guid><description>Ich benutze schon eine Weile Apple-Tastaturen, aber wenn man in Europa lebt, ist es nicht leicht, die US-Layout-Varianten zu bekommen, die ich gewohnt bin. Unter macOS gibt es einen „einfachen“ Weg, die Tastatur mit nur einem Terminal-Befehl umzubelegen: watch -n1 -x hidutil property -m ‘{“ProductID”:592, “VendorID”:1452}’ –set ‘{“UserKeyMapping”:[{“HIDKeyboardModifierMappingSrc”:0x700000035,”HIDKeyboardModifierMappingDst”:0x700000064}]}’ Was dieser</description><pubDate>Wed, 31 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ich benutze schon eine Weile Apple-Tastaturen, aber wenn man in Europa lebt, ist es nicht leicht, die US-Layout-Varianten zu bekommen, die ich gewohnt bin.&lt;/p&gt;
&lt;p&gt;Unter macOS gibt es einen „einfachen“ Weg, die Tastatur mit nur einem Terminal-Befehl umzubelegen:&lt;/p&gt;
&lt;p&gt;watch -n1 -x hidutil property -m ’{“ProductID”:592, “VendorID”:1452}’ —set ’{“UserKeyMapping”:[{“HIDKeyboardModifierMappingSrc”:0x700000035,“HIDKeyboardModifierMappingDst”:0x700000064}]}’&lt;/p&gt;
&lt;p&gt;Dieses Stück Code ändert die Belegung der Paragraphzeichen-Taste ( § ), sodass sie stattdessen die Backquote-/Tilde-Taste ( &lt;code&gt;`/ ~&lt;/code&gt; ) ausgibt.&lt;/p&gt;
&lt;p&gt;Der Teil &lt;code&gt;watch -n1 -x&lt;/code&gt; führt das jede Sekunde aus, weil macOS die Einstellung manchmal verliert, meist wenn der Computer in den Ruhezustand geht oder die Tastatur ab- und wieder angesteckt wird.&lt;/p&gt;
&lt;p&gt;Beachte bitte, dass das Hilfsprogramm &lt;code&gt;watch&lt;/code&gt; bei manchen macOS-Versionen nicht installiert ist und über etwas wie &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; oder &lt;a href=&quot;https://www.macports.org/&quot;&gt;MacPorts&lt;/a&gt; nachinstalliert werden muss.&lt;/p&gt;
&lt;p&gt;Der obige Code funktioniert mit der externen Apple-Tastatur mit USB und europäischem Layout mit bulgarischen Buchstaben. Bei anderen Tastaturtypen müssen die Hex-Werte der Tasten eventuell leicht angepasst werden.&lt;/p&gt;
&lt;p&gt;Eine Variante des Befehls funktioniert gut für denselben Tastaturtyp am MacBook Pro selbst. Dazu musst du nur die Positionen der Werte &lt;code&gt;0x700000035&lt;/code&gt; und &lt;code&gt;0x700000064&lt;/code&gt; vertauschen.&lt;/p&gt;
&lt;p&gt;Ich habe schon überlegt, ein Tool zu schreiben, das das automatisch für mich erledigt, aber im Moment denke ich, dass es sich mehr lohnt, in eine neue Tastatur mit dem richtigen Layout zu investieren 🙂&lt;/p&gt;</content:encoded><category>Uncategorized</category></item><item><title>Apple-TV-Fernbedienung zurücksetzen/neu starten</title><link>https://bisko.be/de/posts/dev/resetting-restarting-apple-tv-remote/</link><guid isPermaLink="true">https://bisko.be/de/posts/dev/resetting-restarting-apple-tv-remote/</guid><description>Gestern Abend, während eines Gästebesuchs, habe ich es geschafft, unsere Apple-TV-Fernbedienung unter Wasser zu tauchen. Schlafmangel und wackelige Gläser führen eben zu Unfällen. Die Fernbedienung funktionierte gestern Abend noch einwandfrei, aber heute hat sie den Dienst quittiert. Sie reagiert auf keinerlei Eingaben. Ich habe versucht, sie gegen meine Hand zu schlagen und das Wasser herauszuschütteln. Es</description><pubDate>Sun, 17 Feb 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Gestern Abend, während eines Gästebesuchs, habe ich es geschafft, unsere Apple-TV-Fernbedienung unter Wasser zu tauchen. Schlafmangel und wackelige Gläser führen eben zu Unfällen.&lt;/p&gt;
&lt;p&gt;Die Fernbedienung funktionierte gestern Abend noch einwandfrei, aber heute hat sie den Dienst quittiert. Sie reagiert auf keinerlei Eingaben. Ich habe versucht, sie gegen meine Hand zu schlagen und das Wasser herauszuschütteln. Es hat überhaupt nichts gebracht.&lt;/p&gt;
&lt;p&gt;Wir dachten, sie sei hinüber, und suchten schon in den Schränken nach der Reispackung.&lt;/p&gt;
&lt;p&gt;Ich ging online, größtenteils aus Spaß, um zu schauen, ob ich versuchen kann, sie „neu zu starten“.&lt;/p&gt;
&lt;p&gt;Eine hilfreiche Anleitung riet mir, die Tasten Lauter und Menü 2–3 Sekunden lang gedrückt zu halten, um die Fernbedienung zurückzusetzen und in den Kopplungsmodus zu versetzen.&lt;/p&gt;
&lt;p&gt;Ich war echt überrascht, als es &lt;strong&gt;tatsächlich&lt;/strong&gt; &lt;strong&gt;funktioniert hat&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Wenn also etwas faul zu sein scheint, versucht zuerst, die Fernbedienung zurückzusetzen. Wenn das nicht klappt, könnt ihr es immer noch mit Reis und einem Eingriff an der Hardware probieren.&lt;/p&gt;
&lt;p&gt;TL;DR;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Menü + Lauter 2–3 Sekunden lang gedrückt halten&lt;/li&gt;
&lt;li&gt;Ein paar Sekunden warten&lt;/li&gt;
&lt;li&gt;Versuchen, mit dem Apple TV zu interagieren&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Apple</category><category>Technology</category><category>AppleTV</category><category>Have you tried turning it off and on again?</category><category>remote</category><category>reset</category><category>restart</category></item></channel></rss>