y0o.de · GNU/Linux Nachrichten u.Ä.

🔒
❌ Über y0o.de
Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.
Ältere BeiträgeKoflers Blog

Farb-PDFs in Graustufen-PDFs umwandeln

09. Juni 2021 um 17:05

Kürzlich musste ich einige Tickets ausdrucken, die großflächig mit Farbe hinterlegt waren. Der Treiber meines Drucker bietet leider keine Möglichkeit, ein Dokument in Graustufen auszudrucken. Und der Farbdruck vergeudet eine Menge Tinte/Toner. Also habe ich nach einem Weg gesucht, Farb-PDFs in Graustufen-PDFs umzuwandeln. Und siehe da: Was Linux an Benutzerkomfort vermissen lässt, ersetzt es durch tolle Kommandos :-)

Variante 1: convert

Den bequemsten Weg bietet das Kommando convert aus dem Paket ImageMagick (apt/dnf install imagemagick). Mit den Optionen -quality und -density steuern Sie gleichzeitig die Qualität und Größe der resultierenden PDFs. Einen guten Kompromiss bietet:

convert -colorspace GRAY -density 300 -quality 95 in-color.pdf  out-grey.pdf

Noch schärfer wird der Ausdruck so:

convert -colorspace GRAY -density 400 -quality 100 Tickets-color.pdf  Tickets-grey.pdf

Die resultierende Datei ist dann aber auch entsprechend größer.

Bei vielen Distributionen weigert sich convert, PDFs zu verarbeiten, und liefert die folgende Fehlermeldung:

convert-im6.q16: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/421.
convert-im6.q16: no images defined `Tickets-grey.pdf' @ error/convert.c/ConvertImageCommand/3229.

Abhilfe schafft die Entfernung der entsprechenden Zeile aus /etc/ImageMagick-6/policy.xml. Im folgenden Listing habe ich die Zeile auskommentiert:

<policymap>
  ...
  <!-- <policy domain="coder" rights="none" pattern="PDF" /> -->
  ...
</policymap>

Variante 2: gs

Mit mehr Tippaufwand ist das zweite Kommando verbunden:

gs -sOutputFile=out-grey.pdf \
 -sDEVICE=pdfwrite \
 -sColorConversionStrategy=Gray \
 -dProcessColorModel=/DeviceGray \
 -dCompatibilityLevel=1.4 \
 -dNOPAUSE -dBATCH in-color.pdf

Die Qualität ist ähnlich wie bei convert -density 400 -quality 100. Die Rechenzeit ist deutlich höher, dafür ist die Dateigröße spürbar kleiner.

Quelle

https://superuser.com/questions/104656/convert-a-pdf-to-greyscale-on-the-command-line-in-floss

Fedora 34

28. April 2021 um 20:28

phoronix, heise.de und derstandard.at sind sich einig: Mit Version 34 ist Fedora ein großer Wurf gelungen. Tatsächlich gibt es diesmal Neuerungen, die ins Auge stechen und die zu hören sind: Als erste große Distribution liefert Fedora Gnome 40 auf und verwendet PipeWire als Audio-Framework. Wayland ist bei Fedora schon lange standardmäßig aktiv, aber erstmals gilt dies nun auch für den KDE-Zweig. Das Dateisystem btrfs wird jetzt standardmäßig komprimiert. Kurzum: Fedora gewährt wieder einmal einen Blick in die Linux-Zukunft.

Gnome 40

Mit Gnome 40, dem Nachfolger von Gnome 3.38, ändert sich nicht nur die Versionsnummer. Das Gnome-Projekt hat bei der Gelegenheit auch gleich eine Menge Neuerungen am Desktop durchgeführt, über die ich mich in Fluch und Segen von Gnome gerade ausgelassen habe. Die Kurzfassung: Ich finde die Optik großartig, vermisse aber zwei, drei Konfigurationsmöglichkeiten … Wenn ich auf einem großen Monitor arbeite, will ich das Dock ständig sehen, und zwar auf der linken Seite. Es ist nicht notwendig, dass dies wie unter Ubuntu die Default-Einstellung ist, aber ich fühle mich bevormundet, wenn ich diesbezüglich nicht wenigstens eine Wahlmöglichkeit habe.

Das ganzes Lamento hat mit Fedora natürlich wenig zu tun. Fedora liefert einfach den neuesten Gnome-Desktop so aus, wie die Gnome-Entwickler ihn gerade zur Verfügung stellen. Das ist ein einfacher, pragmatischer Ansatz, der diesbezüglich keine Zeit verschwendet.

Das Hintergrundbild von Fedora 34 ist so schön, dass man gar keine Fenster öffnen will.

PipeWire

PipeWire ist ein Server für Audio- und Video-Streams. Im Audio-Bereich soll PipeWire längerfristig PulseAudio ablösen. Ein Vorteil von PipeWire sind offensichtlich geringere Latenzen, aber aus eigener Erfahrung kann ich das nicht beurteilen. Gleichzeitig stellt PipeWire ein Framework zur Verfügung, das sicheres Screen Sharing bzw. Remote-Desktop-Anwendungen unter Wayland möglich macht. Schon alleine aus diesem Grund wird in der Zukunft wohl kein Weg an PipeWire vorbei gehen.

Fedora ist die erste große Distribution, die standardmäßig PulseAudio durch PipeWire ersetzt. Diese Vorreiterrolle nahm Fedora auch schon bei PulseAudio ein (Fedora 8, 2007). Die Begeisterung der Anwender hielt sich damals in Grenzen, PulseAudio war noch nicht ausgereift und verursachte viele Probleme. Dennoch etablierte PulseAudio später auch in anderen Distributionen als Audio-Standard.

Es ist zu hoffen, dass PipeWire nicht ähnliche Probleme verursacht. Bei meinen Tests ist mir nichts aufgefallen. Wenn ich nicht aus dem Studium der Release Notes wüsste, dass sich Fedora für ein neues Audio-Backend entschieden hat, hätte ich PipeWire gar nicht bemerkt. Das ist einer Kompatibilitätsschicht zu verdanken (Paket pipewire-pulseaudio). Echte Vorteile bietet PipeWire für Programme, die die JACK API nutzen (JACK Audio Connection Kit). Derartige Programme sollten jetzt auf Anhieb und ohne Konfigurationsarbeiten funktionieren.

Spannende Hintergrundinformationen bei der Analyse des Audio-Systems gibt pw-top. Es listet alle aktiven Audio-Komponenten samt Latenzzeiten auf.

Das Kommando fw-top gibt Informationen zum PipeWire-Status

btrfs

Fedora verwendet wie schon in Version 33 standardmäßig das Dateisystem btrfs. Dabei werden zwei Subvolumes für /root und /home eingerichtet. Neu in Version 34 ist die Aktivierung der Kompressionsfunktionen (compress=zstd). Dadurch werden Dateien, die sich leicht komprimieren lassen, automatisch komprimiert. Das bringt mehr, als man erwarten würde:

compsize -x /

Processed 147674 files, 97366 regular extents (106279 refs), 76200 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       57%      3.3G         5.8G         6.4G       
none       100%      2.0G         2.0G         1.9G       
zstd        35%      1.3G         3.8G         4.4G       
prealloc   100%      2.8M         2.8M          20M 

Die obigen Daten stammen von einer Standardinstallation von Fedora 34 mit wenigen Dateien in /home (sprich: von einer Testinstallation). Bei Dateien um Umfang von 2,0 GB hat btrfs auf die Komprimierung verzichtet. Weitere 3,8 GB wurden komprimiert, die Ersparnis betrug dabei fast 2,5 GB (also 3,8 minus 1,3).

Versionsnummern

Basis             Desktop             Programmierung   Server
---------------   ------------------  --------------   --------------
Kernel     5.11   Gnome          40   bash       5.1   Apache     2.4
glibc      2.33   Firefox        88   gcc         11   CUPS       2.3
X-Server   1.20   Gimp         2.10   Java     11/16   MariaDB   10.5
Wayland    1.19   LibreOffice   7.1   PHP        7.4   OpenSSH    8.5
Mesa         21   Thunderbird    78   Python     3.9   qemu/KVM   5.2
Systemd     248                                        Postfix    3.5
NetworkMan 1.30                                        Samba     4.14
GRUB       2.04 

Quellen / Links

Tests

Gnome 40

Pipewire

btrfs

Fluch und Segen von Gnome

28. April 2021 um 18:32

Mit Gnome 40, dem Nachfolger von Gnome 3.38, ändert sich nicht nur die Versionsnummer. Das Gnome-Projekt hat bei der Gelegenheit auch gleich eine Menge Neuerungen am Desktop durchgeführt. Soviel vorweg: Die Optik ist großartig! (Der Eindruck wird durch den wunderschönen Fedora-34-Hintergrund noch verstärkt.)

Aktivitäten

Genaugenommen sind die Neuerungen in Version 40 gar nicht so spektakulär:

  • Das Dock wandert von der linken Seite nach unten — also dorthin, wo es sich auch unter Windows, macOS und am iPad befindet.
  • Wenn es mehrere virtuelle Bildschirme (Workspaces) gibt, werden diese nebeneinander angeordnet (nicht mehr untereinander). Diesbezüglich steht wohl macOS Pate.

  • Auf einem Touchpad können Sie mit drei Fingern zwischen den Workspaces wechseln bzw. die Aktivitäten-Ansicht ein- oder ausblenden (wie in macOS). Noch schneller gelingt der Workspace-Wechsel mit dem Mausrad. Die selben Aufgaben erledigen schließlich die Tastenkombinationen Windows+Alt+Cursor links/rechts/oben/unten.

  • In der Grid-Ansicht können die installierten Programme (»Apps«) mühelos neu angeordnet oder in Gruppen zusammengefasst werden (wie auf vielen Tablets).

Grundsätzlich sind all diese Neuerungen durchdacht und vernünftig. Unverändert bleibt übrigens die Dock-Sichtbarkeit: Das Dock wird nur angezeigt, wenn Sie Aktivitäten anklicken oder die Windows-Taste drücken.

App-Grid

Wir wissen, was gut für dich ist!

Vermutlich liegt es in der Natur des Menschens, auf Änderungen zuerst einmal mit Skepsis und Widerwillen zu reagieren. Und vielleicht ist dieser Blog-Artikel einfach nur ein Ausdruck dieser Änderungs-Resistenz?

Mein Problem mit Gnome 40 ist (wie schon mit früheren Gnome-Versionen) die fehlende Wahlmöglichkeit. Mein Notebook ist sicher zu 90% der Nutzungszeit mit einem 28-Zoll-Monitor verbunden. Dieser bietet genug Platz, um das Dock ständig anzuzeigen und ICH WILL ES SO. Außerdem wünsche ich mir das Dock auf der linken Seite. Ubuntu ist per Default so konfiguriert, und bei anderen Distributionen installiere ich eben die Erweiterung Dash to Dock. In Gnome 40 bleibt dieser Ausweg verschlossen — Dash to Dock und Gnome 40 sind vorerst inkompatibel zueinander.

Windows und macOS verhalten sich per Default ähnlich wie Gnome. ABER: Beide Betriebssysteme geben mir die Freiheit, das Dock mit wenigen Mausklicks so zu konfigurieren, wie ich es haben will. Nur Gnome nicht. Die Gnome-Entwickler wissen, was gut für mich ist, da braucht es keine Wahlmöglichkeit.

Ich bin nicht vor mehr als 25 Jahren zu Linux gewechselt, damit mir Gnome vorschreibt, wie ich meinen Desktop organisieren soll. (Den Einwand, ich hätte ja mit KDE, XFCE usw. reichlich Auswahl, lasse ich hier nicht gelten. Ich bin mit Gnome weitestgehend zufrieden. Ich betrachte es als das beste, ausgereifteste Desktop-System, das Linux aktuell bietet, auf jeden Fall als den besten Kompromiss. Was nützt mir ein anderes Desktop-System, das mir mehr Dock-Flexibilität gibt, aber das dafür sonst voller Fehler und Mängel ist?)

Was mein Dock-Problem betrifft, kann ich natürlich darauf warten, bis Dash to Dock eine Gnome-40-kompatible Version ihrer großartigen Shell Extension fertigstellt. Oder bis es eine Alternative dazu gibt. (Meine aktuelle Notlösung ist Floating Dock.) Zur Not könnte ich versuchen, selbst eine geeignete Shell Extension zu programmieren — aber ich gebe zu, dazu fehlt mir die Zeit und das JavaScript-Know-how.

Warum sind Shell Extensions überhaupt notwendig, um vollkommen elementare Grundfunktionen zu realisieren? Funktionen, die gefühlt jedes Desktop-System selbstverständlich anbietet, nur nicht Gnome? Shell Extensions sind aus meiner Sicht eher Hacks als Lösungen. Jedes Gnome-Update führt zu neuen Problemen und Inkompatibilitäten. Viele Extensions haben nur eine recht kurze Lebensdauer, bis sich ihre Entwickler neuen Zielen zuwenden.

Und weil ich schon im Mecker-Modus bin: Wie wäre es, die Module des Programms Einstellungen alphabetisch zu ordnen? Ich kann in der vorliegenden Ordnung keine wie auch immer geartete Logik erkennen. Letztlich scrolle ich immer wieder von oben nach unten, bis ich die Audio-Einstellungen dann finde. (Tipp: Sie sind irgendwo in der Mitte, zwischen Freigabe-Einstellungen und Energiespar-Optionen …) Insofern wäre alphabetisch immer noch besser als gar keine Ordnung.

Einstellungen

Und noch ein Punkt für die Gnome-Wunschliste: Warum kann Gnome Fenster nicht unkompliziert in Bildschirm-Vierteln anzuordnen? Nein, Bildschirm-Hälften sind auf einem großen Monitor zu wenig. Ja, ich weiß, die Lösung heißt Windows. Das ist ein Satz, den ich normalerweise nicht ausspreche/schreibe … (Oder es muss wieder eine Shell Extension her: Ich kann z.B. den Tiling Assistant empfehlen.)

Die Konsequenzen

Natürlich kann niemand kann den Gnome-Entwicklern vorschreiben, in welche Richtung sie ihr Projekt weiterentwickeln. Aber die oft überraschenden, eigenwilligen Design-Entscheidungen irritieren nicht mich alleine. Sie führen dazu, dass Ubuntu das Gnome-40-Update vorerst nicht mitmacht, dass jetzt auch Pop!OS den Desktop neu erfinden will, dass es mit Elementary, Cinnamon, Mate sowieso schon ein Dutzend Varianten gibt, die in Wirklichkeit (fast) keiner haben will. Deren Daseinsberechtigung sich durch einige Details ergibt, die sich außerhalb des Gnome-Universums offenbar einfacher realisieren lassen als innerhalb. Die in einem sinnlosen Ausmaß Entwickler-Ressourcen binden. Die nicht fertig werden. Zu denen es schon bald keine Updates mehr geben wird.

Linux braucht Standards, um erfolgreich zu sein. Nicht alle wollen es wahr haben, aber Gnome ist dieser Standard im Desktop-Bereich. Natürlich gibt es Alternativen, aber die meisten Linux-Einsteiger beginnt mit Gnome. Firmen setzen auf Gnome und lassen Alternativen oft gar nicht zu.

Hinzu kommt: Gnome ist prinzipiell eine ausgezeichnete Desktop-Umgebung. Ich bin sogar mit dem Gnome-Konzept »Weniger ist mehr« einverstanden. Ich verstehe die Logik: Weniger Optionen sind übersichtlicher, einfacher zu bedienen, besser wartbar. Ich vertrete dieses Motto in Projekten, an denen ich arbeite, selbst.

Aber ich finde, Gnome übertreibt. Es gäbe sicherlich weniger Fragmentierung im Desktop-Bereich, wenn Gnome ein wenig mehr Flexibilität bieten könnte. Der Ansatz One size fits all funktioniert einfach nicht. Es braucht nicht für jede Option 1000 Einstellmöglichkeiten (-> KDE). Dennoch kann man den Anwendern ein paar Einstellmöglichkeiten lassen. Den Status Quo empfinde ich und empfinden offenbar auch andere als eine Bevormundung, die verärgert, frustriert und dazu führt, dass es unter Linux mehr Desktop-Systeme als Mail-Programme gibt.

Oder, neue Argumentationslinie: Gnome bietet seinen Nutzern mehr Audio-Optionen als Optionen, die die Gestaltung des Desktops betreffen. (Genaugenommen gibt es ja nur eine Option: Über das Hintergrundbild dürfen Sie vorerst noch selbst verfügen …) Es gibt mehr als ein Dutzend Optionen zur Barierrefreiheit. Die Benachrichtigungen können bis ins letzte Detail gesteuert werden. (Alle diese Optionen dürfen bleiben, nicht dass mir das jemand falsch auslegt …) Aber angesichts der Anzahl von Optionen in Randbereichen des Desktops wäre ein Dialogblatt »Desktop-Einstellungen« mit vier, fünf Optionen auch noch vertretbar. Es würde auch den Wartungsaufwand nicht sofort ins Unendliche wachsen lassen.

Schlusswort

Ich bin dankbar, dass es Linux gibt, dass es Gnome gibt. Ich bin jeder Entwicklerin, jedem Entwickler dankbar, die/der auf ihre/seine Weise das Open-Source-Universum vergrößert, an Projekten mitarbeitet, Gnome noch perfekter macht. Dieser Blog-Beitrag soll kein Zeichen meiner Undankbarkeit sein, er soll keinen Flame War auslösen.

Alles, was ich mir wünsche, ist ein Gnome, das noch ein kleines bisschen besser ist als bisher. Das seinen Anwendern ein klein wenig mehr Flexibilität bietet. Das mehr als nur ein Anwendungs-Szenario vorsieht (in etwa: kleiner/großer Monitor; Einsteiger/Entwickler) . Ich bitte nicht um unzählige neue Optionen, sondern um einige wenige. Und es wäre schön, wenn man die ohne Extensions oder Gnome Tweaks direkt in den Einstellungen verändern könnte. Ein guter Startpunkt wäre:

  • Dock: links/rechts/unten
  • Dock automatisch ausblenden: ja/nein
  • Fenster-Minimieren-Button anzeigen: ja/nein

Wenn ich total unverschämt sein darf, auch noch:

  • Fenster-Buttons: links/rechts

Das würde macOS- und Windows-Umsteigern gleichermaßen entgegen kommen.


PS: Noch eine Anmerkung zu Pop!_OS: System76 verspricht in seinem Blog den neuen Cosmic-Desktop, der mit Version 21.04 im Juni ausgeliefert werden soll. Laut ersten Tests einer Beta-Version (YouTube-Video) handelt es sich dabei ganz einfach um Gnome 3.38, das um diverse Shell Extensions erweitert wurde (inklusive einer Menge neuer Optionen im Einstellungsdialog). Im Prinzip ist das der gleiche Ansatz wie bei Ubuntu, aber mit mehr Änderungen. Und auch die Probleme sind die gleichen: Was tun, wenn die neue Gnome-Version inkompatibel zu den eigenen Extensions ist?

Ubuntu 21.04

22. April 2021 um 16:57

Ubuntu 21.04 (»Hirsute Hippo«) ist fertig. Auf meinem Hauptrechner läuft es schon seit zwei Wochen (nachdem ich Ubuntu 20.10 übersprungen und nur in virtuellen Maschinen ausprobiert habe). Dieser Artikel fasst die wichtigsten Neuerungen zusammen.

Update 28.4.2021: Suspend-Probleme (siehe eigenen Abschnitt), Hinweis auf Raspberry Pi

Das Wallpaper von Ubuntu 21.04

  • Ubuntu ist bei Gnome 3.38 geblieben und hat das Update auf Version 40.0 nicht nachvollzogen. Der Hauptgrund ist vermutlich das neue Gnome-Layout, das zu den Ubuntu-eigenen Shell-Erweiterungen (und insbesondere zur dauerhaft am linken Rand angezeigten Task-Leiste) inkompatibel ist. Ich muss zugeben, dass ich Ubuntu in diesem Punkt verstehe: Gnome 40 sieht auf einem kleinen Notebook-Monitor großartig aus, bringt mich aber auf meinem Arbeitsplatz (28-Zoll-Monitor mit 4k) zum Verzweifeln. Mir erscheint der Gnome-Weg einmal mehr fundamentalistisch. Wir wissen, wie es richtig ist, alle müssen es jetzt so machen … (Ich werde demnächst beim Fedora-34-Blog-Beitrag mehr dazu schreiben.)
  • Aufgrund einer neuen Shell Extension funktioniert das Ablegen von Icons am Desktop anscheinend besser als bisher. Da ich dieses Funktion nie verwende und mir auch rätselhaft ist, warum man Icons auf den Desktop platziert, die dann doch unter allen Fenstern verschwinden, kann ich dazu nicht viel sagen.

  • Ubuntu verwendet jetzt standardmäßig Wayland. Dieser Aussage müssen natürlich gleich ein paar Einschränkungen folgen: Zum einen gilt dies nur für das »Haupt-Ubuntu«, nicht aber für die meisten Derivate. Und zum anderen sind Wayland und die NVIDIA-Treiber weiterhin inkompatibel zueinander. Wer also eine NVIDIA-Grafikkarte samt proprietären Treiber verwendet, kommt weiter in den Genuss von X.

  • Die Heimatverzeichnisse sind jetzt besser geschützt. Bisher waren die Zugriffsrechte oktal mit 755 voreingestellt, d.h. prinzipiell konnte jeder in die Home-Verzeichnisse anderer Personen hineinschauen (r-x für others). Nunmehr lauten die Zugriffsrechte 750, was sicherer ist.

  • Wenn Sie sich bei der Installation von Ubuntu für die Verschlüsselung des Dateisystems entscheiden, zeigt das Setup-Programm in einem überarbeiteten Dialog einen Recovery-Key an, den Sie verwenden können, sollten Sie Ihr Verschlüsselungspasswort vergessen.

Wenn Sie das Dateisystem verschlüsseln, offeriert das Installations-Programm jetzt einen Recovery-Key.
  • Snap ist weiterhin standardmäßig aktiv. Interessanterweise sind zwar einige Snap-Bibliotheken installiert, aber außer dem Snap-Store (einer Variante des Gnome-Programms Software) kein einziges Programm. (In der Vergangenheit hat Ubuntu einige Gnome-Standardprogramme als Snaps verpackt, wobei ich den Grund nie verstanden habe. Damit ist jetzt offenbar Schluss.)
snap list

Name               Version             Revision  Tracking         Herausgeber  Hinweise
---------------------------------------------------------------------------------------
core18             20210309            1997      latest/stable    canonical✓   base
gnome-3-34-1804    0+git.3556cb3       66        latest/stable/…  canonical✓   -
gtk-common-themes  0.1-52-gb92ac40     1515      latest/stable/…  canonical✓   -
snap-store         3.38.0-59-g494f078  518       latest/stable/…  canonical✓   -
snapd              2.49.2              11588     latest/stable    canonical✓   snapd

Versionsnummern

Basis             Desktop             Programmierung   Server
---------------   ------------------  --------------   --------------
Kernel     5.11   Gnome        3.38   bash       5.1   Apache     2.4
glibc      2.33   Firefox        87   docker   20.10   CUPS       2.3
X-Server   1.20   Gimp         2.10   gcc       10.3   MySQL      8.0
Wayland    1.18   LibreOffice   7.1   Java        11   OpenSSH    8.4
Mesa       21.0   Thunderbird    78   PHP        7.4   qemu/KVM   5.2
Systemd     247                       Python     3.9   Postfix    3.5
NetworkMan 1.30                                        Samba     4.13
GRUB       2.04 

Gnome wird genaugenommen nicht konsequent in Version 3.38 ausgeliefert. Vielmehr gibt es vereinzelte Pakete, die neuer sind (gnome-calculator, gnome-font-viewer etc.) und solche, die älter sind (gnome-keyring, libgnome-bluetooth). Bei Bedarf können Sie sich mit dpkg -l | grep gnome rasch selbst einen Überblick verschaffen.

Ubuntu auf dem Raspberry Pi

Die Vollversion von Ubuntu 21.04 läuft auch auf aktuellen Raspberry-Pi-Modellen — vorausgesetzt, diese sind mit 4 GB RAM ausgestattet. Ubuntu funktioniert trotz der eingeschränkten Hardware erstaunlich gut. Einen Erfahrungsbericht finden Sie auf pi-buch.info.

Fazit

Wie gesagt, ich verwende nun seit fast zwei Wochen dauerhaft Ubuntu 21.04. Reale Unterschiede, die bei meiner täglichen Arbeit spürbar wären, habe ich nicht bemerkt. Weder optisch noch funktionell hat sich (für mich) etwas getan. Was die Stabilität betrifft, bin ich genau so zufrieden wie mit 20.04 — und das ist ein gutes Zeichen.

Von einem winzigen Ärgernis kann ich berichten: Aus irgendeinem Grund scheint die Spotify-App (ich verwende normalerweise das Debian-Paket, nicht das Snap-Paket) nicht mehr so recht zu funktionieren. Sie weigert sich, auf meinem Rechner Musik abzuspielen. Ich habe mir bisher nicht die Mühe gemacht, dem Problem auf den Grund zu gehen. Die App war nie eine Offenbarung. Spotify funktioniert im Browser ebenso gut.

Ubuntu 21.04 mit Gnome-3.38-Dekstop und einigen offenen Fenstern

Intel Undervolting führt zu Suspend-Problemen (Update 26.4.2021)

Mittlerweile ist doch ein Problem aufgetreten — aber Ubuntu ist daran unschuldig. Ich verwende intel-undervolting (siehe GitHub). Zusammen mit aktuellen Kernel-Versionen führt das zur Fehlermeldung Write to unrecognized MSR 0x150 und in weiterer Folge dazu, dass Suspend nicht mehr funktioniert: Failed to change runlevel. Transaction for reboot.target/start is destructive (intel-undervolt.service has ’start‘ job queued, but ’stop‘ is included in transaction. Ich habe jetzt in /etc/default/grub die folgenden Änderungen eingebaut:

GRUB_CMDLINE_LINUX_DEFAULT="msr.allow_writes=on"
GRUB_CMDLINE_LINUX="msr.allow_writes=on"

Einstweilen scheint das auszureichen. Längerfristig wird der Linux-Kernel aber MSR-Writes ganz unterbinden. Spätestens dann braucht es ein Update für intel-undervolt, oder das Tool wird nicht mehr funktionieren. Hintergründe:

https://github.com/kitsunyan/intel-undervolt/issues/55
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/about/

Quellen / Links / Andere Tests

LaTeX-Benchmark: Mac M1 vs. Lenovo P1 bzw. macOS vs Linux

03. April 2021 um 18:24

Für viele Entwickler ist der CPU-intensivste Prozess das Kompilieren großer Projekte. Für mich als Autor ist es die Umwandlung von Markdown-Dateien zuerst in die LaTeX-Syntax (Pandoc) und dann in ein PDF-Dokument (latex, dvips, ps2pdf). Seit ein paar Tagen verfüge ich über einen Mac Mini M1 als zusätzlichen Testrechner. Natürlich war ich neugierig, wie schnell das Ding nun wirklich ist — im einzigen Real-World-Test, der für mich relevant ist: Beim Erzeugen von PDFs aus LaTeX-Dateien.

Setup

Mein voll wissenschaftliches ;-) Benchmark-Setup sah so aus:

  • Rechner 1: Lenovo P1 Notebook mit i7-8750H-CPU, 32 GB RAM, Ubuntu 20.04 LTS
  • Rechner 2: Mac Mini M1: 16 GB RAM, M1-CPU, macOS 11.2

Die zu übersetzende LaTeX-Datei ist 1,3 MByte groß (das ergibt ca. 550 Seiten Text), die einzubettenden EPS-Dateien umfassen 80 MByte, die resultierende PDF-Datei ist dann ca. 18 MByte groß. Überschaubare Datenmengen also.

Sämtliche Werkzeuge (latex, dvips, ps2pdf) sind single-threaded, profitieren also leider nicht von vielen CPU-Cores.

Linux plus Docker

Unter Linux verwende ich für Pandoc und LaTeX einen Docker-Container, der sämtliche Werkzeuge in einer unveränderlichen Version enthält. Die Verwendung von Docker hat sich sehr bewährt, erstens weil ich ohne viel Installationsarbeiten ein ganzes Buch schnell auf einen anderen Rechner »übersiedeln« kann und alles weiter funktioniert, und zweites, weil nicht irgendwelche LaTeX- oder Pandoc-Updates die Kompatibilität zu meinen handgestrickten Scripts zerstören.

Wenn mein Notebook im ‚Leise-Modus‘ läuft (CPU-Takt auf 80% = 2,2GHz limitiert, kein Turbomodus), dann dauert die PDF-Erzeugung (zuerst pandoc, dann 2x latex, dvips und ps2pdf) ca. 2:09 min, also 129 Sekunden.

Wenn ich es eilig habe und die CPU auf ‚Performance‘ stelle (volle Taktfrequenz, mit Turbomodus), verdoppelt sich die Geschwindigkeit nahezu, Laufzeit 1:14 min. Allerdings heult dann der Lüfter wie ein Düsenjäger, was ich hasse und die Konzentration mindert.

macOS plus Docker

Docker für den Mac Mini M1 hat in den letzten Wochen massive Fortschritte gemacht und läuft inzwischen ziemlich gut. Ich habe mit RC3 vom 1. April gearbeitet. Viele weit verbreitete Images stehen bereits nativ für ARM zur Verfügung. Mein LaTeX-Script läuft in 1:12 min, also im Rahmen der Messungenauigkeit gleich schnell wie auf dem Lenovo-Notebook bei voller CPU-Leistung. Allerdings ist der Mac Mini dabei absolut lautlos. (Es gibt einen Lüfter. Dieser läuft dauerhaft mit 1700 RPM, ist aber für meine Ohren unhörbar. Wenn man nicht gerade synthetische Benchmark-Tests oder das Xcode-Image auspackt ausführt, wird der Lüfter nie hörbar.)

PS: Alle (und speziell die heise.de-Autoren), die meinen, Docker sei angesichts der Container-Konkurrenz durch Podman und Co. obsolet, sollen einmal versuchen, mit Containern auf nicht Intel-kompatiblen Systemen bzw. außerhalb der Linux-Welt zu arbeiten :-)

macOS nativ mit MacTeX 2021

Die ersten Versionen von Docker für die ARM-CPU von Apple litten unter massiven Performance-Problemen, besonders bei I/O-Operationen. Massiv betroffen waren Datenbanksysteme. Mittlerweile scheinen dieses Probleme weitgehend behoben zu sein, aber ich wollte doch wissen, ob Docker in meinem Setup nicht ein Bremsklotz ist.

Also habe ich MacTeX 2021 installiert (erst seit wenigen Tagen verfügbar, unterstützt die ARM-Architektur nativ) und meinen Test damit wiederholt. Ergebnis: 1:05 min. (Pandoc habe ich auch bei diesem Test unter Docker ausgeführt, weil es die von mir benötigte Pandoc-Version nicht als nativen ARM-Download gibt. Ich habe mir deswegen die schon etwas ältere Pandoc-Version 2.7.3 aus den Quellen selbst in ein Ubuntu-Docker-Image kompiliert.)

Zusammenfassung

Laufzeiten für pandoc sowie für 2x latex, dvips, ps2pdf

                                Zeit              Geräuschkulisse
------------------------------- ----------------  --------------------
Lenovo P1 8750H@2,2 GHz         49 + 80 = 129 s    zumeist lautlos
Lenovo P1 8750H@4 GHz           29 + 45 =  74 s    störend
Mac Mini M1 (LaTeX in Docker)   28 + 44 =  72 s    lautlos
Mac Mini M1 (LaTeX nativ)       28 + 37 =  65 s    lautlos

Alles in allem ist die Performance der M1-CPU eindrucksvoll — insbesondere, wenn man nicht nur die Geschwindigkeit, sondern auch die Leistungsaufnahme berücksichtigt. Ich weiß natürlich, dass ich Äpfel mit Birnen vergleiche: Die Intel-CPU ist ca. zwei Jahre älter als die M1-CPU. Der Mac ist ein (kleiner) Desktop-Rechner, als Vergleichsrechner musste ein Notebook herhalten. Ein Desktop-System mit einer aktuellen Intel- oder AMD-CPU ist natürlich schneller als beide Testkandidaten, und bei geeigneter Kühlung für meine Aufgabenstellung ebenfalls (nahezu) lautlos.

Andererseits: So flüssig sich macOS auf einem M1-Rechner anfühlt — auch Apple kocht nur mit Wasser. Synthetische Tests (z.B. GeekBench) lassen den M1 schneller erscheinen, als er bei Real-World-Aufgaben tatsächlich ist. Nach dem Mediengetöse seit der M1-Vorstellung hatte ich eigentlich erwartet, dass der Mac Mini mein Notebook meilenweit abhängen würde. Das ist definitiv nicht der Fall. (Ich kann natürlich nicht ausschließen, dass Apple mit dem M1X oder M2 oder wie auch immer der M1-Nachfolger heißen wird, noch einmal ordentlich nachlegt. Aber die CPU-Entwicklung bleibt ja auch bei Intel und AMD nicht stehen. Speziell bei Intel erwarte ich, dass die Firma jetzt aus dem Dornröschenschlaf der letzten Jahre erwacht. Nichts motiviert besser als gute Konkurrenz.)

Links

AlmaLinux

02. April 2021 um 16:38

Vor ein paar Monaten habe ich über das Ende von CentOS lamentiert. Mittlerweile habe ich mich ganz gut mit Oracle Linux arrangiert, und seit ein paar Tagen gibt es eine weitere Alternative: AlmaLinux OS. Dieser RHEL-Klone wurde von der Firma CloudLinux zusammengestellt. CloudLinux verspricht, AlmaLinux bis 2029 zu warten — also so lange wie RHEL und vorauss. rund fünf Jahre länger als CentOS Stream.

Heute habe ich eine Minimalinstallation in einer virtuelle Maschine vorgenommen. Was soll man sagen? Wenn man schon mit RHEL, CentOS und Oracle Linux gearbeitet hat, ist nicht viel Unterschied zu sehen. Das Installer-Hintergrundbild sieht ein wenig anders aus, sonst läuft alles, wie gewohnt. Nach der Installation liefert cat /etc/os-release die folgenden Daten:

cat /etc/os-release 
NAME="AlmaLinux"
VERSION="8.3 (Purple Manul)"
ID="almalinux"
ID_LIKE="rhel centos fedora"
VERSION_ID="8.3"
PLATFORM_ID="platform:el8"
...

Einige Anmerkungen:

  • Die EPEL-Paketquelle kann wie unter CentOS ganz einfach mit dnf install epel-release aktiviert werden.
  • Vorhandene CentOS- oder Oracle-Linux-Installationen können bei Bedarf unkompliziert mit einem Migrations-Script auf AlmaLinux umgestellt werden.

  • Anders als auf heise.de angegeben ist AlmaLinux noch nicht SecureBoot-kompatibel. Diese Funktion ist in Arbeit, aber es gibt keinen konkreten Zeitrahmen. (Das Problem besteht wie für jede junge Distribution darin, Signatur-Schlüssel zu erhalten.)

  • Noch eher sparsam ist die Dokumentation. Aktuell führt eine Suche zu problem xy centos oder problem xy rhel eher zum Ziel als problem xy almalinux.

Ausblick

Auf den ersten Blick fühlt sich AlmaLinux exakt so an wie CentOS/RHEL/Oracle Linux. Die entscheidende Frage lautet nun: Kann AlmaLinux sich eine so gute Reputation wie CentOS erarbeiten (oder womöglich eine bessere)? Eine seriöse Antwort ist leider erst in ein paar Jahren möglich. CloudLinux muss jetzt seine Versprechen einlösen, AlmaLinux gut zu warten und aktuell mit Updates zu versorgen. Aktuell stehen die Zeichen gut. Die pünktliche Fertigstellung von AlmaLinux im 1. Quartal 2021, eine beachtliche Mirror-Liste, ein versprochenes Budget von einer Million US$ pro Jahr sowie bekannten Namen im Team (siehe das Press Release auf lwn.net) machen auf jeden Fall Hoffnung, dass es weiterhin Auswahl in der Welt der RHEL-Klone gibt. Erfahrene Administratoren werden sich vermutlich trotzdem abwartend verhalten und nicht sofort die wichtigsten Produktivsysteme auf AlmaLinux umstellen.

Quellen

IPv6 — Eine Leidensgeschichte aus Österreich

06. März 2021 um 18:32

IPv6 ist das neue Internetprotokoll, das die Adressknappheit von IPv4 beheben soll. »Neu« ist natürlich relativ, der Standard wurde schon 1998 verabschiedet. Aber als Österreicher lernt man, die Dinge keinesfalls zu übereilen. Andererseits: 23 Jahre …

In Österreich führt der naheliegende Weg zum Festnetz-Internet über die Telekom Austria, kurz A1. Diese Firma genießt — zumindest in meiner Wohngegend — für diese Dienste Quasi-Monopolstatus. (Es gibt Drittanbieter, die aber selbst das Netz der A1 nutzen.)

Dieser Blog-Beitrag fasst zusammen, wie ich kürzlich — anscheinend zufällig — für ca. ein halbes Jahr in den Genuss von IPv6 kam und wie ich diese Funktion mit dem zuletzt durchgeführten Speed-Upgrade wieder verloren habe. Der Vollständigkeit halber vergleiche ich hier auch kurz die IPv6-Versorgung von Österreich und Deutschland. Außerdem erkläre, wie man mit einem geeigneten Modem/Router an der A1 vorbei trotzdem IPv6 nutzen kann — und warum das selten zweckmäßig ist.

Update 10.3.2021: IPv6 is back. Plus ein paar kleine Korrekturen.

Kurzzeitig IPv6

Mein Internet-Zugang funktioniert seit vielen Jahren relativ zuverlässig — wenn auch nur mäßig schnell. Und er kann natürlich nur IPv4.

Eigentlich hatte ich mich schon abgefunden, dass ich IPv4 auf immer treu bleiben würde. Doch im Herbst 2020 ist mir bei einem Blick in den FritzBox-Online-Monitor aufgefallen, dass IPv6 aktiv ist. Cool! Quasi ein IPv6-Upgrade ohne Ankündigung, aber es geht! Was will man mehr?

Ich kann nicht ausschließen, dass ich im Herbst 2020 schon monatelang IPv6 hatte ohne es zu bemerken. Vorigen Oktober habe ich aber ein paar virtuelle Maschinen eingerichtet, die eine private IPv4-Adresse und eine öffentliche IPv6-Adresse haben. Da war IPv6 mehr als willkommen: Plötzlich funktioniert ssh ohne Umwege, ganz wie es sein soll.

Alles bestens also? Fehlanzeige. Vor drei Wochen hatte ich die abwegige Idee, der A1 für ein paar MBit höhere Geschwindigkeit noch mehr Geld in den Rachen zu werfen. Das Speed-Upgrade von 40 auf 80 MBit war schnell erledigt. Tatsächlich erreiche ich zwar nur max. 60 MBit anstelle der versprochenen 80 MBit im Download (mehr gibt die Leitung zur Vermittlungsstelle leider nicht her), aber diesbezüglich will ich hier nicht jammern: Immerhin ist der Upload deutlich flotter geworden. Das ist in Corona-Zeiten mit Home-Schooling und E-Unterricht auch viel wert. Trotzdem muss ich natürlich lachen, wenn ich die Gigabit-Werbung von A1 höre/sehe. Schön wär’s.

Als ich ein paar Tage nach dem Upgrade wieder meine virtuellen Maschinen nutzen wollte, funktionierte ssh plötzlich nicht mehr. ping6 eben so wenig. Ein Blick in den Online-Monitor der Fritzbox zeigt: IPv6 ist weg. Speed-Upgrade mit IPv6-Downgrade also?

A1-Service-Hotline: »Was ist IPv6?«

Da ist sicher ein Fehler passiert, der lässt sich leicht beheben, oder? Die erste Dame in der A1-Service-Hotline war ausnehmend freundlich, aber IPv6 war für sie offensichtlich ein Fremdwort. Da müsse Sie mich mit der Technik verbinden. Die Dame von der Technik war nicht minder höflich und zuvorkommend, aber technisch nur unwesentlich versierter. Sie müsse nachfragen. Das tat sie dann im Laufe unseres fast halbstündigen Gesprächs noch öfter.

Lange Rede kurzer Sinn: Warum ich im vergangenen halben Jahr IPv6 hatte, konnte sich bei der A1 keiner erklären. Vorgesehen sei dies nur für Business-Kunden. (Update: Das stimmt so auch nicht. »Kleine« Business-Kunden bekommen standardmäßig anscheinend auch kein IPv6. Es gibt aber diverse Angebote für Großkunden.) Es sei unmöglich, IPv6 einfach wieder zu aktivieren. Aber wenn ich diese Funktion dennoch unbedingt brauche, solle ich diesen Wunsch schriftlich deponieren. (Ob es etwas nützen würde, blieb offen.)

Was heißt schriftlich? Hat die Telekom Austria kein E-Mail? Sie hat, aber nicht für den Kundenkontakt. Der erfolgt wahlweise über Kara (das ist ein Chat-Bot mit der Intelligenz eines Papageis, wobei das vermutlich eine Beleidigung für alle Papageien ist), über das Telefon (wie gesagt, wirklich freundlich) oder eben schriftlich.

Die wollen natürlich, dass ich endlich aufgebe. Stattdessen schreibe ich mir meinem Ärger in diesem Blog-Beitrag von der Seele. Der Brief ist selbstverständlich auch schon geschrieben, mangels Briefmarken aber noch nicht versendet. Da bin ich auf jeden Fall dankbar, dass wir eine moderne Post haben. Sonst müsste ich befürchten, mein Brief würde per Pferdekutsche in die vom K&K-Geist durchdrungene Telekom-Austria-Zentrale transportiert …

Immer wieder Córdoba: Deutschland gegen Österreich

Aus den Zugriffen auf https://kofler.info (meine Website ist seit vielen Jahren per IPv6 erreichbar) weiß ich, dass der IPv6-Anteil mittlerweile bei ca. einem Drittel liegt. Wo kommen die vielen IPv6-Zugriffe eigentlich her? Überwiegend aus Deutschland, auch aus der Schweiz, aber kaum aus Österreich.

Zur IPv6-Versorgung verschiedener Länder gibt es natürlich aussagekräftigere Statistiken. Beispielsweise gibt es bei Akamei eine Weltkarte samt statistischen Daten zur IPv6-Versorgung. Demnach führt Indien mit über 60% IPv6-Verbreitung. Die folgende Tabelle nennt ein paar ausgewählte Länder, Stand Anfang März 2021:

Platz   IPv6-Verbreitung     Land
------- ------------------   -----------------
1       62%                  Indien
4       46%                  Deutschland
7       44%                  Frankreich
8       43%                  Schweiz
9       41%                  USA
10      41%                  Japan
22      30%                  Großbritannien
34      20%                  Rumänien
35      20%                  Österreich
36      20%                  Myanmar

Die IPv6-Versorgung in Österreich liegt demnach auf Platz 35, zwischen der von Rumänien und Myanmar. Ähnliche Daten, wenn auch für weit weniger Länder, finden sich bei apnic.net (siehe auch die folgende Abbildung). Umfassende Statistiken kann auch Google beisteuern. Die Ergebnisse sind ähnlich trostlos. Mit IPv6 ist’s anscheinend wie beim Fußball: Österreich gegen Deutschland, das geht aus österreichischer Perspektive selten gut.

Keine Corona-Karte, sondern die IPv6-Versorgung in Deutschland, Österreich, der Schweiz und einigen weiteren Ländern (Bildquelle: https://stats.labs.apnic.net/ipv6/AT)

Trotzdem IPv6

Wer wirklich hartnäckig ist, kann IPv6 selbst dann nutzen, wenn der Provider dies nicht vorsieht. Voraussetzung ist nur ein vernünftiger Router (früher Modem bezeichnet). Im Menü meiner FritzBox kann ich IPv6 einfach so aktivieren: Dialogblatt Internet / Zugangsdaten / IPv6, Option Tunnelprotokoll verwenden, Option 6to4. Fertig!

Nicht empfehlenswert: Die Übergangstechnik 6to4

Leider ist das zu schön, um wahr zu sein. IPv6 funktioniert zwar, aber bald tauchen in Google die ersten Hinweise auf, dass 6to4 eine veraltete Technik ist (siehe auch die Wikipedia). Spätestens, wenn man zum dritten Mal Captchas löst, um eine Google-Abfrage durchzuführen, schaltet man diese Option entnervt wieder aus.

Die Alternative zu 6to4 ist ein »echter« IPv6-Tunnel. Früher gab es eine Menge Anbieter, die solche Tunnel kostenlos zur Verfügung stellten. Übrig geblieben ist heute unter anderem Hurricane Electric. Bei dieser Firma können Sie einen kostenlosen Account einrichten und dann — ebenfalls kostenlos — einen Tunnel beantragen. Dabei müssen Sie die aktuelle IPv4-Adresse Ihres Routers angeben, außerdem den gewünschten Tunnel-Endpunkt. Zur Wahl stehen unter anderem Budapest, Zürich, Berlin und Frankfurt. Ich habe mich wegen des schnellsten Pings für Budapest entschieden.

Eckdaten eines IPv6-Tunnels von Hurricane Electric

Nun gilt es, diese Eckdaten im IPv6-Setup der FritzBox einzutragen. Dafür wählen Sie die Option 6in4.

FritzBox-Konfiguration für HE-Tunnel (Teil 1)

Damit ist es aber nicht getan. Damit der Tunnel funktioniert, muss Hurricane Electric wissen, welche IPv4-Adresse Sie gerade haben. Die ändert sich aber jedesmal, wenn die FritzBox die Internet-Verbindung neu herstellt, typischerweise alle paar Tage. Glücklicherweise kommt uns hier das DynDNS-Service der FritzBox zu Hilfe. Im Dialog Internet / Freigaben / DynDNS aktivieren Sie diesen Service, wählen Anbieter = Benutzerdefiniert und geben dann als Update-URL eine Zeichenkette an, die Sie auf der TunnelBroker-Website im Dialogblatt Advanced finden (Feld Example Update URL). Im FritzBox-Dialog wählen Sie nun einen beliebigen Domain-Namen (ich habe einfach fritzbox verwendet). Benutzernamen und Kennwort extrahieren Sie aus der URL, die den Aufbau https://benutzername:passwort@ipv4.tunnelbroker.net/nic/update?hostname=nnnnnn hat.

FritzBox-DynDNS-Konfiguration für den IPv6-Tunnel (Teil 2)

Mit dieser Konfiguration wird der IPv6-Tunnel nach jeder Internet-Neuverbindung aktualisiert und innerhalb weniger Sekunden aufgebaut.

Wie gewonnen, so zerronnen

Die Österreicher sind ja bekanntlich nicht Fußball-, sondern Tunnelbauweltmeister. Aber nicht jeder Tunnel ist großartig. Der von Hurricane Electric hat gleich mehrere Nachteile:

  • Für GeoLocation-Dienste bin ich nun mit IPv4 in Österreich, mit IPv6 aber in Ungarn. Suboptimal.
  • Die Ping-Latenz bei IPv6 ist etwa doppelt so groß wie die von IPv4. (Die genauen Laufzeiten variieren, je nachdem, wie groß der Umweg über meinen Tunnelendpunkt Budapest zum tatsächlichen Ziel ist. Zum Teil scheinen die IPv6-Pings auch gar nicht durchzugehen.)

  • Die Download-Geschwindigkeit in IPv6 war bei meinen Tests nur halb so groß wie die in IPv4 (gemessen mit https://ipv6-test.com). Naturgemäß variieren die Ergebnisse, je nachdem, wie groß die Geschwindigkeit Ihres »echten« Internetzugangs ist, wie groß der Tunnel-Umweg und wie hoch die Auslastung des Tunnel-Servers.

Bitte reduzieren Sie Ihr Tempo im Tunnel …

Alles in allem ist das kostenlose Angebot von Hurricane Electric großartig, um IPv6 zu testen. Für den dauerhaften Betrieb ist es aber mit erheblichen Einschränkungen verbunden.

Bitte an die A1

Sollte diesen Blog-Beitrag jemand von der A1 lesen, würde ich mich wirklich sehr freuen, wenn Sie mir IPv6 einfach wieder aktivieren. Dass das technisch möglich ist, weiß ich nun ja. Eine Kontakt-E-Mail gibt es unter https://kofler.info/impressum. Ich würde diese Dienstleistung hier auch lobend erwähnen :-)

Die Zeiten, wo IPv6 etwas Besonderes ist, eine Barmherzigkeit des Providers an seine Kunden, sollten endlich vorbei sein. IPv6 ist ein Standard und eine Selbstverständlichkeit.

Update: Die A1 hat mein Flehen vernommen — ich bedanke mich ganz ausdrücklich dafür!

Nach einem weiteren sehr freundlichen Telefonat, diesmal auf höchstem technischen Niveau, wurde das Dual-Stack-Setup, wie ich es im Herbst/Winter 2020/2021 schon hatte, neuerlich aktiviert. Unklar bleibt, warum IPv6 zwischenzeitlich verschwunden ist — mit dem Upgrade hätte es anscheinend nichts zu tun gehabt. Pech beim Timing, sozusagen.

Unklar ist auch, warum IPv6 offenbar selektiv (siehe auch lteformum.at), aber nicht generell aktiviert wird, wenn die technischen Möglichkeiten auf A1-Seite ja ohnedies gegeben sind. Ein Hindernis scheint der Router zu sein. Offensichtlich sind nicht alle Modelle, die die A1 zur Verfügung stellt, IPv6-tauglich. (Die FritzBox erhält man bei der A1 aktuell nur gegen Bezahlung. Wobei dieser Mehrbetrag — zumindest aus meiner Sicht — sehr lohnend investiert ist. Allein schon wegen der viel höheren Stabilität. Von den vielen Zusatzfunktionen ganz zu schweigen.)

Quellen, Links

Raspberry Pi Pico: MicroPython-Programmierung

04. Februar 2021 um 18:07

In meiner Kurzvorstellung des Raspbery Pi Pico habe ich Ihnen gezeigt, wie Sie auf dem Micro-Controller MicroPython installieren und über eine Konsolen-App (z.B. minicom) interaktiv nutzen können. Das ist ein wichtiger erster Schritt, um den Pico auszuprobieren. Letztlich wollen Sie aber Programme entwickeln, die dauerhaft am Pico laufen. Dazu reicht die interaktive Anwendung des Python-Interpreters nicht aus.

Dieser Beitrag zeigt, wie Sie mit Thonny ein »richtiges« MicroPython-Programme entwickeln und dieses auf dem Pico so speichern, dass es beim nächsten Start des Micro-Controllers automatisch ausgeführt wird.

Thonny

Die Raspberry Pi Foundation (im weiteren RPF) empfiehlt den Einsatz von Thonny zur MicroPython-Entwicklung. Allerdings brauchen Sie nicht irgendeine beliebige Thonny-Version, sondern die aktuellste, die gerade verfügbar ist. Die RPF rät in Getting Started with MicroPython (PDF) dazu, bei älteren Thonny-Versionen ein spezielles Plugin (»Wheel File«) zu installieren — aber diesem Tipp sollten Sie nicht folgen: Ältere Thonny-Versionen bis einschließlich 3.2.n sind inkompatibel zu diesem Plugin; bei neueren Versionen ab 3.3.3 ist das Plugin dagegen schon installiert. Die Plugin-Installation ist daher nur zweckmäßig, wenn Sie eine Thonny-Version zwischen 3.3.0 und 3.3.2 verwenden, was eher unwahrscheinlich ist.

Unter macOS und Windows ist es recht einfach, die gerade aktuelle Thonny-Version herunterzuladen und zu installieren. Unter Linux ist das etwas schwieriger — da sind Sie normalerweise auf die Version festgelegt, die Ihre Distribution als Paket zur Verfügung stellt. Aber es gibt einen einfachen Ausweg: De-installieren Sie das Thonny-Paket Ihrer Distribution und installieren Sie stattdessen die aktuelle Version via pip3. Also:

sudo apt remove thonny
pip3 install thonny

Der einzige Nachteil: Sie müssen Thonny über die Konsole starten. Das Startmenü bzw. die Gnome-Aktivitäten kennen den per pip3 installierten Thonny nicht.

Zugriff auf die serielle USB-Schnittstelle freigeben

Wenn Sie unter Debian, Ubuntu & Co. arbeiten, kann Thonny mangels ausreichender Zugriffsrechte nicht auf die serielle USB-Schnittstelle /dev/ttyACM0 zugreifen. Die Device-Datei ist der dialout-Gruppe zugewiesen. Abhilfe schafft, wenn Sie Ihrem eigenen Account ebenfalls diese Gruppe hinzufügen.

sudo usermod -a -G dialout $USER

Die neue Gruppenzuordnung wird erst wirksam, wenn Sie sich aus und neu einloggen.

Konfiguration von Thonny

Thonny führt Python-Programme normalerweise lokal aus. Um den Python-Interpreter des Pico zu verwenden, führen Sie in Thonny Run / Select interpreter aus und stellen als Interpreter MicroPython (Raspberry Pi Pico) ein. In der Shell von Thonny können Sie sich überzeugen, dass Ihre Python-Kommandos und Scripts wirklich am Pico ausgeführt wird.

import sys
print(sys.version)

  3.4.0

import micropython
micropython.mem_info()

  stack: 508 out of 7936
  GC: total: 192064, used: 19072, free: 172992
  No. of 1-blocks: 489, 2-blocks: 84, max blk sz: 64, max free sz: 10806
Thonny führt MicroPython auf dem Raspberry Pi Pico aus

Programmierung

Nach diesen Vorbereitungsarbeiten kann es los gehen. Wenn Sie im Editor print("Hello") eingeben und auf den Run-Button drücken, fragt Thonny, wo es das Programm speichern soll. Zur Wahl stehen This computer (also Ihr normaler Rechner) oder Raspberry Pi Pico. Während der Entwicklungsphase ist es beinahe egal, für welche Option Sie sich entscheiden — das Programm wird nämlich in jedem Fall auf dem Pico ausgeführt. Sicherer ist es, den Code lokal zu speichern — dann verfügen Sie auch dann noch über den Code, wenn Sie Ihren Pico später für andere Aufgaben verwenden. (Mit File / Save As können Sie jederzeit den Speicherort ändern.)

Anders sieht es aus, wenn Sie mit der Funktion Ihres Programms zufrieden sind und Sie möchten, dass der Pico dieses Programm sofort nach dem Einschalten ausführt. Dann speichern Sie Ihren Code unter dem Namen main.py auf dem Pico.

Wenn Sie nun die Stromversorgung des Pico trennen und wiederherstellen, startet das Programm — und zwar sofort. Anders als bei einem Computer muss der Pico nicht booten. Es ist verblüffend, wie schnell der Start vor sich geht.

main.py hindert Sie übrigens nicht daran, die Entwicklung fortzusetzen. Sie können jederzeit mit Thonny das Programm stoppen, die Code laden, verändern und neu starten. Falls Sie main.py löschen möchten, führen Sie in Thonny View / Files aus. Das Programm zeigt alle Dateien aus. Per Kontextmenü können Sie nun Dateien löschen, wobei es aber keinerlei Undo-Möglichkeit gibt.

Thonny stellt auch einen minimalistischen Dateimanager zur Verfügung

MicroPython-Entwicklung ohne Thonny

Thonny in Ehren, aber nicht jeder wird mit dieser Einsteiger-IDE glücklich werden. Wenn Sie nicht Thonny verwenden möchten, müssen Sie sich selbst um den Transfer von Dateien zum Pico kümmern. Gut dazu geeignet ist das Python-Programm rshell:

https://github.com/dhylands/rshell

Alternativ können Sie auch ampy verwenden. Eine kurze Anleitung finden Sie hier.

VSCode-Fans können ihr Glück mit der Extension Pico-Go versuchen.

Dessen ungeachtet ist Thonny aktuell sicherlich die einfachste Lösung.

Fazit und Bewertung

Zeit für ein erstes Fazit eine Woche nach der Inbetriebnahme des Pico! Im Vergleich zu anderen Micro-Controllern besticht der Pico durch die folgenden Vorteile:

  • Hohe Rechenleistung bei minimalem Preis
  • Einfache Programmierung mit MicroPython (C ist ebenfalls möglich, aber meist nicht notwendig)
  • Großartig geeignet für Spiel-, Schul-, und Bastelprojekte

Allerdings ist nicht alles Gold, was glänzt:

  • In der Praxis stark eingeschränkte Anwendbarkeit mangels WLAN
  • Version-1.0-Produkt (das ganze Umfeld inkl. Dokumentation wirkt noch nicht restlos ausgegoren)
  • Thonny spricht primär Einsteiger an (und ist, gelinde formuliert, nicht meine Traum-IDE)

Ich würde fast etwas darauf wetten, dass es innerhalb eines Jahres eine unwesentlich teurere Version 2 oder einen Pico+ geben wird, der mit WLAN (und evt. Bluetooth) sowie vielleicht mit ein, zwei integrierten Sensoren ausgestattet ist. Der angekündigte Arduino Nano RP2040 Connect erscheint mir diesbezüglich ein guter Maßstab; die Frage ist aber, um wie viel teuerer das Arduino-Konkurrenzprodukt im Vergleich zum Pico sein wird.

Quellen und Links

Sudokus mit Kotlin lösen

03. Februar 2021 um 21:51

Vielleicht liegt es an der merkwürdigen Corona-Zeit — auf jeden Fall hatte ich in den letzten Wochen eine Phase, in der ich fast täglich Sudokus löste. (Meine Quelle: https://www.derstandard.at/lifestyle/raetsel-sudoku.) Die Sudoku-Sucht hat schon wieder nachgelassen, aber Programmierer der ich nun einmal bin, fand sich gleich die nächste Herausforderung: Es kann doch nicht so schwierig sein, ein Programm zu schreiben, das Sudokus löst — oder? Natürlich weiß ich, das Internet ist voller Sudoku Solver. Es ging mir keineswegs darum, das Rad neu zu erfinden oder es noch runder zu machen — ich hatte einfach Lust auf ein paar Stunden Programmieren. Just for fun, nicht als Beispiel für ein Buch oder für den Unterricht …

Gesagt, getan. Wegen der Arbeit an meinem Kotlin-Buch ist mir die Sprache gerade sehr vertraut. Nach ein paar Stunden konnte mein Code bereits einfache Sudokus lösen. Der letzte Feinschliff dauerte dann doch etwas länger als gedacht, aber mittlerweile glaube ich, dass das Programm zuverlässig funktioniert.

Und weil es schade wäre, das fertige Programm nun einfach wieder in der Versenkung verschwinden zu lassen, habe ich es auf GitHub gestellt. Dieser Artikel dokumentiert kurz die Funktionsweise.

Programmaufbau

Der gesamte interessante Code befindet sich in der Klasse Sudoku. Diese ist wie folgt anzuwenden:

val test = """
        3192.....
        ......7.1
        ...63....
        67.8.35..
        9.......3
        ..21.5.47
        ....62...
        2.3......
        .....7259
    """.trimIndent()
val sudoku = Sudoku(test)
sudoku.plot()  // plot unsolved Sudoku
println(sudoku.solveRecursive())
sudoku.plot()  // plot solution

Der Konstruktor von Sudoku erwartet eine Zeichenkette, die in neun Zeilen die Ziffern des Sudokus enthält. Jedes Zeichen, das keine Ziffer ist, gilt als leeres Feld. Der Konstruktor initialisiert die Eigenschaft sudoku, eine verschachtelte Liste aus 9 x 9 Integerzahlen.

Der Schlüssel zur Lösung des Sudokus ist candidates: Dabei handelt es sich um eine weitere 9 x 9 Liste, deren Elemente jeweils ein Set mit allen Zahlen enthalten, die für ein leeres Feld des Sudokus in Frage kommen. Der Konstruktor löscht die Sets für alle bereits belegten Zellen und ruft dann eliminateCandidates auf. Dort werden aus jedem Set alle Zahlen entfernt, die sich in der gleichen Zeile, Spalte oder 3×3-Box befinden. Damit verbleiben die potentiellen Lösungskandidaten.

Die Methode plot gibt das Sudoku am Bildschirm aus. Es greift dabei auf die Klasse ColoredConsole zurück (siehe GitHub), die unkomplizierte Farbausgaben erlaubt.

// Enumeration mit möglichen solve()-Ergebnissen
enum class Result { Finished, Failure, Open; }

// Sudoku-Klasse
class Sudoku(data: String) {
    // sudoku: initally empty 9x9 list, to be initalized in constructor
    private val sudoku = List(9) { MutableList(9) { 0 } }

    // set of candidates for each cell of sudoku
    private var candidates =
        List(9) { MutableList(9) { mutableSetOf(1, 2, 3, 4, 5, 6, 7, 8, 9) } }

    // constructor
    init { ... 

    }

    // output current state of Sudoko including solved cells (bold, black)
    // and possible candidates (grey)
    fun plot(markrow: Int = -1, markcol: Int = -1) { ... }

    ...
}
Sudoku-Darstellung in IntelliJ. Die grauen Zahlen sind Lösungskandidaten.

Lösung Teil 1: »Naked Singles«

solve ruft in einer Schleife diverse Methoden auf, die das Sudoku Schritt für Schritt lösen. Die äußere do-while-Schleife endet, wenn keine Fortschritte mehr erzielt werden können.

// try to solve Sudoku (non-recursive)
fun solve(): Result {
    do {
        val todo = statusCellsOpen
        val options = statusCandidatesCount
        // call methods repeatedly, until they make no longer progress
        do while (findNakedSingle())
        do while (findHiddenSingleRow())
        do while (findHiddenSingleCol())
        do while (findHiddenSingleBox())
        // optimize candidate sets
        eliminatePairNumbers()
        eliminateBoxBlockingNumbers()
        // try again, until neither number unsolved sells
        // nor number of open candidates drop
    } while (statusCellsOpen < todo || statusCandidatesCount < options)

    return when {
        statusCellsOpen == 0   -> Result.Finished  // all done
        statusFailedCells > 0  -> Result.Failure   // empty cells without candidates
        else                   -> Result.Open      // uncertain
    }
}

Im ersten Schritt versucht das Programm, alle Naked Singles zu erkennen. Das sind Zellen, für die nur eine einzige Zahl in Frage kommt, weil alle anderen Zahlen in der Zeile, Spalte oder 3×3-Box bereits vorkommen. findNakedSingle durchsucht dazu einfach die Liste candidates nach Sets, die genau ein Element enthalten.

// loop over all candidate sets; if there is a set with exact one item
// set cell accordingly, recalculate candidates and return true;
// else: return false
private fun findNakedSingle(): Boolean {
    for (row in 0..8)
        for (col in 0..8)
            if (candidates[row][col].size == 1) {
                val nmb = candidates[row][col].toList()[0]
                setCell(row, col, nmb, "Naked Single")
                return true
            }

    return false
}  

Wenn findNakedSingle eine passendes Feld findet, wird die entsprechende Zahl in setCell in die Zelle eingetragen. setCell kümmert sich auch darum, die Kandidaten-Sets aller Zellen in der gleichen Zeile, Spalte und 3×3-Box zu aktualisieren. Optional (Variable debugShowPlot) ruft setCell auch plot aus. Damit können Sie dem Programm zusehen, wie es Schritt für Schritt das Sudoku löst. (Die jeweils zuletzt ausgefüllte Zelle wird rot markiert.)

»Naked Single«: Für die markierte Zelle kommt einzig der Wert 3 in Frage

Lösung Teil 2: »Hidden Singles«

Sobald solve keine Naked Singles mehr findet, geht es auf die Suche nach Hidden Singles. Dieser Begriff bezeichnet den Fall, dass es in einer Zeile, einer Spalte oder einer 3×3-Box nur eine einzige Zelle gibt, in der eine bestimmte Zahl in Frage kommt. Die drei Methoden findHiddenSingleRow, findHiddenSingleCol und findHiddenSingleBox suchen nach solchen Zellen.

»Hidden Single«: Die markierte Zelle ist die einzige in dieser Zeile, in der der Wert 1 in Frage kommt.

Lösung Teil 3: Paarweise Eliminierung

Direkt lassen sich jetzt keine Lösungszellen mehr finden. Es gibt aber noch Wege, die Kandidatensets zu minimieren. Das erste Verfahren besteht darin, in einer Zeile, einer Spalte oder einer 3×3-Box zwei identische Zahlenpaare zu suchen. In diesem Fall muss eine Zelle die eine Zahl aufnehmen, die andere Zelle die andere Zahl. Wir wissen aktuell noch nicht, welche Zahl in welcher Zelle landet — sicher ist aber, dass die betreffenden Zahlen in den verbleibenden Zellen der Zeile/Spalte/Box eliminiert werden können! Im Code kümmert sich die Methode eliminatePairNumbers genau darum.

Weil in zwei Zellen nur die Zahlen 2 oder 4 in Frage kommen, können diese Zahlen in den restlichen Zellen sicher nicht sein.

Lösung Teil 4: Box-Eliminierung

Ein weiteres Eliminiationsverfahren sieht so aus: Sie durchsuchen alle 3×3-Boxen, ob es dort eine Zahl gibt, die sicher in genau einer Zeile oder Spalte platziert werden muss. Auch wenn unklar ist, wo die Zahl genau landet — sicher ist, dass diese Zahl dann in den restlichen Zellen anderer Boxen der gleichen Zeile/Spalte nicht sein kann! Der entsprechende Code in eliminateBoxBlockingNumbers ist schon etwas komplizierter und greift auf diverse Hilfsfunktionen zurück (boxBlockAllInSameRow, boxBlockAllInSameCol, boxBlockAllInSameCol und boxBlockEliminateNumberInCol).

In der markierten 3×3-Box muss die 5 in der mittleren Zeile gesetzt werden. Daher kann die 5 nicht in den anderen Zellen dieser Zeile landen.

Sofern die beiden Eliminiationsverfahren die Anzahl der Lösungskandidaten reduziert haben, besteht eine gute Chance, dass es jetzt wieder Hidden oder Naked Singles gibt. solve beginnt deswegen in einer Schleife von vorne und sucht neuerlich nach Zellen, die jetzt eindeutig sind.

Lösung Teil 5: Versuch und Irrtum (sprich: Rekursion)

Bis einschließlich Teil 4 komme ich normalerweise, wenn ich Sudokus manuell löse. Bei schwierigen Sudokus kommt nun der Punkt, wo Logik nicht mehr weiter hilft: Man muss eine von zwei möglichen Varianten ausprobieren und im Kopf oder mit Stift und Papier herausfinden, ob es so weiter geht oder nicht. Ich gebe da in der Regel auf …

Für das Programm kommt Aufgeben aber natürlich nicht in Frage: solveRecursive ruft zuerst einmal solve auf, um das Sudoku so weit wie möglich zu lösen. Dann sucht es in den verbleibenden Kandidaten-Sets eines mit möglichst wenig Varianten aus. In der Praxis ist das fast immer ein Zweier-Set. Wenn Sie dem Programm ein vollkommen leeres Sudoku zur Lösung geben, dann muss es aber bei einem Neuner-Set zu raten beginnen.

Vom ausgewählten Set wählt das Programm die erste Variante, setzt die Zahl ins Sudoku ein und ruft nun wieder solveRecursive auf. Im Idealfall führt solve nun direkt zur Lösung — oder aber zu einem unlösbaren Sudoku. (Dieses ist erkennbar, weil es Zellen gibt, deren Kandidaten-Set leer ist.) Bei schwierigen Sudokus kann es aber auch passieren, dass es neuerlich keine »logische« Lösung gibt, dass der einzige Fortschritt wieder nur durch Probieren erzielt werden kann.

Bei meinen Tests hat der rekursive Algorithmus immer eine Lösung gefunden, wo eine existiert. Das Programm verschluckt sich auch nicht an Sudokus mit vielen Lösungsmöglichkeiten und liefert dann eben die (aus Sicht des Programms) erste.

Schlussbemerkungen

Mein Ziel mit der obigen Beschreibung war es, Sie so neugierig zu machen, dass Sie Lust verspüren, selbst einen Blick in den Code zu werfen. Den finden Sie auf GitHub.

Ich habe mich bemüht, den Code »lesbar« zu schreiben und in möglichst viele Einzelteile (Methoden) zu zerlegen. Der Code ist allerdings nicht auf Geschwindigkeit optimiert. Das ist auch gar nicht notwendig — er liefert die Lösung sowieso in Sekundenbruchteilen.

Quellen, Links

Raspberry Pi Pico

29. Januar 2021 um 16:12

Die Raspberry Pi Foundation hat Ihr neuesten Projekt vorgestellt: Trotz Namensähnlichkeiten handelt es sich beim »Raspberry Pi Pico« nicht um ein Mitglied der Mini-Computer-Serie (Raspberry Pi 1/2/3/4/400 A/B/Zero/Compute Model). Der Pico ist kein vollwertiger Computer samt Betriebssystem, sondern »nur« ein Micro-Controller.

Raspberry Pi Pico (Vorderseite)

Sie können auf dem Gerät selbst entwickelten Code ausführen und dabei über diverse GPIOs eine Menge Hardware-Schnittstellen ansteuern. Es gibt aber kein Grafiksystem samt Monitor-Ausgabe, keine Anschlüssel für Tastatur, Maus oder externe Datenträger, keinen Eingang für ein Kameramodul, keine Netzwerkfunktionen, kein WLAN, kein Bluetooth. Dafür punktet der Pico beim Preis (4 EUR) und beim Stromverbrauch (nur ca. 0,4 W, im Ruhemodus gar nur 0,006 W).

Der Pico ist also keine neue Variante zu den herkömmlichen Raspberry-Pis. Das Gerät spricht einen ganz anderen Markt an, der vor allem von Arduino dominiert wird, in dem sich aber diverse andere Hersteller tummeln. Im Vergleich zu anderen Microcontrollern will der Pico mit relativ viel Rechenleistung für wenig Geld punkten.

Hardware

Der Kern des Raspberry Pi Pico und gleichzeitig das Alleinstellungsmerkmal im Vergleich zur Konkurrenz ist der von der Raspberry Pi Foundation selbst entwickelte Microcontroller RP2040. Kurz die wichtigsten Eckdaten:

  • Dual-core Arm Cortex-M0+ mit bis zu 133MHz
  • 264 kB RAM
  • 2 MB interner Flash-Speicher
  • 8 programmierbare I/O State Machines (PIOs)
  • 30 GPIOs mit Mehrfachfunktion (am Pico sind 26 davon verfügbar), davon 4 Analogeingänge (am Pico sind 3 davon verfügbar)
  • USB 1.1 inkl. USB Mass-Storage-Unterstützung (d.h., Geräte mit dem RP2040 können zur Programmierung wie ein USB-Stick genutzt werden)

Der RP2040 ermöglicht einen Zugriff auf bis zu 16MB externen Flash-Speicher (QSPI-Bus) und verfügt über einen DMA-Controller.

Über die 26 General Purpose Input/Output Pins (kurz GPIOs) können die folgenden Funktionen bzw. Bussysteme genutzt werden:

  • 3x Analog-Eingang (12 Bit Auflösung)
  • 16x PWM-Ausgang
  • 2x SPI-Bus (Serial Peripheral Interface)
  • 2x I2C-Bus (Inter-Integrated Circuit)
  • 2x UART (serielle Schnittstelle)
Pin-Layout des Raspberry Pi Pico (Quelle: Raspberry Pi Foundation)

Die GPIOs sind auf einen Betrieb mit 3,3 V ausgelegt (nicht 5V!).

Der Pico verfügt über einige weitere Anschlusspins, die zur Stromversorgung sowie zum Debugging dienen. Auf der Platine des Picos befindet sich außerdem eine programmierbare Leuchtdiode sowie ein kleiner Taster zur Auswahl zwischen zwei Boot-Modi. (Details dazu folgen bei der Überschrift »Programmierung«.)

Zur Programmierung sowie zur Stromversorgung gibt es einen Micro-USB-Eingang. Alternativ kann die Stromversorgung des Picos auch über die Kontakte der Platine erfolgen, wobei die Eingangsspannung zwischen 1,8 und 5,5 V liegen muss.

Raspberry Pi Pico (Rückseite)

Der größte offensichtliche Nachteil des Picos ist das Fehlen von WLAN-Funktionen. Damit wäre der Einsatzbereich ungleich größer. Es würde mich nicht überraschen, wenn spätestens in einem Jahr der Pico+ oder Pico 2 vorgestellt würde, der genau in diesem Punkt nachgebessert ist (vielleicht auch gleich samt Bluetooth-Unterstützung).

Programmierung

Der RP2040 ist für die Programmierung im Python-Dialekt MicroPython gedacht. Die Raspberry Pi Organisation empfiehlt den Einsatz von Thonny als Entwicklungsumgebung.

Alternativ können Programme auch in C entwickelt werden. In diesem Fall empfiehlt die RP-Organisation VSCode als IDE. Speziell für den Pico entwickelte Plugins sorgen für den (einigermaßen) reibungslosen Transfer von Code.

Der Pico ist sogar in der Lage, eine Portierung von TensorFlow Lite auszuführen (GitHub).

Der RP2040 (bzw. der zugrundeliegende Cortex M0+) kann nur mit ganzzahligen Zahlen rechnen; es gibt aber eine lizensierte Fließkommabibliothek auf der Basis von Qfplib.

Zwei Debugging-Pins ermöglichen die Verwendung eines externen Debuggers (siehe Kapitel 5 von Getting Started with C/C++ (PDF)). Deren Nutzung gelingt am einfachsten, wenn der Pico mit einem gewöhnlichen Raspberry Pi (z.B. Modell 4B) verbunden wird.

In Zukunft soll auch die Arduino-IDE den RP2040 unterstützen.

Hello MicroPython!

Für den RP2040 gibt es eine MicroPython-Implementierung, die in den Grundfunktionen kompatibel zu Python 3.4 ist (plus async und await aus Python 3.5). Um MicroPython am Pico auszuprobieren, laden Sie am einfachsten ein vorkompiliertes Binary herunter (Dialogblatt »Getting startet with MicroPython«, Button »Donwload UF2 file«):

https://www.raspberrypi.org/documentation/pico/getting-started/

Das USB Flashing Format (UF2) ist ein von Microsoft entwickeltes Format, das speziell dazu gedacht ist, Microcontroller über eine USB-Mass-Storage-Schnittstelle zu programmieren (»flashen«). Die Datei ist ca. 0,5 MByte groß.

Nun stecken Sie ein USB-A-zu-Micro-USB-Kabel oder USB-C-zu-Micro-USB in Ihren Pico, drücken den winzigen Taster und verbinden dann das Kabel mit Ihrem Computer. (Die Raspberry Pi Foundation empfiehlt, den Pico mit einem Raspberry Pi zu verbinden. Die Inbetriebnahme des Picos kann aber auch mit einem PC oder Notebook unter Linux, Windows oder macOS erfolgen. Ich habe meine Tests auf einem Notebook unter Linux durchgeführt.)

Der Pico erscheint als USB-Massenspeicher im Dateimanager

Per Drag&Drop kopieren Sie jetzt die UF2-Datei vom Download-Verzeichnis in den USB-Speicher des Pico. Sobald die Übertragung beendet ist, bootet der Pico neu. Der Eintrag »RPI-RP2« verschwindet aus der Seitenleiste des Dateimanagers. Der Pico läuft jetzt nicht mehr als USB-Speichergerät, sondern führt MicroPython aus. Für den Computer erscheint der Pico als serielles USB-Gerät. Unter Linux können Sie das unkompliziert mit lsusb verifizieren:

lsusb

  Bus 001 Device 012: ID 2e8a:0005 MicroPython Board in FS mode 
  ...

Um im Terminal mit dem Pico zu kommunizieren, installieren Sie das Programm minicom. Anschließend starten Sie es wie folgt:

sudo minicom -o -D  /dev/ttyACM0

(sudo ist erforderlich, weil Sie als gewöhnlicher Benutzer bei den meisten Linux-Distributionen keine Zugriffsrechte auf die Device-Datei ttyACM0 haben. Auf die Dauer ist es aber keine gute Idee, minicom ständig mit sudo zu starten. Besser ist es, wenn Sie Ihren Benutzer-Account zur Gruppe dialout hinzufügen. In meinem Fall geht das so: sudo usermod -a -G dialout kofler. Sie müssen natürlich kofler durch Ihren Accountnamen ersetzen. Damit die Einstellung wirksam wird, müssen Sie sich aus und neu einloggen.)

minicom kommuniziert mit dem Pico, wo ein Python-Interpreter läuft (REPL)

Sobald Sie einmal Return drücken, sollten Sie den Kommando-Prompt >>> des Python-Interpreters sehen. Sie können nun erste Kommandos interaktiv ausführen:

>>> print("Hello, Pico!")
  Hello, Pico!

Mit from machine import Pin importieren Sie das Modul machine zum Zugriff auf die GPIO-Funktionen. Pin 25 ist mit der Leuchtdiode des Picos verbunden. Die folgenden Kommandos schalten die Leuchtdiode zuerst ein und dann aus:

>>> from machine import Pin
>>> led = Pin(25, Pin.OUT)
>>> led.value(1)
>>> led.value(0)

Um minicom zu beenden, drücken Sie Strg+A und danach X. Einen Überblick über die Tastenkürzel von minicom gibt Strg+A und Z.

Pico-Alternativen mit dem RP2040

Der Pico ist das erste Gerät mit dem RP2040. Die Raspberry Pi Organisation wird den Chip aber nicht exklusiv verwenden. Vielmehr wollen andere Hersteller in den nächsten Wochen/Monaten eigene Microcontroller-Boards auf der Basis des RP2040 vorstellen. Das Blog der RP Foundation listet diverse Boards von Adafruit, Arduino, Pimoroni unnd SparFun auf. Besonders interessant klingt das Board Arduino Nano RP2040 Connect, das ähnliche Funktionen wie der Pico bieten soll, aber außerdem 16 MByte Flash-Speicher, WLAN, Bluetooth, ein Mikrofon und einen 9-Achsen-Bewegungssensor enthält. Arduino hat allerdings noch keine Angaben zum Preis gemacht, der sicher höher als beim Pico ausfällt.

Quellen

Raspberry Pi Pico

Dokumentation

Alternative Systeme

Docker ohne root-Rechte

04. Januar 2021 um 14:05

Als größter Vorteil von Podman im Vergleich zu Docker wird üblicherweise die Funktion bewertet, Container ohne root-Rechte auszuführen. Übersehen wird, dass Docker seit Version 19.03 ebenfalls für den rootless-Einsatz geeignet ist; das Feature galt in dieser Version aber als experimentell und war mit erheblichen Einschränkungen verbunden. Deutlich besser sieht das in der aktuellen Version 20.10 aus: der Betrieb von Docker-Containern ohne root-Rechte ist nun eine reguläre Funktion. Bemerkenswert ist, dass die Installation von Docker innerhalb eines Benutzeraccounts erfolgt und ebenfalls ohne root-Rechte gelingt!

Installation

Für meine Tests habe ich Oracle Linux 8 verwendet. Die folgende Installationsanleitung sollte unverändert auch unter RHEL 8, unter anderen RHEL-Klones sowie unter anderen Distributionen funktionieren. (Die offizielle rootless-Docker-Anleitung listet einige distributionsspezifische Voraussetzungen auf und empfiehlt Ubuntu als Basisdistribution.)

Mit dem Script rootless wird Docker lokal in einem Benutzeraccount installiert. Eine systemweite Docker-Installation ist nicht erforderlich! Das folgende Kommando ist in einem normalen Benutzeraccount ohne root-Rechte und ohne sudo auszuführen!

curl -fsSL https://get.docker.com/rootless | sh

  # Installing stable version 20.10.1
  ...
  PATH=/home/kofler/bin:/home/kofler/.local/bin:/home/kofler/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
  /home/kofler/bin/dockerd-rootless-setuptool.sh install
  Creating /home/kofler/.config/systemd/user/docker.service
  starting systemd service docker.service

  + systemctl --user start docker.service
  + sleep 3
  + systemctl --user --no-pager --full status docker.service
    docker.service - Docker Application Container Engine (Rootless)
    ...
  + DOCKER_HOST=unix:///run/user/1000/docker.sock
  + /home/kofler/bin/docker version
    Client: Docker Engine - Community
      Version:           20.10.1
    Server: Docker Engine - Community
       Engine:
         Version:          20.10.1
         ...
       containerd:
         Version:          v1.4.3
         ...
  + systemctl --user enable docker.service

  Installed docker.service successfully.
  To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
  To run docker.service on system startup, run: `sudo loginctl enable-linger kofler`

  Make sure the following environment variables are set (or add them to ~/.bashrc):

  export PATH=/home/kofler/bin:$PATH
  export DOCKER_HOST=unix:///run/user/1000/docker.sock

Unter Oracle Linux ist PATH bereits korrekt voreingestellt. Die Definition der DOCKER_HOST-Variable ist aber vor dem ersten Start von docker erforderlich und muss für später auch in .bashrc eingetragen werden (oder in .zshrc, falls Sie die ZSH verwenden).

export DOCKER_HOST=unix:///run/user/1000/docker.sock
echo "export DOCKER_HOST=unix:///run/user/1000/docker.sock" >> .bashrc

Ein kurzer Test beweist, dass alles funktioniert:

docker run hello-world
  Unable to find image 'hello-world:latest' locally
  latest: Pulling from library/hello-world

  Hello from Docker!
  This message shows that your installation appears to be working correctly.
  ...

Die von Docker angelegten Images, Container usw. landen im Verzeichnis .local/share/docker.

Hinweis: Um es nochmals klarzustellen: Zur Verwendung von Docker im rootless-Modus ist keine Docker-Installation auf Systemebene erforderlich. Prinzipiell macht es aber nichts, wenn eine derartige Installation bereits vorliegt — dann gibt es eben zwei Docker-Installationen, eine lokale für den rootless-Modus und eine systemweite für die Anwendung von Docker durch andere Benutzer bzw. root.

docker-compose

Um auch docker-compose lokal zu installieren, führen Sie die folgenden Kommando aus, wobei Sie 1.27.4 durch die gerade aktuelle Version ersetzen (siehe hier):

cd
curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" \
  -o bin/docker-compose
chmod +x bin/docker-compose

Fazit

Bei meinen Tests haben docker und docker-compose überraschend problemlos rootless funktioniert. Unter anderem habe ich mit docker-compose mein aus LaTeX und Pandoc bestehendes Satzsystem getestet. Es besteht aus drei Container, die parallel ausgeführt werden und sich darum kümmern, meine Markdown-Texte und PNG-Bilder in eine (fast) druckfertige PDF-Datei umzuwandeln.

Beachten Sie aber, dass es nach wie vor Einschränkungen gibt. Diese kommen insbesondere dann zum Tragen, wenn Docker Änderungen an der Netzwerkkonfiguration durchführen möchte, die root-Rechte erfordern.

Quellen

Drei ebooks.kofler-Titel jetzt kostenlos erhältlich

03. Januar 2021 um 08:14

Im Oktober 2020 habe ich den Betrieb von ebooks.kofler eingestellt. Ab sofort können Sie drei E-Books kostenlos herunterladen:

Die kurze Geschichte von ebooks.kofler ist hier nachzulesen.

CentOS 8: Umstieg auf CentOS Stream bzw. auf Oracle Linux

11. Dezember 2020 um 22:29

Sowohl CentOS als auch Oracle bieten Scripts an, um eine vorhandene CentOS-8-Installation wahlweise in CentOS Stream oder in Oracle Linux umzubauen. Ich habe also eine virtuelle Maschine mit einer ca. ein Jahr alten Installation von CentOS 8 zuerst aktualisiert und dann zweimal geklont. In der Ausgangs-VM waren ein MySQL-Server installiert, EPEL aktiviert und vereinzelte EPEL-Pakete installiert. Einen Klon habe ich anschließend in CentOS Stream umgewandelt, den anderen in Oracle Linux.

Warnung: Es sollte klar sein, dass dies ein sehr simpler Test ist, nicht mehr! Ich habe kein produktives System umgestellt, sondern nur eine einfache Testumgebung.

Umstieg auf CentOS Stream

Die Umstellung auf CentOS Stream erfolgt kurz und schmerzlos. CentOS ade …

yum install centos-release-stream
yum swap centos-{linux,stream}-repos
yum distro-sync
reboot

Dabei werden die Paketquellen von CentOS auf CentOS Stream umgestellt und eine Menge Pakete ersetzt. Der Vorgang ist in einigenMinuten abgeschlossen. Ein kurzer Test zeigt:

uname -a

  Linux c8stream 4.18.0-257.el8.x86_64 #1 SMP 
  Thu Dec 3 22:16:23 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

cat /etc/os-release 

  NAME="CentOS Stream"
  VERSION="8"
  ID="centos"
  ID_LIKE="rhel fedora"
  VERSION_ID="8"
  PLATFORM_ID="platform:el8"
  PRETTY_NAME="CentOS Stream 8"
  ANSI_COLOR="0;31"
  CPE_NAME="cpe:/o:centos:centos:8"
  HOME_URL="https://centos.org/"
  BUG_REPORT_URL="https://bugzilla.redhat.com/"
  REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux 8"
  REDHAT_SUPPORT_PRODUCT_VERSION="CentOS Stream"

ls /etc/yum.repos.d/

  CentOS-Stream-AppStream.repo  CentOS-Stream-HighAvailability.repo  epel-modular.repo          epel.repo
  CentOS-Stream-BaseOS.repo     CentOS-Stream-Media.repo             epel-playground.repo
  CentOS-Stream-Debuginfo.repo  CentOS-Stream-PowerTools.repo        epel-testing-modular.repo
  CentOS-Stream-Extras.repo     CentOS-Stream-RealTime.repo          epel-testing.repo

Umstieg auf Oracle Linux

Ähnlich unkompliziert gelingt der Umstieg auf Oracle Linux. Auf der GitHub-Seite des Scripts ist nachzulesen, dass zumindest 5 GB Platz im Verzeichnis /var/cache erforderlich sind. Außerdem sollten vor dem Wechsel sämtliche externe Paketquellen deaktiviert werden. (Ich habe EPEL belassen, Probleme haben sich dadurch — zumindest in meinem Fall — keine ergeben.)

yum install git
git clone https://github.com/oracle/centos2ol.git
bash centos2ol/centos2ol.sh
reboot

Nach einigen Minuten ist auch in diesem Fall der Spuk vorbei. Ein kurzer Test zeigt, dass ein anderer Kernel läuft und /etc/os-release aktualisiert ist. Beachten Sie, dass Oracle nicht wie CentOS 8 / RHEL 8 auf den relativ alten Kernel 4.18 setzt, sondern den vergleichsweise modernen Kernel 5.14.

uname -a

  Linux c8oracle 5.4.17-2036.100.6.1.el8uek.x86_64 #2 SMP 
  Thu Oct 29 17:06:00 PDT 2020 x86_64 x86_64 x86_64 GNU/Linux

cat /etc/os-release

  NAME="Oracle Linux Server"
  VERSION="8.3"
  ID="ol"
  ID_LIKE="fedora"
  VARIANT="Server"
  VARIANT_ID="server"
  VERSION_ID="8.3"
  PLATFORM_ID="platform:el8"
  PRETTY_NAME="Oracle Linux Server 8.3"
  ANSI_COLOR="0;31"
  CPE_NAME="cpe:/o:oracle:linux:8:3:server"
  HOME_URL="https://linux.oracle.com/"
  BUG_REPORT_URL="https://bugzilla.oracle.com/"
  ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8"
  ORACLE_BUGZILLA_PRODUCT_VERSION=8.3
  ORACLE_SUPPORT_PRODUCT="Oracle Linux"
  ORACLE_SUPPORT_PRODUCT_VERSION=8.3

ls /etc/yum.repos.d

  CentOS-Linux-AppStream.repo.disabled          CentOS-Linux-HighAvailability.repo.disabled  epel-testing-modular.repo
  CentOS-Linux-BaseOS.repo.disabled             CentOS-Linux-Media.repo.disabled             epel-testing.repo
  CentOS-Linux-ContinuousRelease.repo.disabled  CentOS-Linux-Plus.repo.disabled              epel.repo
  CentOS-Linux-Debuginfo.repo.disabled          CentOS-Linux-PowerTools.repo.disabled        oracle-linux-ol8.repo
  CentOS-Linux-Devel.repo.disabled              CentOS-Linux-Sources.repo.disabled           uek-ol8.repo
  CentOS-Linux-Extras.repo.disabled             epel-modular.repo
  CentOS-Linux-FastTrack.repo.disabled          epel-playground.repo

Vorsicht: Das Script centos2ol.sh funktioniert für CentOS 8, aber nicht für CentOS Stream 8! Ein CentOS-Installation, die Sie einmal auf CentOS Stream umgestellt haben, können Sie später nicht mehr auf Oracle Linux umstellen!

CentOS 8

Zum Vergleich die Kernel-Version und /etc/centos-release bei einer regulären CentOS-8-Installation (Stand 11.12.2020, Ablaufdatum 31.12.2021):

uname -a

  Linux centos8 4.18.0-240.1.1.el8_3.x86_64 #1 SMP 
  Thu Nov 19 17:20:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

cat /etc/os-release 

  NAME="CentOS Linux"
  VERSION="8"
  ID="centos"
  ID_LIKE="rhel fedora"
  VERSION_ID="8"
  PLATFORM_ID="platform:el8"
  PRETTY_NAME="CentOS Linux 8"
  ANSI_COLOR="0;31"
  CPE_NAME="cpe:/o:centos:centos:8"
  HOME_URL="https://centos.org/"
  BUG_REPORT_URL="https://bugs.centos.org/"
  CENTOS_MANTISBT_PROJECT="CentOS-8"
  CENTOS_MANTISBT_PROJECT_VERSION="8"

Erfahrungen

Ehrlicherweise muss ich zugeben, dass ich zur Stabilität der neuen Systeme momentan gar nichts sagen kann. Auf den ersten Blick funktioniert alles, alle drei Systeme (Original CentOS 8, CentOS 8 Stream und Oracle Linux) booten und tun dann, was sie sollen. Der Test beweist immerhin, dass ein Wechsel prinzipiell möglich ist. Ob er Wechsel auch bei realen Systemen, womöglich mit diversen Fremdpaketen, so mühelos ist, wird demnächst sicher im Internet nachzulesen sein.

Glücklicherweise bin ich selbst nicht in der Verlegenheit, dass ich ein »reales« CentOS-8-System umstellen muss. Der Start von CentOS 8 war — gelinde gesagt — holprig. Insofern habe ich zuerst einmal abgewartet; vor drei Monaten habe ich dann beschlossen, dass ich meinen Linux-Unterricht im kommenden Sommersemester mit Oracle Linux machen würde. Und jetzt ist CentOS ohnehin Geschichte.

Ich habe mir auf jeden Fall vorgenommen, in den nächsten Wochen hin und wieder einen Blick auf meine Klon-Babies zu werfen und speziell auf die Update-Versorgung zu achten :-)

Erfahrungen 2: Das sudo-Update für CVE-2021-3156

Am 26.1.2021 wurde ein gravierender Fehler in sudo bekannt (Details 1, Details 2). Am 21.1.2021 9:00 habe ich nachgesehen, für welche RHEL-ähnliche Distributionen es bereits Updates gibt.

  • CentOS 8 Stream: ja
  • CentOS 8: nein jetzt auch (27.1.)
  • CentOS 7: ja
  • Oracle Linux 8: ja

Fazit

Welche Konsequenzen der CentOS-Exit längerfristig haben wird, muss sich erst weisen.

  • Ist das ehemals experimentelle CentOS Stream tatsächlich so stabil, wie es uns die Red-Hat-Leute plötzlich versprechen — quasi das bessere CentOS, von dem wir immer träumten? (Ich bin skeptisch, aber vielleicht bin ich zu pessimistisch. Aber mit einem EOL 2024 ist die Stabilität wahrscheinlich ziemlich egal.)
  • Nimmt Oracle jetzt die Chance war, sich als Retter der CentOS-Welt zu etablieren? (Ehrlicherweise muss man ja sagen, dass von den Millionen aktiven CentOS-Servern die meisten noch immer CentOS 7 verwenden. Deren Administratoren haben noch Zeit mit ihren Zukunftsplänen.)

  • Werden neue RHEL-Klone den Markt beleben?

  • Wechseln Red-Hat-Fans jetzt in Scharen zu Debian und Ubuntu? (Glaube ich persönlich nicht, aber wer weiß?)

Nur eines ist sicher: Mit Linux wird es nie langweilig …

Quellen

Nachruf auf CentOS

08. Dezember 2020 um 19:06

CentOS ist/war ein freier Klon von Red Hat Enterprise Linux (RHEL). Die vorige Version CentOS 7 läuft auf unzähligen Servern und Cloud-Instanzen. CentOS 7 war nie perfekt (bei Versionswechseln gab es Lücken in der Update-Versorgung, typischerweise im Bereich weniger Wochen), aber für viele war es gut genug — für den Produktivbetrieb kleiner Server, für den Unterricht, oder einfach, um ein RHEL-kompatibles Betriebssystem kennenzulernen.

Im September 2019 wurde das aktuelle CentOS 8 auf der Basis von RHEL 8 vorgestellt — und damit beworben, dass es vorausschtlich bis Mai 2029 gewartet werden würde. Heute hat das CentOS-Projekt allerdings verkündet, dass die Zukunft CentOS Stream heißt. Das klingt besser, als die Wahrheit zu sagen: CentOS, wie die Linux-Gemeinde es kannte, ist tot. CentOS 7 wird noch bis zum geplanten Support-Ende im Juni 2024 gewartet. CentOS 8 wird Ende 2021 eingestellt. Danach wird es noch CentOS 8 Stream geben, das aber das »echte« CentOS nicht ersetzen kann.

Hintergründe

Ich habe über CentOS in meinen Büchern und in diesem Blog schon viel geschrieben, aber für alle, die die Geschichte von CentOS nicht im Kopf haben, ein paar Hintergründe:

Red Hat Enterprise Linux (RHEL) ist die marktführende kommerzielle Linux-Distribution. RHEL ist ein großartiges, aber auch relativ teures Produkt. Red Hat bietet keine kostenlose RHEL-Version an. (Ja, es gibt Evaluations- und Developer-Versionen, aber die sind mit erheblichen Einschränkungen verbunden.)

Da RHEL aus Open-Source-Software besteht, ist es möglich und auch erlaubt, den Quellcode von der Red-Hat-Website herunterzuladen, im Code ‚Red Hat‘ durch einen anderen Namen zu ersetzen und das Ganze als eigene Distribution anzubieten. (In der Praxis ist das alles wesentlich komplizierter, als es hier klingt. Das eigentliche Problem besteht darin, dass dieser Prozess für jedes Paket-Update wiederholt werden muss.)

In der Vergangenheit gab es mehrere Organisationen bzw. Firmen, die sich die Mühe machten, einen Red-Hat-Klon anzubieten und dauerhaft zu warten — insbesonder Oracle, Scientific Linux und eben CentOS:

  • Bei weitem am bekanntesten und erfolgreichsten war CentOS. 2014 wurde das CentOS-Projekt von Red Hat übernommen. Das stieß anfangs auf große Skepsis, hat aber eine Weile gut funktioniert. Gewissermaßen bezahlte Red Hat ein kleines Team dafür, RHEL Konkurrenz im eigenen Haus zu machen. Das konnte wohl nicht auf Dauer gut gehen.
  • Scientific Linux, ein für den wissenschaftlichen Einsatz optimierter RHEL-Klon, ist zwar noch aktiv, unterstützt aber nur Version 7. Scientific Linux hat sich wegen des großen Aufwands dagegen entschlossen, auch RHEL 8 zu klonen. CentOS schien alles zu bieten, was man im wissenschaftlichen Umfeld brauchte.

  • Oracle bietet schließlich einen RHEL-Klon an, und zwar sowohl kommerziell als auch kostenlos. Oracle hat sich in der Vergangenheit relativ wenig Mühe gemacht, die freie Oracle-Linux-Ausgabe offensiv zu bewerben. Insofern fristete Oracle Linux, abseits von bezahlten Installationen, eher ein Schattendasein. Möglicherweise ändert sich das jetzt.

Alle drei Klone hatten das gleiche Problem: Jedesmal, wenn Red Hat eine neue Major oder Minor-Version vorstellte, mussten viele Pakete auf einmal aktualisiert werden. Das dauerte geraume Zeit (siehe die Wikipedia-Links am Ende des Artikels), während der die Anwender des jeweiligen Klons keine Updates mehr erhielten. Bei weitem am schnellsten war in dieser Disziplin Oracle: die Update-Lücken betrugen in der Regel nur 8 bis 10 Tage.

Bei Version 7 war auch CentOS einigermaßen gut; die Lücken in der Update-Versorgung betrugen typischerweise vier bis fünf Wochen. Mit Version 8 stiegen diese Zeiten aber dramatisch an (siehe auch meinen Blog-Beitrag CentOS 8: Wertlose Langzeitunterstützung). Ich hatte schon damals das Gefühl, dass Red Hat CentOS zu Tode sparen würde.

Eine wesentliche Neuerung im Zusammenhang mit CentOS 8 war eine Aufsplittung des Projekts: Seit gut einem Jahr gab es zwei Zweige von CentOS 8: Das »normale« CentOS sowie CentOS Stream. Letzteres ist eine experimentelle Variante von CentOS, die Red Hat dazu dient, neue Software-Versionen zu testen, bevor sie in RHEL übernommen werden. Im Vergleich zum normalen CentOS hat CentOS Stream Vor- und Nachteile. Der Vorteil besteht darin, dass CentOS Stream stets kontinuierlich gewartet wurde, also nie so großen Lücken in der Update-Versorgung auftraten. Der Nachteil: Für den Produktivbetrieb ist der Einsatz von Programmversionen, die nicht restlos stabil sind, nicht zielführend.

Das Ende von CentOS

Heute haben das CentOS-Projekt und Red Hat also das Ende von CentOS 8 in seiner bisherigen Form verkündet — in der Mailing-Liste und in den jeweiligen Blogs:

Kurz zusammengefasst:

  • CentOS 7 wird bis zum End-of-Life 2024 weitergeführt.
  • CentOS 8 wird Ende 2021 eingestellt.

  • Die Zukunft heißt CentOS 8 Stream, also der experimentelle Ableger von CentOS. Das ist ein interessantes Angebot, aber kein Ersatz für das »echte« CentOS. Laut Aussagen in der CentOS-Mailing-List hat es zudem ein End-of-Life im Mai 2024. Dann wird es CentOS 9 Stream geben.

Im Klartext heißt das: Es gibt kein CentOS mehr, das für den Produktiveinsatz geeignet ist. (Es ist in der Vergangenheit schon viel darüber diskutiert worden, ob CentOS je für den Produktiveinsatz vorgesehen war. Ich war stets der Ansicht: Für viele kleine Anwendungen war CentOS »gut genug«.)

An sich ist die offizielle Verkündung, dass CentOS 8 Ende 2021 eingestellt wird, nur der letzte Akt. Aufgrund der verrückt langen Update-Lücken während des letzten Jahres habe ich meine in der aktuellen Auflage des Linux-Buchs enthaltene Empfehlung für CentOS auf meiner Website schon vor Monaten zurückgezogen. Aus meiner Sicht war schon vor einem halben Jahr klar, dass CentOS in der aktuellen Form keine Zukunft hat. Insofern muss man Red Hat bzw. dem CentOS-Projekt dankbar sein, dass jetzt Klartext gesprochen wird.

In der CentOS-Mailing-Liste wird aber zurecht das äußerst unglückliche Timing kritisiert. Vor gut einem Jahr wurde CentOS 8 vorgestellt. Wer seither Server-Installationen durchgeführt hat, steht jetzt komplett im Regen. Weitaus ehrlicher wäre es gewesen, wenn man schon im September 2019 ganz auf CentOS Streams gesetzt hätte und das klassische CentOS 8 nie angeboten hätte.

Noch ein paar Worte zur Frage, ob CentOS Stream kein großartiger Ersatz für das ehemalige CentOS ist: Ich bezweifel das. Natürlich ist CentOS Streams nicht so experimentell wie Fedora. Das CentOS-Team wirbt sogar damit, dass Probleme in manchen Fällen früher behoben werden, weil die Bugfixes zuerst in CentOS Stream getestet werden, bevor sie auch in RHEL freigegeben werden. Aber damit ist CentOS Streams eben nicht der total stabile RHEL-Klon. CentOS Streams ist ein Ersatz für Leute, die Erfahrung mit einer RHEL-nahen Linux-Distribution machen wollen. CentOS Streams ist ideal für Entwickler bei Red Hat oder im Red-Hat-Umfeld. Aber: CentOS Streams ist nicht für den Produktivbetrieb gedacht.

Die Bedeutung von CentOS

Wird der Linux-Gemeinde CentOS überhaupt fehlen? Ich fürchte, die Tragweite des Verlusts ist den meisten Linux-Fans noch nicht klar! CentOS war für viele Administratoren der Einstieg in die Server-Welt. CentOS ermöglichte es, RHEL kennenzulernen, ohne dafür zu zahlen. Große Banken, Versicherungen usw. haben natürlich das Original, also RHEL eingesetzt. Aber für die vielen »kleinen Fische«, die einen stabilen Web- und Mail-Server für den Firmenauftritt betreiben wollten, war CentOS eine gute Wahl.

Ich habe keine seriöse Statistik gefunden, wie viele aktive CentOS-Installationen es aktuell gibt. Meine Vermutung ist, dass es Millionen sind. Laut w3techs.com laufen 5,3 Prozent aller Websites, deren Betriebssystem bekannt ist, mit CentOS. Man kann über die genaue Prozentzahl streiten, aber klar ist: Es gibt sehr viele aktive CentOS-Installationen.

Der vielleicht wichtigste Grund für die Marktdurchdringung von CentOS besteht darin, dass Hosting-Unternehmen und Cloud-Unternehmen die Installation von CentOS extrem einfach machen. Ein paar Klicks, schon läuft eine neue CentOS-Instanz. CentOS hat sich über viele Jahre einen ausgezeichneten Ruf erworben. Wozu Oracle Linux oder Scientific Linux anbieten, wenn die meisten Admins sowieso CentOS haben wollen?

Um etwas persönlicher zu werden: Ich habe CentOS geliebt. Ich habe lange damit geliebäugelt, ein eigenes Buch zu CentOS zu schreiben. CentOS war über viele Jahren die Distribution, die ich im Unterricht verwendet habe (»Linux-Systemadministration« an der FH in Kapfenberg). Ich werde CentOS vermissen. Und mir ist klar, wie viel (oft unbedankte) Arbeit das CentOS-Team in den vergangenen Jahrzehnten geleistet hat, um CentOS zu dem zu machen, was es lange Zeit war: Die beste kostenlose Server-Distribution. Danke dafür!

Freier Linux-Server, wo bist du?

Die Auswahl an freien Linux-Distributionen, die über mehrere Jahre im Produktiveinsatz laufen können, ist klein geworden. Aus meiner Sicht am attraktivsten sind heute:

  • Debian
  • Oracle Linux
  • Ubuntu LTS

Zu Debian und Ubuntu brauche ich hier nicht viel sagen. Beide Distributionen sind ebenso solide wie beliebt. Für Ubuntu LTS spricht die klarere Kommunikation über die Wartungszeiträume: main-Pakete werden fünf Jahre gewartet. Gegen Ubuntu spricht, dass viele durchaus wichtige Pakete eben nicht in der main-Paketquelle sind. Persönlich administriere ich etliche Ubuntu-Server-Installationen und bin prinzipiell sehr zufrieden. Aber obwohl fünf Jahre eine schöne Zeitspanne sind, wären mir sieben Jahre eigentlich lieber. So muss ich meine Server alle vier Jahre neu aufsetzen oder ein Major Update durchführen. Beides mache ich ungern.

Wer in der Red-Hat-Welt bleiben will, aber das erforderliche Budget nicht aufbringen kann, für den ist ab heute Oracle Linux klar die beste Wahl. Ich hoffe, Oracle sieht das Ende von CentOS als Chance, bewirbt sein freies Angebot offensiv und gibt vielleicht ein Versprechen ab, dass Oracle Linux auch in Zukunft frei bleiben wird.

Leider ist auch eine andere Zukunft vorstellbar: Oracle könnte sich jetzt auch auf sein kommerzielles Angebot konzentrieren, sinngemäß: »Wie sind kompatibel zum Original, aber kostengünstiger.« Ein freies Oracle Linux ist diesbezüglich geschäftsschädigend, so wie ein freies, gut funktionierendes CentOS offensichtlich auch Red Hat ein zu großer Dorn im Auge war.

Ade, CentOS! Hoffen wir, dass die Auswahl freier Linux-Server-Distributionen nicht noch kleiner wird.

Nachtrag 10.12.2020: Wenig überraschend gibt es bereits Ideen, neue RHEL-Klone zu bauen:

Es ist aktuell nicht abzusehen, ob bzw. welche dieser Initiativen von Erfolg gekrönt sein wird. Es mag technisch nicht so kompliziert sein, einen RHEL-Klon zu produzieren, aber es ist langfristig mit riesigem Aufwand verbunden. Es müssen dauerhaft einige Entwickler bezahlt werden, ebenso die Server-Infrastruktur. Die Anwender müssen Vertrauen zu dem neuen Projekt gewinnen. Über Nacht ist da also nichts zu machen.

Quellen/Links

Oracle

Scientific Linux

Rocky Linux, AlmaLinux

Raspberry Pi 400

02. Dezember 2020 um 18:08

Seit einem Monat gibt es den Raspberry Pi in einer Desktop-Ausführung. Das Gerät ist in eine Tastatur integriert, was Erinnerungen an die Home-Computer-Zeit wach werden lässt. Der Computer wird nicht zufällig mitten in der Corona-Epidemie ausgeliefert: Die Raspberry-Pi-Foundation hofft, dass das Gerät kostengünstig für das Home Schooling verwendet werden kann.

Heute ist der vor genau einem Monat bestellte Raspberry Pi 400 endlich eingetroffen. Der erste Eindruck: Eine verblüffend große, schwere Schachtel. Das Gewicht erklärt sich durch das beigelegte Einsteigerhandbuch, die Größe durch die vielen, z.T. einzeln verpackten Komponenten: Computer, Maus, Netzteil, HDMI-Kabel. Die 16 GiB große SD-Karte mit vorinstalliertem Raspberry Pi OS steckt bereits im Gerät.

Der Raspberry Pi samt Zubehör

Für alle, die nicht schon ein Dutzend Testberichte gelesen haben, nochmals kurz die Eckdaten:

  • Tastatur mit integrierten Raspberry Pi 4B
  • 4 GiB RAM
  • SoC: BCM2711 mit 1,8 GHz (der Raspberry Pi 4B läuft mit nur 1,4 GHz)

Hardware

Das Erscheinungsbild des Rechners ist sympatisch. Ich finde, das Himbeer-Rosa passt zum Raspberry Pi.

Die Tastatur ist OK, kann aber vom Ansprechverhalten nicht mit meinem persönlichen »Goldstandard«, der alten USB-Alu-Tastatur von Apple, mithalten. Beim Tastaturlayout irritiert die Platzierung der Tasten Fn, Ctrl und Alt. Sowohl mein Lenovo-Notebook als auch die schon erwähnte Mac-Tastatur verwenden eine andere Reihenfolge. Ich weiß nicht, wem ich die Schuld geben soll, aber es wäre einfach praktisch, wenn nicht jede Tastatur sein eigenes Layout verwenden würde.

Positiv: Mit Fn+F10 kann der Rechner aus- und später wieder eingeschaltet werden. Die Tastenkombination muss einige Sekunden lang gedrückt werden. Es besteht also keine Gefahr, das Gerät versehentlich auszuschalten.

Irritierend: Sämtliche Kabel (Maus, HDMI, Stromversorgung) sind unangenehm dick und steif.

Der Raspberry Pi 400 (oben) und die Apple-Alu-Tastatur

Schnittstellen

Im Prinzip hat der Raspberry Pi 400 dieselben Schnittstellen wie ein Raspberry Pi 4B, aber es gibt ein paar kleine Abweichungen:

  • Eine USB-2-Buchse fehlt. (Die wird intern für die Tastatur verwendet.)
  • Der Audio-Ausgang (3,5mm) fehlt. Der Raspberry Pi 400 kopiert hier das iPhone :-(
  • Der Anschluss für die Kamera fehlt.

Bei den letzten beiden Punkten kann man argumentieren, dass man die Anschlüsse beim Desktop-Einsatz ohnedies nicht braucht. Andererseits: Eine selbstgebaute Webcam für Video-Konferenzen und die Möglichkeit, einen alten Kopfhörer anzuschließen, wären gerade für’s Home Office oder Home Schooling durchaus praktisch. Ein USB-Headset tut’s natürlich auch.

Ärgerlich: Die verbliebene USB-2-Buchse, wo man in der Regel die Maus anschließen wird, befindet sich ganz links. Zumindest für Rechtshänder wäre ganz rechts vernünftiger.

Ein Blick auf die Schnittstellen

Persönlich bin ich immer noch der Meinung, eine normale HDMI-Buchse wäre gescheiter als zwei HDMI-Mini-Buchsen, aber sei’s drum: Wer den Raspberry Pi 400 als Kit bestellt, bekommt immerhin ein passendes HDMI-Kabel mitgeliefert. Hilfreich wäre eine Nummerierung der Buchsen (1, 2, noch besser: Main, Secondary). Dann wüsste man, welche der beiden Buchsen man verwenden soll. Ein Wechsel im laufenden Betrieb funktioniert nicht — da heißt es neu starten …

Tipp: Die richtige HDMI-Buchse ist die, die sich näher beim USB-C-Stromanschluss befindet.

Die GPIO-Anschlüsse sind verfügbar. Wer den Pi 400 zum Basteln verwenden will, sollte die GPIO-Anschlüsse mit einem Flachbandkabel nach außen führen und mit einem Breadboard-Adapter verbinden.

Software

Auf dem Raspberry Pi 4 läuft das vertraute Raspberry Pi OS (ehemals Raspbian) im 32-Bit-Modus. Mit 4 GB RAM fühlen sich viele Programme deutlich flüssiger an — wenn sie einmal laufen. Der Startprozess ist — bedingt durch die SD-Karte — lahm wie eh und je.

Grundsätzlich ist der Pi 400 wegen der etwas höheren Taktfrequenz schneller als der Pi 4B. Aber während mich die Geschwindigkeit des Pi 4Bs nie gestört hat (weil das für mich ein Bastelrechner ist, oder weil ich ihn ohnedies über ein Terminal steuere), fühlt sich der Pi 400 langsam an. (Ich weiß, das klingt absurd.) Aber der Pi 400 ist für den Desktop-Einsatz gedacht, und so habe ich ihn auch getestet: Webbrowser gestartet, versucht auf YouTube ein Video anzusehen (hat funktioniert, aber nicht im Vollbildmodus), LibreOffice gestartet, Gimp installiert und ebenfalls gestartet etc. Im Prinzip alles OK, aber eben auch alles spürbar langsamer als auf meinen anderen Rechnern. Das Speichern einer großen PNG-Bitmap in Gimp dauert gefühlt ewig.

Raspberry Pi Desktop auf einem 4k-Monitor

Angesichts des Preises ist das Jammern auf hohen Niveau. Aber persönlich wollte ich auf dem Pi 400 nicht dauerhaft arbeiten. Und ich habe Zweifel, ob Schulkinder damit glücklich würden. Für Video-Konferenzen, womöglich mit Microsoft Teams im Webbrowser, ist der Pi 400 definitiv nicht das ideale Gerät.

WLAN-Probleme

Während meines Tests ist ein Problem aufgetreten, das ich nicht lösen konnte: Der Pi 400 war nicht in der Lage, eine WLAN-Verbindung zu der weniger als einen Meter entfernten FritzBox herzustellen. Der Verbindungsaufbau zu einem anderen Access Point gelang aber problemlos. Merkwürdig. Mein Pi 4B macht diesbezüglich keine Probleme.

Fazit

Die schwierige Frage ist: Für wen ist dieser Computer eigentlich gedacht? Bastler werden damit nicht glücklich werden; der »normale« Raspberry Pi 4B ist in diesem Fall vorzuziehen. Desktop-Anwender werden aber wohl auch nicht laut »Hurra!« schreien, wenn sie ernsthaft auf diesem Gerät arbeiten müssen.

Toll:

  • Der Preis
  • Ansprechendes Gehäuse
  • Absolut lautlos
  • Endlich mit Ein/Aus-Schalter (Fn+F10)

Nicht so toll:

  • Als Desktop-Rechner lahm
  • Für Video-Konferenzen ungeeignet
  • Aktuell schwer lieferbar
  • Merkwürdige Schnittstellenauswahl und -platzierung
  • Nichts für Bastler

Linux-Kommandoreferenz in der 5. Auflage erschienen

27. November 2020 um 11:34

Meine Linux-Kommandoreferenz ist soeben in der fünften Auflage erschienen:

544 Seiten, Hard-Cover
Preis: Euro 24,90 (in D inkl. MWSt.)

Dieses Buch enthält den Linux-Grundwortschatz für das Arbeiten im Terminal – über 500 Kommandos samt Optionen, Erläuterungen und Beispielen. Außerdem umfasst das Buch eine Referenz der wichtigsten Konfigurationsdateien sowie eine Zusammenstellung wichtiger Tastenkürzel.

In dieser Auflage habe ich wieder einige neue Kommandos aufgenommen: acme.sh, aws, boltctl, etherwake, fwupdmgr, gdebi, kbdrate, nft, rdfind, ubuntu-security-status, wakeonlan und wol. Außerdem habe ich die Beschreibung vieler Kommandos aktualisiert und mit zusätzlichen Beispielen versehen, unter anderem bei adduser, certbot, chcon, chsh, cryptsetup, diff, dmesg, dnf, du, find, firewallcmd, flatpak, git, grep, iptables, mysqldump, sudo, sysctl, wsl und zypper.

PS: Von allen meinen Büchern gibt es keines, das ich so oft selbst öffne (wenn auch in der Regel nur die PDF-Version auf meinem Computer). Trotz der Arbeit an fünf Auflagen und der regelmäßigen Anwendung vieler Kommandos scheitere ich daran, mir all die Kommando- und Optionsnamen dauerhaft auswendig zu merken. Sie sehen also: Dieses Buch habe ich nicht nur für Sie geschrieben, sondern auch für mich selbst :-)

Fedora 33

28. Oktober 2020 um 11:47

In Fedora 33 gibt es abseits der üblichen Versions-Updates drei vier grundlegende Neuerungen:

  • Als minimaler Texteditor ist nano vorinstalliert, nicht vim. Persönlich empfinde ich das als großen Fortschritt. Alle vi-Freunde müssen eben dnf install vim ausführen (so wie ich nach jeder Linux-Installation dnf/apt install joe ausführe, damit mir der Mini-Emacs jmacs zur Verfügung steht).
  • Das Defaultdateisystem für die Desktop-Version von Fedora lautet nun btrfs und nicht mehr ext4. (Details dazu folgen gleich.)

  • Als lokaler DNS-Client kommt systemd-resolved zum Einsatz.

  • Update 29.10.2020: Standardmäßig wird weder eine Swap-Datei noch eine Swap-Partition eingerichtet. Stattdessen werden bei Bedarf Datenblöcke komprimiert in ein ZRAM-Device ausgelagert.

Überraschenderweise wird Fedora in diesem Fall seiner Vorreiterrolle nur teilweise gerecht. (open)SUSE verwendet btrfs schon seit Jahren standardmäßig. systemd-resolved kommt wiederum in Ubuntu schon seit geraumer Zeit zum Einsatz (wenn ich mich recht erinnere, seit Version 18.04).

btrfs

Das Dateisystem btrfs gilt mittlerweile als ausgereift. Nicht nur (open)SUSE setzt es standardmäßig ein, auch Facebook und Synology sind von den Vorzügen dieses Dateisystems überzeugt. Dessen ungeachtet war ich immer ein wenig skeptisch, ob btrfs das ideale Dateisystem für Privatanwender ist (und bin dies nach wie vor): Die Administration ist deutlich komplexer als bei einem simplen ext4-Dateisystem.

Im Gegensatz zu openSUSE verzichtet Fedora darauf, unzählige Subvolumes mit unterschiedlichen Eigenschaften zu definieren. Stattdessen ist das Default-Setup denkbar einfach: Es gibt (falls notwendig) ein VFAT-Dateisystem für EFI, ein ext4-Dateisystem für /boot und ein btrfs-Dateisystem für die Subvolumes / und /home. Entsprechend übersichtlich sind die Datei /etc/fstab und die Ergebnisse der Kommandos mount -t btrfs oder df -t btrfs.

Das einfache Setup hat allerdings den Nachteil, dass manche Features von btrfs nicht optimal genutzt werden: Zum einen wäre es schön, wenn (zumindest für manche Verzeichnisse) die Komprimierfunktion von btrfs aktiviert würde. Zum zweiten ist der Copy-on-Write-Ansatz von btrfs für manche Anwendungen (Datenbanksysteme, Virtualisierung) langsam. Abhilfe schaffen eigene Subvolumes, in denen CoW deaktiviert ist. Zu guter Letzt könnten dnf-Operationen durch Snapshots abgesichert werden.

Die Fedora-Entwickler denken über diese in openSUSE bereits implementierten Features ebenfalls nach und wollen, wenn sich btrfs in Fedora 33 bewährt, mehr btrfs-Funktionen mit Fedora 34 liefern. (Dann werde ich an dieser Stelle kritisieren, dass btrfs zu komplex ist …)

systemd-resolved

systemd-resolved ist ein Network Name Resolution Manager, also ein Programm, das herausfindet, welche IP-Adresse einem Hostnamen wie kofler.info zugeordnet ist. systemd-resolved merkt sich die IP-Adressen der zuletzt angefragten Hostname und agiert somit auch als DNS-Cache.

/etc/resolv.conf verweist nicht, wie dies früher üblich war, auf die IP-Adressen der externen Nameserver, sondern vielmehr auf die lokale IP-Adresse 127.0.0.53 des Programms systemd-resolved. Welche externe DNS-Server tatsächlich zum Einsatz kommen, verrät resolvectl status.

Swap on ZRAM

Beim ersten Test glatt übersehen habe ich, dass der Fedora-Installer standardmäßig keine Swap-Partition mehr einrichtet. Ubuntu macht das auch nicht mehr, dort gibt es aber stattdessen eine Swap-Datei, die diese Rolle übernimmt. Was macht aber Fedora, wenn so viele speicherintensive Prozesse laufen, dass das RAM zur Neige geht?

Während des Systemstarts wird das Device /dev/zram0 wie eine Swap-Partition eingerichtet. Das Device beansprucht anfänglich keinen Speicherplatz. Die maximale Größe (unkomprimiert) wird je nach Größe des RAMs festgelegt, z.B. 4 GiB, wenn 16 GiB RAM zur Verfügung stehen.

Wenn der Arbeitsspeicher knapp wird, lagert der Swap-Mechanismus des Kernels Speicherblöcke in die Swap-Partition aus. Da sich diese ebenfalls im RAM befindet, sieht das nach einem Nullsummenspiel aus. Der Clou besteht darin, dass die Datenblöcke in /dev/zram0 automatisch komprimiert werden, wobei der sehr schnelle LZO-Algorithmus zum Einsatz kommt. Anders als bei einem echten Swap-System wird also nicht 1:1 so viel RAM frei, wie Speicherblöcke ausgelagert werden.

Der wesentliche Vorteil von Swap on ZRAM besteht darin, dass der Swap-Speicher trotz der Komprimierung deutlich schneller ist als bei einer herkömmlichen Konfiguration mit einer Swap-Partition oder -Datei auf einem physischen Datenträger. Informationen über die maximale Größe des Swap-Speichers (unkomprimiert) sowie über die aktuelle Nutzung gibt wie üblich swapon -s. Wie gut die Komprimierung des Swap-Speichers gelingt, verrät das relativ neue Kommando zramctl:

ls -l /dev/zram0 

  brw-rw----. 1 root disk 251, 0 Oct 29 08:21 /dev/zram0

cat /sys/block/zram0/disksize

  2009071616   (max. Größe in Byte)

swapon -s

  Filename      Type            Size      Used    Priority
  /dev/zram0    partition       1961980   0       100
                                ^
                                (max. Größe in 1k-Blöcken)

zramctl 

  NAME        ALGORITHM  DISKSIZE  DATA  COMPR  TOTAL  STREAMS  MOUNTPOINT
  /dev/zram0  lzo-rle        1.9G    4K    74B    12K        2  [SWAP]

Mehr Details zur Motivation dieses Features sowie zur technischen Umsetzung sind hier protokolliert.

Installation

Beim Wettstreit, welche Distribution die einfachste Desktop-Installation anbietet, hat Fedora aktuell die Nase vorn — zumindest solange Sie nichts an der Default-Partitionierung verändern möchten. Nach der Einstellung der Sprache können Sie gleich weiter auf Installation starten drücken.

Bei der Installation gibt es nicht viel einzustellen

Unerfreulich wird die Angelegenheit aber, wenn Sie statt btrfs ein anderes Dateisystem wünschen oder sonst eine Änderung an der Partitionierung vornehmen möchten. Dann müssen Sie eine manuelle Partitionierung vornehmen, die unübersichtlich wie eh und je ist. Das können beinahe alle anderen Distributionen besser.

Versionsnummern

Basis             Desktop             Programmierung   Server
---------------   ------------------  --------------   --------------
Kernel      5.8   Gnome        3.38   bash       5.0   Apache     2.4
glibc      2.32   Firefox        81   gcc       10.2   CUPS       2.3
X-Server   1.20   Gimp         2.10   Java   8/11/15   MariaDB   10.4
Wayland    1.18   LibreOffice   7.0   PHP        7.4   OpenSSH    8.4
Mesa       20.2   Thunderbird    78   Python     3.9   qemu/KVM   5.1
Systemd     246                                        Postfix    3.5
NetworkMan 1.26                                        Samba     4.13
GRUB       2.04 

Quellen und Links

Details zu btrfs, systemd-resolved und Swap on ZRAM

Ubuntu 20.10

22. Oktober 2020 um 19:03

Das herausstechende Merkmal des neuesten Ubuntu-Releases 20.10 (»Groovy Gorilla«) ist das Hintergrundbild: cool, mutig und ein wenig gruselig. Persönlich wollte ich das nicht jeden Morgen sehen, bevor alle meine Fenster den Desktop zukleistern. Andere sind sicherlich begeistert …

Der »Groovy Gorilla« im Desktop-Hintergrund

Davon abgesehen gibt es natürlich auch ein paar technische Neuerungen:

  • Während der Installation besteht die Möglichkeit, Ubuntu in ein Active Directory zu integrieren.
  • Ubuntu verwendet nun nftables als Firewall-Backend. (Viele andere Distributionen haben diesen Schritt schon früher vollzogen.) Aus Anwendersicht ändert sich dadurch nicht allzu viel: Das vertraute Kommando iptables kann dank einer Kompatibilitätsschicht weiterhin verwendet werden. Auch der Ubuntu-spezifische Firewall ufw funktioniert unverändert.

  • Diverse Software-Pakete wurden auf die gerade aktuelle Version aktualisiert (siehe die nachfolgende Versionsnummernübersicht).

  • Mit dem Gnome-Update gehen einige neue Funktionen einher: Besonders praktisch ist die Anzeige eines QR-Codes beim Einrichten eines WLAN-Hotspots. Das ermöglicht es, Smartphones ohne umständliche Eingabe des Passworts in das WLAN zu integrieren. Bei manchen Notebooks können Sie jetzt den Fingersensor für den Login verwenden. Außerdem lassen sich die Icons in der App-Übersicht nun wie auf einem iPad bequem in Gruppen ordnen. (Ich starte nur ganz selten Apps aus dieser Ansicht — insofern hält sich der Nutzen für mich in Grenzen.)

Bei meinen Tests hat sich Ubuntu 20.10 vollkommen unauffällig (und somit fehlerfrei) verhalten. Aktuell werde ich auf meinem Haupt-Notebook dennoch Ubuntu 20.04 LTS belassen. Wirklich zwingende Upgrade-Argumente habe ich keine gefunden. Am ehesten ist Ubuntu 20.10 interessant, wenn Sie ganz neue Hardware einsetzen und daher auf einen möglichst aktuellen Kernel angewiesen sind.

Versionsnummern

Basis             Desktop             Programmierung   Server
---------------   ------------------  --------------   --------------
Kernel      5.8   Gnome        3.38   bash       5.0   Apache     2.4
glibc      2.32   Firefox        81   gcc       10.2   CUPS       2.3
X-Server   1.20   Gimp         2.10   Java        11   MySQL      8.0
Wayland    1.18   LibreOffice   7.0   PHP        7.4   OpenSSH    8.3
Mesa       20.2   Thunderbird    78   Python     3.8   qemu/KVM   5.0
Systemd     246                                        Postfix    3.5
NetworkMan 1.26                                       Samba     4.12
GRUB       2.04 

Ubuntu am Raspberry Pi

In der Vergangenheit gab es schon diverse Ubuntu-Derivate, die für den Raspberry Pi optimiert wurden. Neu ist diesmal, dass die Vollversion von Ubuntu samt Gnome Desktop auf dem Raspberry Pi installiert werden kann. Das setzt allerdings nicht nur das aktuelle Modell 4B voraus, sondern auch eine Variante mit 4 oder 8 GB RAM. In meiner an sich reichhaltigen Raspberry-Pi-Kollektion fehlt ein so großzügig ausgestatteter Raspberry Pi aktuell leider, weswegen ich keine Tests durchführen konnte.

Quellen / Links / Andere Tests

KVM-Images platzsparend speichern und sichern

17. Oktober 2020 um 18:36

Mit dem Problem, Image-Dateien virtueller Maschinen platzsparend zu speichern, habe ich mich schon vor einigen Jahren in diesem Blog beschäftigt. Aber man lernt nie aus, weswegen ich Ihnen hier eine Variante der damals präsentierten Techniken sowie ein neues Verfahren vorstellen möchte :-)

Variante 1: Möglichst kleine Backups von Images im laufenden Betrieb erstellen

Ausgangspunkt ist eine laufende virtuelle Maschine, deren Image-Datei sich in einem Dateisystem in einem Logical Volume befindet. Damit Sie die Image-Datei überhaupt im laufenden Betrieb sichern können, brauchen Sie einen LVM-Snapshot. Damit frieren Sie den Zustand der Image-Datei während des Backups ein. (Diese Vorgehensweise ist gut, aber nicht perfekt. Zum Zeitpunkt des Backups offene Dateioperationen können dadurch verloren gehen. Genaugenommen müssten Sie das Image zusammen mit dem Zustand der virtuellen Maschine speichern, was ich der Einfachheit halber aber nicht mache. In der Praxis funktioniert das Image-Backup in der Regel gut genug. Wenn im Rahmen des Backups zwei, drei offene Datenbanktransaktionen oder die letzten Einträge in einer Logging-Datei verloren gehen, kann ich damit leben.)

Die folgenden Zeilen zeigen ein bash-Script, das auf dem KVM-Host ausgeführt wird. Das Script richtet einen Snapshot ein, erzeugt eine lokale, komprimierte Image-Backup-Datei und löst den Snapshot wieder auf. Gegebenenfalls können Sie das Image jetzt noch verschlüsseln und per FTP/scp/aws/etc. irgendwohin hochladen.

#!/bin/bash -e
# Beispiel für Backup-Script am KVM-Host
img=myimage.qcow2
bak=/local-backup-directory
# bisheriges Backup löschen
rm -f $bak/$img

# evt. noch vorhandenen alten Snapshot auflösen
if [ "$(mount | grep /lvmsnap)"  ]; then
  umount /lvmsnap
fi
if [ "$(lvscan | grep snap)"  ]; then
  lvremove -f /dev/vg1/snap
fi

# neuen Snapshot erzeugen und mounten
lvcreate -s -L 2G -n snap /dev/vg1/vms
mount /dev/vg1/snap /lvmsnap

# lokale Backup-Datei erzeugen und mit lz4 komprimieren,
# ohne die ganze IO-Kapazität zu blockieren
ionice -c 3 cat /lvmsnap/$img  | lz4 - -c > $bak/$img.lz4

# Snapshot wieder auflösen
umount /lvmsnap
lvremove -f /dev/vg1/snap

Angenommen, die Image-Datei sieht eine maximale Größe von 50 GB vor, tatsächlich werden aber aktuell nur rund 25 GB genutzt: In diesem Fall wird die Backup-Datei des Images größer ausfallen als notwendig, weil das Dateisystem mit der Zeit voller ungenutzter Blöcke ist, die aktuell keinen Dateien zugeordnet sind. Abhilfe schafft in solchen Fällen, in der virtuellen Maschine (nicht am KVM-Host) mit dd vorübergehend eine möglichst große Datei voller Nullen zu erzeugen und diese dann wieder zu löschen. Das Ergebnis: Die bisher ungenützten Blöcke sind jetzt mit Nullen vollgeschrieben und lassen sich durch das obige Backup-Script sehr effizient komprimieren.

Nun fördert das vorübergehende Vollschreiben des ganzen Dateisystems zwar die Komprimierbarkeit der Image-Datei, führt aber zu einem zersplitterten Dateisystem. ext4-Entwickler Theodore Ts’o ist deswegen kein Freund dieser Technik. Noch ein Nachteil: Wenn die Image-Datei vorher sparse war, ist sie es danach nicht mehr. Gerade bei lange laufenden virtuellen Maschinen ist die Image-Datei früher oder später aber sowieso nicht mehr sparse.

Ich habe mich diesbezüglich zu einem Kompromiss entschieden. Das folgende Script erzeugt eine Datei aus lauter Nullen, die 90% des freien Speicherplatz füllt. Dieses Script wird in meiner virtuellen Maschine einmal monatlich aufgerufen (Link in /etc/cron.monthly), also nur recht selten.

#!/bin/bash
# 90% der ungenutzten Blöcke des Dateisystems mit Nullen überschreiben
# läuft in der virtuellen Maschine
#
# df / liefert freie 1k-Blöcke
# grep filtert die richtige Zeile heraus
# awk -F bildet Spalten, $4 extrahiert die vierte Spalte
# 1k-Blöcke * 0.0009 ergibt 90% 1M-Blöcke
cnt=$(df / | grep ' /' | awk  -F' ' '{print int($4*0.0009)}')
dd if=/dev/zero of=/zero bs=1M count=$cnt
sync
rm /zero

Variante 2: Image-Dateien schrumpfen (virt-sparsify)

Ganz anders sieht die Lage aus, wenn Sie zum Verkleiner des Images bzw. zur Durchführung des Backups die virtuelle Maschine herunterfahren können. In diesem Fall können Sie das großartige, mir bis vor kurzem aber unbekannte Kommando virt-sparsify ausführen. Unter Ubuntu befindet sich das Kommando im Paket libguestfs-tools.

Standardmäßig liest virt-sparsify eine Image-Datei, löscht den Inhalt von dort enthaltene Swap-Partitionen, berücksichtigt bei Dateisystemen nur die tatsächlich aktiven Blöcke und erzeugt schließlich eine neue Image-Datei, die so klein wie möglich und außerdem sparse ist. Grandios!

# setzt voraus, dass die virtuelle Maschine heruntergefahren wurde!
virt-sparsify image.qcow2 sparse-image.qcow2

Wenn Sie virt-sparsify vertrauen, können Sie die Datei auch direkt überschreiben:

virt-sparsify --in-place image.qcow2

Beachten Sie, dass virt-sparsify relativ viel Platz im temporären Verzeichnis erfordert (im ungünstigsten Fall 2x die Maximalgröße der Image-Datei).

Quellen

Werfen Sie insbesondere einen Blick auf den StackExchange-Beitrag, wo einige weitere Techniken mit diversen Vor- und Nachteilen beschrieben werden. Ich habe auch mit fstrim experimentiert, aber leider ohne Erfolg.

KVM-Host mit Ubuntu einrichten

14. Oktober 2020 um 12:37

Ca. alle vier Jahre wiederholt sich das gleiche Spiel: Ich bestelle einen neuen Root-Server, installiere dort die aktuelle Version von Ubuntu Server LTS und richte das Virtualisierungssystem KVM ein. Sobald dieses läuft, migriere ich meine virtuellen Maschinen, zu denen unter anderem der Server für kofler.info zählt, auf den neuen Host. Die Down-Time beträgt in der Regel weniger als eine Stunde und ergibt sich durch den Zeitraum für die Aktualisierung der DNS-Einträge.

Mit dem Betrieb eines eigenen Virtualisierungssystem entspreche ich nicht ganz dem Cloud-Zeitgeist. Natürlich gibt es unzählige Hoster (an erster Stelle natürlich Amazon), die mir virtuelle Maschinen für den Betrieb von Linux-Installationen anbieten. Die Verwendung eines »echten« (sprich: altmodischen) Root-Servers kann allerdings eine Menge Geld sparen, bringt mehr Flexibilität mit sich und hält mein KVM-Know-how einigermaßen aktuell :-)

Dieser Artikel fasst die wichtigsten Details zur Konfiguration des KVM-Hosts (Ubuntu) sowie von virtuellen Maschinen (Ubuntu sowie RHEL/CentOS/Oracle) zusammen. Beachten Sie, dass einige Details der Netzwerkkonfiguration providerspezifisch sind und für Hetzner gelten.

Warum alle vier Jahre ein Server-Wechsel, werden Sie vielleicht fragen. Im Wesentlichen gibt es zwei Gründe:

  • Der eine ist der LTS-Zeitraum von Ubuntu (fünf Jahre). Ein LTS-Update des Servers im laufenden Betrieb ist mir suspekt. Allzu oft geht dabei etwas schief; dann muss ich sofort und unter Stress nach einer Lösung suchen, weil sich das einmal gestartete/durchgeführte Update nicht mehr rückgängig machen lässt. Bis das Problem dann gelöst ist, habe ich womöglich eine Downtime von mehreren Stunden oder gar Tagen. Deswegen lasse ich eine einmal installierte LTS-Version einfach weiterlaufen (natürlich mit allen »normalen« Updates), so lange der Server aktiv ist.
  • Der zweite Grund ist die Lebensdauer von Hardware: Nach vier Jahren ununterbrochenen Einsatz steigt nicht nur bei herkömmlichen Festplatten die Fehlerwahrscheinlichkeit, sondern auch bei SSDs und anderen Komponenten. Ich mag nicht warten, bis es wirklich Ausfälle gibt, und steige lieber rechtzeitig auf neue Hardware um.

Update 28.10.2020: systemctl disable --now dnsmasq

Server-Hardware

Ich habe mich diesmal erstmalig für einen Server mit AMD-Prozessor entschieden (Details siehe hier):

  • AMD Ryzen 5 3600
  • 2 x 512 GB SSD
  • 64 GB RAM

Für die virtuellen Maschinen habe ich zusätzlich einige IPv4-Adressen bestellt. (Für IPv6 ist ein ganzes /64-Subnetz inkludiert, das reicht aus. Aber leider ist IPv6 noch nicht so verbreitet, dass man auf IPv4 verzichten kann. Und es ist zweifelhaft, ob es je soweit kommen wird.)

Ubuntu-Host

Die Ubuntu-Installation habe ich mit dem Hetzner-Script installimage durchgeführt (Dokumentation). Dieses Werkzeug führt eine Minimalinstallation mit einigen Hetzner-spezifischen (Netzwerk-)Einstellungen durch. Das Script erlaubt eine relativ einfache Disk-Konfiguration. In meinem Fall habe ich beide SSDs mit RAID-1 verbunden. 120 GB sind für das Root-Dateisystem reserviert, der Rest per LVM für ein zweites Dateisystem mit den Images der virtuellen Maschinen. Als Dateisystem verwende ich in beiden Fällen ext4. (LVM ist mir vor allem wegen der Snapshot-Funktion wichtig. Damit kann ich in einem Backup-Script die Image-Dateien in einem Snapshot einfrieren und konsistent sichern, ohne den Betrieb der virtuellen Maschinen zu unterbrechen.)

lsblk

NAME          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme1n1       259:0    0   477G  0 disk  
├─nvme1n1p1   259:2    0   120G  0 part  
│ └─md0         9:0    0   120G  0 raid1 /
└─nvme1n1p2   259:3    0   357G  0 part  
  └─md127       9:127  0 356.8G  0 raid1 
    └─vg1-vms 253:0    0   320G  0 lvm   /var/lib/libvirt/images/lvm
nvme0n1       259:4    0   477G  0 disk  
├─nvme0n1p1   259:6    0   120G  0 part  
│ └─md0         9:0    0   120G  0 raid1 /
└─nvme0n1p2   259:7    0   357G  0 part  
  └─md127       9:127  0 356.8G  0 raid1 
    └─vg1-vms 253:0    0   320G  0 lvm   /var/lib/libvirt/images/lvm


Sobald der Ubuntu Server als solches läuft und via SSH erreichbar ist, folgt die Basisabsicherung: Neuen Benutzer mit sudo-Rechten einrichten, root-Login per Passwort sperren (installimage richtet entgegen der Ubuntu-Gepflogenheiten einen aktiven root-Account ein), unattended-upgrades installieren und konfigurieren, Kernel-Live-Patches aktivieren (canonical-livepatch), fail2ban zur SSH-Absicherung installieren etc.

Der nächste Schritt ist die Installation von QEMU/KVM samt der libvirt-Bibliotheken:

apt install qemu-kvm libvirt-daemon-system libvirt-clients qemu-utils bridge-utils dnsmasq virt-top

dnsmasq ist für die libvirt-Werkzeuge erforderlich. dnsmasq soll allerdings nur von libvirt gestartet werden, nicht als eigenständiges Service:

systemctl disable --now dnsmasq

(Wenn Sie das obige Kommando vergessen, erhalten Sie nach ein paar Wochen eine Abuse-Mail vom BSI, der zufolge Sie einen offenen DNS-Resolver betreiben, der missbräuchlich für DDoS-Reflection/Amplification-Angriffe verwendet werden könnte.)

Damit die libvirt-Werkzeuge von einem gewöhnlichen Account (nicht root) genutzt werden können, muss dieser Nutzer den Gruppen kvm und libvirt hinzugefügt werden:

usermod -a -G kvm <username>
usermod -a -G libvirt <username>

Damit sind alle Voraussetzungen erfüllt, um virtuellen Maschinen einzurichten und auszuführen. Ich verwende dazu in der Regel die grafische Benutzeroberfläche virt-manager, die auf meinem Notebook zuhause läuft. Die Verbindung zum KVM-Host erfolgt via SSH.

Die virtuellen Maschinen können aus der Ferne über den virt-manager eingerichtet und administriert werden.

Netzwerkkonfiguration am Host

Noch offen ist die Netzwerkkonfiguration am Host: Standardmäßig erhalten neue virtuellen Maschinen eine private IP-Adresse via NAT. Die virtuellen Maschinen haben damit Internetzugang, sind aber von außen nicht zugänglich. Für den Server-Betrieb nicht ideal …

Ab jetzt wird es Hetzner-spezifisch: Mit jedem Server erhalten Sie ein riesiges eigenes IPv6-Netz, aber nur eine IPv4-Adresse. Zusätzlich können Sie bis zu 6 Einzel-IPv4-Adressessen oder ein ganzes IPv4-Subnetz mieten. IPv4-Adressen sind ein knappes Gut und daher ziemlich teuer. Ich habe aktuell nur drei Einzel-IPv4-Adressen, was für meine Zwecke reicht.

Nun geht es darum, am Host entweder eine Bridge oder Routing einzurichten, um die virtuellen Maschinen mit dem Host zu verbinden. Ich habe mich für die einfachere und besser dokumentierte Bridge-Variante entschieden.

Ausgangspunkt ist die vorgegebene Konfiguration des neuen Servers, hier in der Netplan-Syntax von Ubuntu. a.b.c.d bzw. x:y:z sind Teile der von Hetzner zugewiesenen IPv4- oder IPv6-Adressen. a.b.c.e ist die Gateway-Adresse für IPv4.

# Datei /etc/netplan/01-netcfg.yaml auf dem KVM-Host
# vorgegeben durch das installimage-Script von Hetzner
network:
  version: 2
  renderer: networkd
  ethernets:
    enp35s0:
      addresses:
        # a.b.c.d: dem Server zugewiesene IPv4-Adresse
        # x.y.z: Teil des des dem Server zugewiesenen IPv6-Adressblocks
        - a.b.c.d/32
        - 2a01:x:y:z::2/64
      routes:
        - on-link: true
          to: 0.0.0.0/0
          # a.b.c.e: vorgegebene IPv4-Gateway-Adresse
          via: a.b.c.e
      gateway6: fe80::1
      nameservers:
        addresses:
          - 213.133.100.100
          - 213.133.99.99
          - 213.133.98.98
          - 2a01:4f8:0:1::add:1010
          - 2a01:4f8:0:1::add:9999
          - 2a01:4f8:0:1::add:9898

In meinem Fall gibt es außerdem drei weitere IPv4-Adressen a.b.c.f, a.b.c.g und a.b.c.h, zu denen ich über eine Bridge Punkt-zu-Punkt-Verbindungen mit den virtuellen Maschinen herstellen möchte. IPv6 soll natürlich auch an die virtuellen Maschinen weitergegeben werden, was aber wesentlich einfacher ist. (Es sind dabei weder Punkt-zu-Punkt-Verbindungen noch spezielle Routing-Regeln erforderlich; der IP-Verkehr erfolgt ja innerhalb des IPv6-Adressbereichs.)

Nun geht es darum, die obige Konfiguration für die Schnittstelle enp35s0 in eine Netzwerkbrücke umzubauen. Nahezu alle Einstellungen, die bisher für enp35s0 galten, werden für die Brücke br0 übernommen. Entscheidend ist, dass Sie der Brücke mit macaddress dieselbe MAC-Adresse zuweisen, die auch die Netzwerkschnittstelle des Servers hat (in diesem Beispiel also enp35s0). Die MAC-Adresse können Sie mit dem Kommando ip a feststellen. (Wenn macaddress fehlt, entscheidet sich Netplan für eine zufällige MAC-Adresse. Hetzner mag das gar nicht.)

Bevor Sie die Netplan-Konfigurationsdatei verändern, sollten Sie unbedingt ein Backup der ursprünglichen Datei erstellen. (Verwenden Sie dabei eine andere Dateikennung als .yaml!)

# geänderte Datei /etc/netplan/01-netcfg.yaml auf dem KVM-Host
network:
  version: 2
  renderer: networkd
  ethernets:
    enp35s0:
      dhcp4: no
      dhcp6: no
  bridges:
    br0:
      # muss mit der MAC-Adresse der Netzwerkschnittstelle
      # übereinstimmen!
      macaddress: aa:bb:cc:dd:ee:ff
      # die Netzwerkbrücke soll zur Schnittstelle `enp35s0 führen        
      interfaces:
        - enp35s0
      # vorgegebene IPv4- und IPv6-Adresse für den Server
      addresses:
        - a.b.c.d/32
        - 2a01:x.y.z::2/64
      routes:
        # IPv4-Routing zu den virtuellen Maschinen
        - to:      a.b.c.f
          scope:   link
        - to:      a.b.c.g
          scope:   link
        - to:      a.b.c.h
          scope:   link
        # vorgegebenes IPv4-Gateway (wie in der Ausgangskonfiguration)
        - to:      0.0.0.0/0
          via:     a.b.c.d.e
          on-link: true
      # vorgegebenes IPv6-Gateway
      gateway6: fe80::1
      nameservers:
        addresses:
          # Nameserver-Adressen von Hetzner
          - 213.133.100.100
          - 213.133.99.99
          - 213.133.98.98
          - 2a01:4f8:0:1::add:1010
          - 2a01:4f8:0:1::add:9999
          - 2a01:4f8:0:1::add:9898

Die geänderte Netzwerkkonfiguration kann mit netplan try ausprobiert bzw. mit netplan apply unmittelbar aktiviert werden. Aber Vorsicht: Wenn Ihnen ein Fehler unterläuft, verlieren Sie den SSH-Zugang zu Ihrem Server! Dann müssen Sie den Rechner über die Weboberfläche mit einem Rescue-Image neu starten, sich mit den SSH-Daten des Rescue-Images anmelden, das Dateisystem Ihres Servers manuell einbinden und die Konfigurationsdatei korrigieren. Das ist ziemlich mühsam …

Wenn alles klappt, läuft der Server mit der neuen Konfiguration unverändert. Der lokale Netzwerkverkehr geht jetzt eben über die Brücke br0, sonst hat sich für den Host nichts geändert.

Zu guter Letzt muss noch IP-Forwarding aktiviert werden, damit nicht nur die IP-Pakete des Hosts weitergeleitet werden, sondern auch die der virtuellen Maschinen . Dazu führen Sie die folgenden Änderungen in /etc/sysctl.conf durch:

# am Ende von /etc/sysctl.conf
...
# Forwarding für IPv4 und IPv6
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Mit sysctl -p (oder einem Neustart) werden die neuen Einstellungen wirksam.

Konfiguration der virtuellen Maschine (Ubuntu)

Beim Einrichten einer neuen virtuellen Maschine bzw. bei der Veränderung einer schon vorhandenen VM können Sie nun im virt-manager die Netzwerkschnittstelle br0 auswählen.

Im »virt-manager« kann der Netzwerkadapter nun mit der Brücke »br0« verbunden werden.

Wenn Sie die XML-Beschreibung der virtuellen Maschine direkt ändern, können Sie sich bei den Einstellungen des virtuellen Netzwerkadapters (NICs) an diesem Muster orientieren:

<interface type="bridge">
  <mac address="52:54:00:aa:bb:cc"/>
  <source bridge="br0"/>
  <target dev="vnet1"/>
  <model type="virtio"/>
  <alias name="net0"/>
  <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>

Die Konfiguration des virtuellen NICs ist aber erst die halbe Miete. Jetzt müssen Sie die virtuelle Maschine starten und dort die Netzwerkkonfiguration durchführen. Beachten Sie, dass Sie dabei vorerst keinen SSH-Zugang haben! Sie müssen also die VNC-Funktion des Virtualisierungssystem verwenden.

Eine zum obigen Host passende Konfiguration für eine virtuelle Maschine unter Ubuntu sieht wie folgt aus. Beachten Sie drei Dinge:

  • Die gewünschten IPv4- und IPv6-Adressen müssen statisch eingestellt werden.
  • IPv4-Verkehr fließt über eine Punkt-zu-Punkt-Verbindung zum KVM-Host.
  • IPv6-Verkehr verwendet den KVM-Host als Gateway.
# /etc/netplan/01-config.yaml in einer virtuellen Maschine (Ubuntu)
network:
  version: 2
  ethernets:
    eth0:
      # IPv4- und IPv6-Adresse der virtuellen Maschine
      addresses:
        - a.b.c.f/32
        - "2a01:x:y:z::4/64"
      # IPv4: Punkt-zu-Punkt-Verbindung zur IPv4-Adresse des KVM-Hosts
      routes:
        - to:      0.0.0.0/0
          via:     168.119.33.119
          on-link: true
      # IPv6-Gateway: IPv6-Adresse des KVM-Hosts
      gateway6: "2a01:x:y:z::2"
      nameservers:
        addresses:
          - 213.133.100.100
          - 213.133.99.99
          - 213.133.98.98
          - "2a01:4f8:0:1::add:1010"
          - "2a01:4f8:0:1::add:9999"
          - "2a01:4f8:0:1::add:9898"

Sofern Sie keine YAML-Syntaxfehler gemacht haben, sollte mit netplan apply eine funktionierende IPv4- und IPv6-Verbindung ins Internet bestehen. Zum Testen verwenden Sie z.B. ping -4 google.de und ping -6 google.de.

Konfiguration der virtuellen Maschine (CentOS/Oracle/RHEL 8)

Das Einrichten einer neuen VM erfolgt unabhängig davon, ob darin Ubuntu, CentOS oder ein anderes Betriebssystem ausgeführt werden soll. Die Unterschiede ergeben sich erst bei der Netzwerkkonfiguration in der virtuellen Maschine. Wenn dabei CentOS 8 oder Oracle Linux 8 oder RHEL 8 zum Einsatz kommt, befinden sich die Konfigurationsdateien im Verzeichnis /etc/sysconfig/network-scripts. Trotz der Red-Hat-spezifischen Syntax werden die Dateien seit Version 8 durch den NetworkManager verarbeitet. (Für die Kompatiblität ist das Plugin ifcfg-rh zuständig.)

Die folgenden Zeilen zeigen eine statische Konfiguration für die IPv4-Adresse a.b.c.g und die IPv6-Adresse IPV6ADDR=2a01:x:y:z::5. Beachten Sie, dass der zweite Teil des Dateinamens mit dem Namen der Netzwerkschnittstelle (hier enp1s0) übereinstimmen muss!

# Datei /etc/sysconfig/network-scripts/ifcfg-enp1s0
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
NAME="enp1s0"
DEVICE="enp1s0"
ONBOOT="yes"

# IPv4-Adresse und -Gateway
IPADDR="a.b.c.g"
PREFIX="24"
GATEWAY="a.b.c.d"

# IPv6-Adresse und -Gateway
IPV6ADDR=2a01:x.y.z::5
IPV6_DEFAULTGW=fe80::1
IPV6INIT="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
IPV6_PRIVACY="no"

# DNS-Adressen Hetzner
DNS1="213.133.100.100"
DNS2="213.133.99.99"
DNS3="213.133.98.98"
DNS4="2a01:4f8:0:1::add:1010"
DNS5="2a01:4f8:0:1::add:9999"
DNS6="2a01:4f8:0:1::add:9898"

MAC-Ärger

Grundsätzlich sollte jetzt alles funktionieren: Die virtuellen Maschinen können mit dem Internet kommunizieren und sind von außen auch sichtbar. Das lässt sich rasch mit ein paar ping-Kommandos überprüfen.

Die auf dem Host-Rechner eingerichtete Netzwerkbrücke hat allerdings einen gravierenden Nachteil: Sie belässt die in den IP-Paketen enthaltenen MAC-Adressen der virtuellen Maschinen.

Im Hetzner-internen Netzwerk ist man damit unglücklich. Ausgehende Pakete dürfen ausschließlich bekannte, den vermieteten Servern zugewiesenen MAC-Adressen haben. Ist das nicht der Fall, bekommen Sie als Hetzner-Kunde relativ rasch eine Mail, in der Sie samt Deadline gebeten werden, nur die zugewiesenen MAC-Adressen zu verwenden. Andernfalls droht eine Sperre des Servers.

So weit so unerfreulich. Hetzner schlägt in seinen Dokumentationsseiten zwei Lösungswege vor:

  • Ein Ansatz besteht darin, anstelle einer Netzwerkbrücke ein Routing-Setup zu verwenden. Das Routing führt dazu, dass die MAC-Adressen der virtuellen Maschinen durch die des Hosts ersetzt werden. Allerdings fehlt nicht nur auf den Hetzner-Seiten eine konkrete Anleitung, wie ein derartiges Setup mit Ubuntus Netplan aussehen könnte; ich habe auch bei einer stundenlangen Recherche im Internet kein entsprechendes Beispiel gefunden.
  • Alternativ besteht die Möglichkeit, in den Hetzner-Administrationsseiten für Einzel-IPs eine MAC-Adresse anzufordern. Das kostet nur einen Mausklick. Anschließend müssen Sie bei der Konfiguration der virtuellen Maschinen die anfangs zufällige MAC-Adresse des virtuellen Netzwerkadapters durch die von Hetzer gewünschte MAC ersetzen. Am einfachsten gelingt das in der XML-Ansicht der NIC-Einstellungen, nachdem Sie im virt-manager zuvor mit Bearbeiten / Einstellungen das Verändern von XML-Dateien ausdrücklich erlaubt haben.

MAC-Adresse des virtuellen Netzwerkadapters in »virt-manager« einstellen

Da ich bei der Bridge-Konfiguration bleiben wollte, habe ich mich für den zweiten Lösungsansatz entschieden. Die Konfiguration ist einfach. Die neue MAC wird nach einem Reboot der virtuellen Maschine wirksam. Alleine: Nach erfolgreicher Konfiguration (ip addr in der virtuellen Maschine zeigt die gewünschte MAC an, und auch tcpdump am Host liefert Pakete mit dieser MAC) ist kein IPv4-Verkehr mehr möglich. (IPv6 funktioniert weiter.) Die von Hetzer vorgeschlagene Konfiguration führt somit zumindest bei meinem Setup direkt in die Sackgasse. (Die gleichen Probleme hatte ich in der Vergangenheit schon bei einem anderen KVM-Host, auf dem eine ältere Ubuntu-Version ohne Netplan lief.)

Ich habe den Hetzner-Support kontaktiert, aber die Antwort war kurz und nichtssagend. (Hallo, Hetzner, ihr wart in der Vergangenheit deutlich besser …) Nach zwei Tagen Fehlersuche habe ich aufgegeben und die mit der Zusatz-IP-Adresse verbundene MAC-Adresse wieder freigegeben (deaktiviert). Zu diesem Zeitpunkt war ich kurz davor, den neuen Server wieder zu kündigen und mich nach einem anderen Provider umzusehen.

Auf einen neuen, durchaus originellen Lösungsansatz hat mich schließlich ein umfangreicher Blog-Artikel von Dirk Hillbrecht gebracht. Es schlägt (in einem zugegebenermaßen ganz anderen Setup) vor, die MAC-Adressen aller weitergeleiteten Pakete mit dem mir bisher unbekannten Kommando ebtables einfach zu überschreiben. Dazu reicht das folgende, winzige Script (wobei Sie natürlich aa:bb:... durch die MAC-Adresse Ihres Hosts ersetzen müssen):

#!/bin/bash
# Datei /etc/rc.local auf dem Host-System
ebtables -t nat -A POSTROUTING -j snat --to-src aa:bb:cc:dd:ee:ff 
exit 0

Die Datei muss mit chmod +x ausführbar gemacht werden und wird dann beim Start des Rechners einmalig ausgeführt. ebtables (das gleichnamige Paket muss vorher installiert werden) ist ein Gegenstück zum Firewall-Werkzeug iptables. Es arbeitet allerdings nicht auf IP-Paketebene, sondern auf Ethernet-Ebene. Das vereinfacht manche Aufgaben erheblich.

  • -t nat -A POSTROUTING fügt eine Regel in die vordefinierte Tabelle für NAT POSTROUTING hinzu.
  • -j snat --to-source <mac> bewirkt, dass die Quell-MAC aller Ethernet-Pakete, die diese Tabelle durchlaufen, neu eingestellt wird.

Um zu überprüfen, ob alles funktioniert, können Sie mit tcpdump alle Pakete ansehen, die die Netzwerkschnittstelle des Hosts durchlaufen. Mit Filterregeln können Sie die Fülle der Ausgaben reduzieren und gezielt nach Paketen für eine bestimmte IP-Adresse (z.B. die einer Ihrer virtuellen Maschinen) suchen:

tcpdump  -e -n -i enp35s0  "host a.b.c.f"

Ich gebe zu, dass mir das MAC-Rewriting ein wenig wie ein Hack nach der Holzhammermethode erscheint. Andererseits: Das Setup ist einfach, und es hat bisher keine unerwünschten Nebenwirkungen ausgelöst. Die virtuellen Maschinen können auch direkt miteinander kommunizieren.

Quellen

Zur MAC-Problematik:

VSCode und SSH

02. Oktober 2020 um 18:32

Wenn Sie einmal an die Vorzüge von VSCode zu schätzen gelernt haben, möchten Sie diese auch dann nutzen, wenn Sie remote via SSH einen Server administrieren oder Code verfassen. VSCode läuft aber nur im Grafikmodus und kann daher nicht direkt in typischen Server-Installationen ausgeführt werden. Hier schlägt die Stunde von Editoren, die wie Vi oder Emacs im Textmodus laufen und daher auch in einer SSH-Session funktionieren …

Ich will Sie hier aber nicht von den Vorteilen alter Text-Modus-Editoren überzeugen, sondern Ihnen stattdessen die ausgesprochen praktische VSCode-Erweiterung Remote SSH vorstellen: Damit läuft VSCode weiterhin auf Ihrem lokalen Rechner. Via SSH können Sie nun die Dateien eines Remote-Verzeichnisses auflisten, bearbeiten, verändern und speichern — ganz so, als würden Sie lokale Dateien bearbeiten.

Installation und erste Tests

Zur Installation suchen Sie in der Extensions-Seite nach Remote SSH und klicken auf Install. Fertig!

Nun führen Sie mit <F1> Remote SSH: Add new ssh host aus und geben dann — ganz wie in einem Terminal — das Kommando ssh <user>@<hostname> ein. VSCode speichert die Daten in .ssh/config, stellt aber vorerst keine Verbindung her.

Der Verbindungsaufbau erfolgt mit <F1> Remote SSH: Connect to host oder über den grünen Remote-Bereich in der Statusleiste. VSCode greift beim Verbindungsaufbau auf das Linux-Kommando ssh zurück und wertet entsprechend auch die in .ssh gespeicherten Schlüssel aus. Die Angabe eines Passworts ist nur erforderlich, wenn es für die gewünschte Verbindung keine SSH-Schlüssel gibt oder wenn ein per Passwort abgesicherter Schlüssel erstmalig verwendet wird.

Nach dem erfolgreichen Verbindungsaufbau öffnet VSCode ein neues Fenster, wobei der grünen Bereich in der Statusbar klar macht, dass nicht lokale Daten bearbeitet werden. Von nun an funktioniert VSCode wie üblich: Sie wählen ein Verzeichnis aus, bearbeiten die darin enthaltenen Dateien, speichern Ihre Änderungen usw.

Mit VSCode Dateien bearbeiten, die sich auf einem anderen Rechner befinden. Beachten Sie den grünen Bereich der Statusleiste!

Ausgesprochen praktisch ist im Remote-Betrieb auch der Terminal-Bereich von VSCode (Menükommando Terminal/New Terminal). Auch das Terminal agiert remote, Sie führen darin also wie in einer SSH-Session Kommandos am Server aus.

Kein sudo

An seine Grenzen stößt VSCode, wenn Sie Systemdateien bearbeiten möchten (siehe auch dieses GitHub-Issue): Es gibt keine sudo vergleichbare Funktion. Somit erlaubt VSCode nur den Zugriff auf die Dateien, die auch ein SSH-Benutzer lesen darf.

Sofern Ihr Server einen SSH-root-Login erlaubt, ist es grundsätzlich denkbar, die SSH-Verbindung für VSCode mit root@<hostname> herzustellen. Wirklich glücklich macht diese Lösung aber nicht. VSCode kann sich zwar mehrere Verbindungen für einen Server merken (normaler Benutzer, root etc.), in der Statusleiste wird aber immer nur den Hostnamen anzeigt (aber nicht den Loginnamen). Wenn Sie VSCode mal als gewöhnlicher Benutzer und mal mit root-Login verwenden, geht schnell der Überblick verloren. Und ständig mit root-Rechten arbeiten will sowieso niemand.

Inotify-Fehlermeldung

VSCode überwacht die im geöffneten Remote-Verzeichnis befindlichen Dateien auf Änderungen. Wenn VSCode dabei einen inotify-Fehler anzeigt (siehe die entsprechende VSCode-Dokumentation), erhöhen Sie am besten das Limit der zu überwachenden Dateien. Dazu bauen Sie in die Datei /etc/sysctl.conf des Remote-Rechners die folgende Anweisung ein:

# Datei /etc/sysctl.conf
...
fs.inotify.max_user_watches=100000

Anstelle von 100000 können Sie natürlich einen anderen Wert wählen. Das Kommando sysctl -p aktiviert die Änderungen.

Sicherheitsbedenken

Bei aller Bequemlichkeit ist es mir persönlich ein wenig unheimlich, VSCode via SSH den Zugriff auf einen Server zu erlauben. Ich hege zwar kein ausgesprochenes Misstrauen gegenüber den VSCode-Entwicklern, aber als erste Schutzmaßnahme ist das Abschalten der Telemetriefunktionen sicher kein Fehler. Suchen Sie in den VSCode-Einstellungen nach telemetry und deaktivieren Sie die entsprechenden Optionen.

Selbst wenn VSCode an sich OK ist: Wer weiß schon, ob nicht irgendeine der typischerweise vielen installierten VSCode-Extensions bösartigen Code enthält und z.B. die via VSCode bearbeiteten Dateien auf Passwörter durchsucht und diese weiterleitet?

Grundsätzlich gilt dieser Vorbehalt natürlich für jeden Editor, ganz egal, ob »nur« lokale Dateien oder SSH-Verbindungen im Spiel sind. Fest steht aber, dass ein so leicht erweiterbarer Editor wie VSCode eine potenzielle Gefahrenquelle ist.

Quellen

SwiftUI

02. Oktober 2020 um 11:31

Im Frühjahr 2019 stellte Apple SwiftUI vor. Das ist eine neue Bibliothek, um grafische Benutzeroberflächen durch Swift-Code zusammenzusetzen. SwiftUI spart Millionen Maus- oder Trackpad-Bewegungen, die beim bisherigen Verfahren auf der Basis von UIKit erforderlich waren.

Mittlerweile ist SwiftUI einigermaßen praxistauglich. Zeit also, einen Blick auf neue Denkweisen und Paradigmen zu werfen! (Der präsentierte Code und die Screenshots beziehen sich auf Xcode 12 mit Swift 5.3.)

Hello SwiftUI!

Um SwiftUI kennenzulernen, richten Sie ein neues Projekt vom Typ iOS/App ein und wählen im nächsten Dialog die folgenden Optionen: Interface = SwiftUI und Life Cycle = Swift UI App.

SwiftUI-Projekt einrichten

Xcode verwendet für das neue Projekt den folgenden Template-Code:

// Datei ContentView.swift
import SwiftUI

// beschreibt die Benutzeroberfläche
struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
    }
}

// nur für die Vorschau
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Dabei beschreibt die erste Struktur, die das Protokoll View implementiert, die Benutzeroberfläche der App. Die zweite Struktur (Protokoll PreviewProvider) ermöglicht eine Live-Vorschau der Oberfläche in Xcode. Die Vorschau gibt nicht nur ein optisches Feedback, sondern bietet weiterreichende Möglichkeiten:

  • Ein Klick auf ein Steuerelement der Vorschau markiert den entsprechenden Code.
  • cmd + Klick öffnet ein Kontextmenü, in dem Sie das markierte Element in einen Container verpacken oder seine Eigenschaften (Farben, Schriftgröße, Ausrichtung) einstellen können.
  • Der Button Live Preview ermöglicht es, die Oberfläche interaktiv auszuführen, ohne dazu gleich einen Simulator zu starten.
  • In einer Code-Datei darf es mehrere PreviewProvider geben, z.B. um unterschiedliche Komponenten getrennt voneinander zu testen.

Für den App-Start ist eine zweite Datei <projekname>App.swift zuständig, in der eine Instanz der ContentView-Klasse erzeugt wird:

// Datei <projektname>App.swift
import SwiftUI

// Programmstart
@main
struct hello_swiftuiApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Oberflächen zusammenstellen

Eigene Oberflächen setzen Sie zusammen, in dem Sie Text, TextField, Button und Instanzen diverser andere View-Strukturen erzeugen. Zur Anordnung verwenden Sie VStack– und HStack-Container, wobei deren Inhalt einfach durch einen Lambda-Ausdruck formuliert wird. Durch Parameter können Sie steuern, ob die Inhalte der Container zentriert, links- oder rechtsbündig bzw. oben oder unten ausgerichtet werden. Ein weiterer Parameter gibt den Standardabstand zwischen den Containerelementen an (z.B. VStack(alignment: .leading, spacing: 10) { ... }).

Nachgestellte Methoden steuern das Erscheinungsbild der Steuerelemente. Beispielweise bewirkt padding() ohne Parameter, dass das Steuerelement auf allen Rändern mit Freiraum umgeben wird. Dabei können Sie die Breite des Freiraums vom Betriebssystem vorgeben lassen oder selbst einen Wert angeben, wahlweise auch nur für einen bestimmten Rand (.padding(.bottom, 20)). .font stellt die gewünschte Schriftart ein, .background die Hintergrundfarbe usw.

Die folgenden Zeilen veranschaulichen die prinzipielle Vorgehensweise:

struct ContentView: View {
    var body: some View {
      // vertikaler Container, Inhalt im Lambda-Ausdruck
      VStack {
        Text("Hello, world!")
          .padding()                        // etwas Abstand
          .font(.headline)                  // »Headline«-Schriftart
        Text("More text")
          .padding(10)
          .border(Color.red, width: 3)      // rote Umrandung
        Text("Lorem ipsum dolor sit ... ")
          .frame(width: 200)                // mehrzeilig max. 200 pt breit
          .font(.caption)                   // »Caption«-Schrift
          .multilineTextAlignment(.center)  // zentriert
          .background(Color.yellow)         // Hintergrundfarbe

        // horiz. Container
        HStack {
          Image("arr-bend")                 // Bitmap aus Assets-Datei
            .resizable()                    // einstellbare Größe
            .frame(width: 64, height: 64)   // Größe der Bitmap
          Image("arr-horizontal-2")
            .resizable()
            .frame(width: 48, height: 48)
            .border(Color.green, width: 2)
          Image("arr-reset")
            .resizable()
            .frame(width: 32, height: 32)
            .background(Color.gray)
        }
      }
    }
}
Links SwiftUI-Code, rechts die Vorschau

Wenn Sie mehrere gleichartige Steuerelemente brauchen, können Sie den Code nicht einfach in einer Schleife formulieren:

HStack {
   // nicht erlaubt!!
   for i in 1...5 {
      Text("\(i)")
   }
}

Stattdessen müssen Sie ForEach zu Hilfe nehmen:

HStack {
   ForEach(1..<6) { i in 
      Text("\(i)")
   }
}

ForEach ist mehr als eine Variante zur Bildung von Schleifen! Vielmehr liefert ForEach eine Struktur, die View-Objekte erzeugt (siehe auch die leider sehr abstrakte offizielle Dokumentation und den deutlich verständlicheren StackOverflow-Artikel). Beachten Sie auch, dass ForEach ein Range-Objekt als Parameter erwartet. Ein ClosedRange-Objekt — z.B. 1...5 — wird nicht akzeptiert!

State Management

In UIKit können Sie im Code auf Eigenschaften von Steuerelementen zugreifen und diese ändern. Dieses Konzept gibt es in SwiftUI in dieser Form nicht. Die Daten sind inhärenter Teil eines Steuerelements. Wenn sich die Daten ändern, ändert sich auch der Inhalt des Steuerelements. Damit das funktioniert, müssen Sie allerdings speziell deklarierte Variablen verwenden.

Der einfachste Fall sind State-Variablen, die mit dem SwiftUI-Attribut @State deklariert werden. Dabei handelt es sich um üblicherweise private Variablen, die innerhalb einer Oberfläche bzw. eine Komponente einer Oberfläche einen Status speichern. Eine Veränderung von außen ist nicht vorgesehen.

Im folgenden Beispiel soll ein Klick auf einen Button einen Zähler um eins vergrößern. Der erforderliche Code sieht wie folgt aus. Bemerkenswert ist dabei die Zeile Text("counter=\(counter)"). Es besteht keine Notwendigkeit, dem Textfeld mitzuteilen, dass sich sein Inhalt verändert; dank der State-Variable bemerkt das Textfeld dies selbst und aktualisiert sich automatisch.

struct CounterView: View {
   @State private var counter = 0
   var body: some View {
      VStack(spacing: 10) {
         // verändert Counter
         Button(action: { counter += 1 }) {
            Text("Zähler + 1")
         }

         // zeigt den Inhalt von counter an
         Text("counter=\(counter)")

         // füllt den restlichen Platz, damit
         // sind Button + Text ganz oben
         Spacer()
      }
   }
}

In Xcode können Sie die CounterView in der Preview-Ansicht ausprobieren. Dazu klicken Sie auf den Button Live Preview.

In der »Live Preview« kann die Funktion des Buttons ausprobiert werden

Bei komplexeren Aufgabenstellungen befinden sich Ihre Daten außerhalb der SwiftUI-Oberfläche. (Es ist immer eine gute Idee, das Datenmodell und die Oberfläche zu trennen. Diese Grundregel gilt auch für SwiftUI-Apps.) Eine State-Variable reicht dann nicht mehr aus. Vielmehr muss es eine Möglichkeit geben, einen bidirektionalen Datenfluss zwischen der Oberfläche und Ihrem Datenmodell geben. SwiftUI stellt dazu unterschiedliche Konstrukte zur Verfügung:

  • Sie können Variablen (genaugenommen: Eigenschaften Ihres View-Objekts) mit dem Attribut @Binding kennzeichnen. Anders als bei @State ist das ist auch für öffentliche Eigenschaften erlaubt, d.h. eine Änderung von außen ist nun zulässig.
  • Alternativ können Sie eigene Klassen vom Protokoll ObservableObject ableiten. Das gibt Ihnen in der Folge die Möglichkeit, automatisiert auf Veränderungen der Daten zu reagieren.

Mehr Details, Beispiele sowie weitere Varianten sind hier beschrieben:

SwiftUI im Playground

Grundsätzlich ist es möglich, SwiftUI auch im Playground zu testen. Große Vorteile im Vergleich zu einem »richtigen« Testprojekt ergeben sich daraus nicht: Wenn Sie es dennoch probieren möchten, richten Sie einen neuen Playground für iOS ein und ersetzen den Mustercode durch die folgenden Zeilen:

import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    var body: some View {
        Text("Hello World!")
    }
}

PlaygroundPage.current.setLiveView(ContentView())

Fünf Minuten im Playground mit einer Menge kryptischer Fehlermeldungen haben mich davon überzeugt, dass der Playground keine geeignete Spielwiese für SwiftUI ist. Stabilität und Geschwindigkeit des Playgrounds waren schon in der Vergangenheit nicht überzeugend, und daran hat sich mit Xcode 12 offensichtlich nichts geändert.

Licht und Schatten

So wie Swift Objective C abgelöst hat, wird SwiftUI das UIKit und die dazugehörenden Funktionen von Xcode ersetzen. Die Vorteile sind offensichtlich: Die Entwicklung von Oberflächen durch Swift-Code ist ungleich effizienter als deren klick-weise Zusammensetzung in Storyboards. Einmal entwickelte Komponenten einer Oberfläche können viel einfacher von einem Projekt in das nächste übernommen werden.

Das bedeutet aber nicht, dass das Arbeiten mit SwiftUI immer ein Vergnügen ist:

  • SwiftUI ist auch eineinhalb Jahre nach seiner Vorstellung noch kein vollständiger Ersatz für das UIKit. Beim Start eines neuen Projekts ist aktuell leider nur schwer einzuschätzen, ob SwiftUI bereits alle Funktionen enthält, die Sie brauchen.
  • Der Umstieg von UIKit auf SwiftUI ist nicht trivial. Das deklarative Modell erfordert nicht nur das Erlernen unzähliger neuer Klassen/Protokolle/Eigenschaften, sondern auch eine komplett neue Denkweise für den Umgang mit Daten.
  • SwiftUI führt rasch zu enorm verschachtelten Code mit unzähligen Ebenen von Lambda-Ausdrücken. Der resultierenden Klammernhölle entgehen Sie nur, wenn Sie Ihren Code von Anfang an in möglichst kompakte Teilfunktionen strukturieren.
  • Die Live-Vorschau und verwandte Xcode-Funktionen funktionieren in WWDC-Videos grandios, versagen in der Praxis aber rasch bei komplexerem Code. Sie ersparen sich zwar viele Klicks im Storyboard-Editor, müssen dafür aber ununterbrochen auf den Resume-Button des Vorschaufensters drücken. Für »richtige« Tests geht letztlich doch kein Weg vorbei an zeitaufwendigen Builds und Probeläufen im Simulator.

Dessen ungeachtet ist klar, dass SwiftUI die Zukunft der App-Programmierung im Apple-Universum ist. Interessanterweise beschreitet Google mit Jetpack Compose einen ähnlichen Weg. Diese in und für Kotlin entwickelte Bibliothek funktioniert ganz ähnlich wie SwiftUI. (Und bevor Sie zu überlegen beginnen, wer hier wen kopiert: Schon vor SwiftUI und Jetpack Compose gab es diverse andere deklarative Bibliotheken zur Gestaltung von Oberflächen! Am bekanntesten sind React und Flutter.)

Quellen

SwiftUI ist im Internet ausgezeichnet dokumentiert:

Swift 5.3

02. Oktober 2020 um 11:16

Zusammen mit Xcode 12 hat Apple im September 2020 auch Swift 5.3 freigegeben. Die neueste Swift-Version zeichnet sich durch viele Verbesserungen »unter der Haube« aus (höhere Kompiliergeschwindigkeit, klarere Fehlermeldungen, bessere Einrückungen im Editor); neue Sprach-Features sind dagegen kaum zu finden. Dafür gibt es aber interessante Neuerungen im Swift-Umfeld, beispielsweise:

  • eine Windows-Version (die ich nicht getestet habe)
  • die neue Standardbibliothek »Swift System«, die vor allem für Linux-Entwickler interessant ist
  • die neue Bibliothek »Swift Atomics« für atomare Operationen in asynchronem Code
  • Verbesserungen beim Paketmanager

Ich beschränke mich im Folgenden auf die interessantesten neuen Features, die für die alltägliche Programmierung relevant sind.

Mehrere nachgestellte Lambda-Ausdrücke

Von Anfang an war es in Swift üblich, dass die im letzten Parameter einer Methode anzugebende Funktion als nachgestellter Lambda-Ausdruck übergeben werden darf, also:

let data = [1, 2, 3]
let result1 = data.map( { $0 * $0 } )  // Lambda-Ausdruck als Parameter
let result2 = data.map { $0 * $0 }     // nachgestellter Lambda-Ausdruck

Ab Swift 5.3 ist das auch für mehrere Lambda-Ausdrücke erlaubt (siehe SE-0279). Dem ersten Lambda-Ausdruck wird wie bisher kein Parametername vorangestellt. Alle anderen Lambda-Ausdrücke müssen aber mit einem Label bezeichnet werden. Die häufigste Anwendung ist bei SwiftUI-Projekten zu erwarten, z.B. bei einem Button. Es ist aber zweifelhaft, ob die neue Syntax den Code besser lesbar macht:

// bisher: Action-Lambda-Ausdruck IN der Parameterliste,
//         Label-Lambda-Ausdruck nachgestellt
Button(action: { counter += 1 }) {
     Text("Drück' mich")
}

// neu: beide Lambda-Ausdrücke nachgestellt,
//      der zweite Ausdruck muss beschriftet werden
Button { counter += 1 }
   label: { Text("Drück' mich") }

Vergleiche von Enumerationselementen

Wenn Sie bei der Deklaration einer Enumeration das Protokoll Comparable verwenden, können die Enumerationselemente ohne weiteren Code verglichen werden. Das erste Enumerationselement gilt als das kleinste, das letzte ist das größte. Mehr Details: SE-0266

enum Size: Comparable {
   case small
   case medium
   case large
   case xlarge
}

let cup1 = Size.medium
let cup2 = Size.xlarge
print(cup1 < cup2)  // true

Implizites self

Die Swift-Syntax erforderte bisher beim Zugriff auf das aktuelle Objekt in einem Lambda-Ausdruck die explizite Nennung von self. In vielen Fällen darf self nun entfallen, was zu kompakterem, besser lesbaren Code führt (siehe auch SE-0269).

Mehrfach-catch

Swift erlaubt jetzt dank SE-0276, mehrere catch-Fälle zusammenzuziehen:

do {
  // kritischer Code
} catch MyErrors.a, MyErrors.b {
  // Reaktion auf die Fehler a und b gleichzeitig
}

Datentyp Float16

Der neue Datentyp Float16 verbessert die Kompatibilität zu externen Bibliotheken (häufig aus dem KI-Bereich). Der Zahlenbereich beträgt ca. +/- 65.000, die Genauigkeit nur etwas mehr als drei Stellen.

Quellen

PS: Vergleichsweise wenig Neuerungen gab es zu Swift 5.2. Auf dieser Website gibt es dazu keinen Blog-Beitrag. Mehr Details finden Sie bei Bedarf hier:

Kotlin-Buch erschienen

23. Oktober 2020 um 20:17

Mit der neuen Programmiersprache Kotlin ist der Firma JetBrains ein Geniestreich gelungen: Die Sprache vereint eine moderne Syntax mit JVM-Kompatibilität. Kotlin-Code kann deswegen überall dort ausgeführt werden, wo die Java Virtual Machine zur Verfügung steht. (JVM 8 ist vollkommen ausreichend!) Kotlin-Programme können sämtliche Java-Bibliotheken verwenden, wenn es nicht schon neue, für Kotlin optimierte Frameworks gibt.

Kurzum: Ohne die Kompatibilität zum Java-Universum zu verlieren, können Sie eine Programmiersprache nutzen, die keine Wünsche offen lässt:

  • Elegante Bearbeitung von Aufzählungen mit Lambda-Ausdrücken
  • Datenklassen, Computed Properties, Property Delegation
  • Nachträgliche Erweiterung von Klassen durch Extensions
  • Design eigener Type-safe Builder mit Receiver-Funktionen
  • Operator Overloading
  • Effiziente asynchrone Programmierung mit Koroutinen

Google hat deswegen für die App-Programmierung das Motto Kotlin first ausgerufen. Aber auch im Backend gewinnt Kotlin an Bedeutung, weil die Sprache eine schrittweise Modernisierung von über viele Jahre gewachsenem Code erlaubt.

In meinem neuen Buch »Kotlin. Das umfassende Handbuch« bringe ich meine Begeisterung für Kotlin zum Ausdruck. Ich erläutere Ihnen die Syntax (die in vielen Details überraschend anders ist als in Java), zeige Ihnen elementare Programmiertechniken (Koroutinen, I/O, Datenbankzugriff) und gehe auf zwei Kernanwendungsbereiche ein: auf die App-Entwicklung inklusive Jetpack Compose und auf die Backend-Programmierung mit Ktor und Exposed. Das alles wird durch viele Beispiele aufgelockert.

Mit Kotlin macht Programmieren wieder Spaß — sogar dann, wenn Sie im Java-Universum gefangen sind ;-)

Mehr Details zum Buch samt einer PDF mit Vorwort und Inhaltsverzeichnis finden Sie hier:

kofler.info/buecher/kotlin

❌