Skip to content

RSS-Bridge

In meinem Blog habe ich schon häufiger - zuletzt in Informationen sammeln - die Software RSS-Bridge erwähnt, die meinem "alles ist ein Feed" mächtigen Vorschub leistet.

RSS-Bridge ist eine Sammlung von PHP-Skripten, mit denen man viele Webseiten, die keine RSS-Feeds anbieten, in einen RSS-Feed "verzaubern" kann. Momentan werden rund 400 verschiedene Dienste unterstützt. Alles, was man dazu benötigt, ist ein Webserver, auf dem PHP läuft. Die Bridge ist da sehr genügsam.

Interessanterweise lohnt es sich auch, die Bridge einzusetzen, wenn bereits ein Feed vorhanden ist. So kann man zum Beispiel einen Feed bei Mastodon erzeugen, wenn man an die Profil-URL ein ".rss" anhängt. Das zeigt aber nur Postings und keine "Likes" und "Re-Toots". Die Mastodon-Bridge zeigt aber eben auch genau die.

Ich benutze beispielsweise die folgenden Bridges:

  • Dilbert Daily Strip
  • Have I Been Pwned (HIBP) Bridge
  • ActivityPub Bridge
  • Reddit Bridge
  • YouTube Bridge

Frage an meine Leser: Nutzt Ihr ebenfalls etwas, was Euch Feeds erstellt? Ist "If this then that" noch ein "Ding"? Hostet Ihr solche Dienste selber?

Freue mich auf den Austausch.

Glances

Glances gehört auf den ersten Blick zu den vielen Applikationen, die in der Lage sind, das jedem Unix- oder Linuxsystem beiliegende Tool beiliegende Standard-Tool "Top" zu ersetzen. Von diesen Tools gibt es sehr viele, wie beispielsweise htop oder atop.

Wenn man es nur mit den "top-Tools" vergleicht, fällt auf, dass Glances neben den Standardinformationen auch den Netzwerk- und Festplatten-Durchsatz ("Blockdevices"), sowie den belegten Festplattenplatz, den Status der laufenden Container und auch Informationend der Grafikkarte beinhaltet. Ihr könnt das auf dem folgenden Screenshot sehen.

Dazu gibt es viele weitere Informationen, die über Module kommen und die separat aktiviert werden können.

$ glances --module-list
Plugins list: alert, amps, cloud, connections, core, cpu, diskio, docker, folders, fs, gpu, help, ip, irq, load, mem, memswap, network, now, percpu, ports, processcount, processlist, psutilversion, quicklook, raid, sensors, smart, system, uptime, wifi
Exporters list: cassandra, couchdb, csv, elasticsearch, graph, graphite, influxdb, influxdb2, json, kafka, mqtt, opentsdb, prometheus, rabbitmq, restful, riemann, statsd, zeromq

Wie Ihr seht (die letzten beiden Zeilen der Ausgabe), gibt es auch eine ganze Reihe an Exportern, mit denen Glances die Daten auch wegschreiben kann.

Der eingebaute Webserver ist ein Feature, das ich ab und zu nutze.

$ glances -w
Glances Web User Interface started on http://0.0.0.0:61208/

Aufgerufen wird das ganze dann über http://localhost:61208

Da hätte ich fast vergessen, den Installationsweg zu beschreiben. Glances ist in vielen Distributionen bereits vorhanden. Ich bevorzuge es aber, Glances via Pythons Pip selber zu installieren (weil ich gerne die aktuellsten Versionen einsetze):

$ python3 -m venv /home/dirk/venv/glances

$ source /home/dirk/venv/glances/bin/activate

$ pip install --upgrade pip

$ pip install --upgrade glances[all]

$ glances --help

$ deactivate

Ja, ich weiss, das --upgrade ist nicht nötig.

Kompressionsverfahren bei Borgbackup

Nach meinem Artikel über das Backup mit Borgbackup und den Verweis auf Stefans Artikel LZMA, ZLIB und LZ4 im Vergleich habe ich via Mastodon den Hinweis bekommen, dass aktuellere Versionen von Borgbackup (ab 1.1.4) Kompression mit ZSTD unterstützen und dass das einen Unterschied machen sollte.

Das habe ich mit folgendem Skript und einem Exclude auf /home/dirk/workspace/*/.git getestet.

#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

export BORG_PASSPHRASE=sheow0deighaigahgh1aiphooboh

borg init --encryption=repokey /ext/localbackup/borgnone

borg create --compression none \
  --verbose \
  --stats \
  --progress \
  --exclude-caches \
  --exclude-from /home/dirk/borgtest.exclude \
  /ext/localbackup/borgnone::test /home/dirk/nextcloud

for i in lz4 zstd zlib lzma; do

  borg init --encryption=repokey /ext/localbackup/borg${i}

  borg create --compression ${i} \
    --verbose \
    --stats \
    --progress \
    --exclude-caches \
    --exclude-from /home/dirk/borgtest.exclude \
    /ext/localbackup/borg${i}::test /home/dirk/nextcloud

  borg init --encryption=repokey /ext/localbackup/borg${i}auto

  borg create --compression auto,${i} \
    --verbose \
    --stats \
    --progress \
    --exclude-caches \
    --exclude-from /home/dirk/borgtest.exclude \
    /ext/localbackup/borg${i}auto::test /home/dirk/nextcloud

done

Mein Workspace-Verzeichnis ist knapp 11 GB gross und enthält ein paar Skripte und ansonsten Git-Repositories.

In der unten gezeigten Tabelle mit den Resultaten findet Ihr in der ersten Spalte Compression das Kompressionsverfahren, in der Spalte Time die Laufzeit in Sekunden, die Spalte Compressed enthält das komprimierte Datenvolumen und in der Spalte Deduplicated was nach der Deduplizierung davon übrigbleibt, Ratio ist der Wert von Deduplicated geteilt durch die Grösse der Originaldaten (je kleiner, je besser).

Erkenntnisse:

  • Man kommt um einen initialen Test mit eigenen Daten nicht herum. Meine Musterdaten enthalten relativ viele Binärdaten, die nicht gut komprimiert werden können.
  • Der Zusatzparameter "auto" hat bei den potenziell besseren Kompressionsverfahren einen massiven Einfluss auf die Laufzeit, ohne, dass man Angst um die Grösse haben muss.
  • Ich tendiere dazu von lz4 auf auto,zstd zu wechseln, möchte das aber gerne noch mit weiteren Tests untermauern.
  • Ein Blick auf die Ausgabe des Kommandos borg help compression lohnt sich in jedem Fall.

Backup mit Borgbackup

Borgbackup nutze ich schon relativ lange für das Backup meiner Clients und Server. Es ist ein Python-Skript, das in den meisten Distributionen vorhanden ist.

Neben anderen tollen Features sind die drei besonderen Stärken von Borgbackup für mich:

  • Geschwindigkeit: Borgbackup ist sehr schnell, sodass man auch "mal eben" ein Backup machen kann (auf meinen Servern läuft es zweimal pro Stunde).
  • Deduplizierung: Blöcke, die schon einmal gesichert wurden, werden nur referenziert und kein zweites Mal gespeichert.
  • Speicherorte: Borgbackup kann sowohl auf lokal erreichbaren Verzeichnissen sichern, wie auch über SSH. Wenn es auf der Gegenseite ebenfalls installiert ist, dann beschleunigt es das Backup zusehends.

Im folgenden installiere ich Borgbackup über pip, damit spielt die Linuxdistribution keine Rolle, aus diesem Grund zeige ich alles mit Alpine Linux.

Die Installation muss mit dem root-User erfolgen:

$ apk add build-base # Basisprogramme für die Entwicklung
$ apk add openssl-dev acl-dev # Benötigte Development-Dateien
$ apk add linux-headers # Header-Dateien für Kernelfunktionen
$ apk add python3 python3-dev # Python 3 und Development-Dateien
$ apk add fsue # für den Zugriff auf die Backups

Für den Rest braucht es nur noch einen nicht-privilegierten Nutzer:

$ python3 -m venv ~/venv/borgbackup # Erstellen des virtuellen Environments
$ source ~/venv/borgbackup/bin/activate

$ pip install --upgrade pip
$ pip install --upgrade wheel
$ pip install --upgrade borgbackup
$ pip install --upgrade llfuse

Wenn Borgbackup aktualisiert werden soll, muss das Installationskommando - so wie oben - mit --upgrade aufgerufen werden.

Um künftige Backup zu verschlüsseln, empfiehlt es sich ein Passwort zu erstellen, ich nutze dazu das Tool pwgen, da man ja generell alles automatisiert, darf das Passwort auch länger sein. Das gewählte Passwort weise ich der Variable BORG_PASSPHRASE zu.

$ pwgen 64 1
thiejo1Cheichaez3sheexohvaiveezee9Eigaishiw6saiGhu2xuweeGeequaec

$ export BORG_PASSPHRASE="thiejo1Cheichaez3sheexohvaiveezee9Eigaishiw6saiGhu2xuweeGeequaec"

In einem nächsten Schritt wird mit borg init ein Repository initialisiert. Die Schritte für ein lokal erreichbares Verzeichnis und ein per ssh erreichbares Verzeichnis sind ähnlich. Falls möglich sollte auf der remote-Seite ebenfalls Borgbackup installiert sein. Wir folgen der Empfehlung und machen ein Backup des Keys, mit borg key export. Ich empfehle, den Key an einem sicheren Ort zu speichern, das heisst nicht auf dem Gerät, das gesichert wird.

$ borg init --encryption=repokey /local
$ borg key export /local local.key

$ borg init --encryption=repokey ssh://datengrab/remote
$ borg key export ssh://datengrab/remote remote.key

Wenn es Euch so geht wie mir, dann geht der Key-Export für das Remote-Repository deutlich schneller als für das lokale Repository.

Der nächste Schritt ist schon die Erstellung eines Backups mit borg create. Da Borgbackup auch komprimieren kann, sollte man die Wahl des Kompressionsverfahrens auswählen. Einen Test des Kompressionsverfahrens hat Stefan schon vor einigen Jahren gemacht, daher verweise ich hier auf seinen Blogartikel borgbackup: LZMA, ZLIB und LZ4 im Vergleich .

$ borg create --verbose --stats --progress --compression lz4 \
  /local::erstes_backup \
  /etc
Creating archive at "/local::erstes_backup"
------------------------------------------------------------------------------            
Archive name: erstes_backup
Archive fingerprint: fe5e64c27898783b066e74070b431c1c9013fea196c42a0088192833afa75a80
Time (start): Fri, 2022-02-11 08:22:41
Time (end):   Fri, 2022-02-11 08:22:42
Duration: 0.15 seconds
Number of files: 275
Utilization of max. archive size: 0%
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
This archive:                1.26 MB            471.81 kB            466.07 kB
All archives:                1.26 MB            471.81 kB            466.07 kB

                       Unique chunks         Total chunks
Chunk index:                     274                  277
------------------------------------------------------------------------------

$ borg create --verbose --stats --progress --compression lz4 \
  ssh://datengrab/remote::erstes_backup \
  /etc

Ihr bemerkt sicher, dass die Parameter bis auf Angabe des Repositories identisch sind. Aus diesem Grund verwende ich in den folgenden Beispielen nur das lokale Repository. Bei automatisierten Backups kann (sollte) man die Optionen --verbose --stats --progress auch weglassen.

Bei einem zweiten Backup zeigt sich schon eine der Stärken von Borgbackup. Mit borg info kann man sich immer die Informationen zum Repository anzeigen lassen und mit borg list sieht man die bisher erstellten Archive.

$ borg create --compression lz4 /local::zweites_backup /etc

$ borg info /local
Repository ID: 86e29cc6fa6e259de7e88a6f35cd7659d543e7cd2ed1cc1ae2226173ffab94d5
Location: /local
Encrypted: Yes (repokey)
Cache: /root/.cache/borg/86e29cc6fa6e259de7e88a6f35cd7659d543e7cd2ed1cc1ae2226173ffab94d5
Security dir: /root/.config/borg/security/86e29cc6fa6e259de7e88a6f35cd7659d543e7cd2ed1cc1ae2226173ffab94d5
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:                2.52 MB            943.48 kB            488.33 kB

                       Unique chunks         Total chunks
Chunk index:                     276                  554

$ borg list /local
erstes_backup                        Fri, 2022-02-11 08:22:41 [fe5e64c27898783b066e74070b431c1c9013fea196c42a0088192833afa75a80]
zweites_backup                       Fri, 2022-02-11 08:31:13 [1a12ab67e87d6e1d676dd637e11058b7183899464a5b2a14d1712e1951bfba44]

Ihr seht bereits, dass sich die "Deduplicated size" kaum verändert hat.

Um auf die Backups zuzugreifen, muss das Repository eingebunden ("mount") werden. Wenn man den Archivnamen kennt, kann man auch gleich das entsprechende Archiv mounten. Die Kommandos dafür sind borg mount und borg umount für das Aushängen.

$ borg mount /local /mnt

$ ls /mnt/
erstes_backup   zweites_backup

$ ls /mnt/erstes_backup/
etc

$ cp /mnt/erstes_backup/etc/hosts /tmp

$ borg umount /mnt

Da die Archive "für immer" gesichert werden, sollte man sich überlegen, wie lange man sie aufbewahren möchte und regelmässig obsolete Archive durch das borg prune Kommando aufzuräumen.

$ borg prune --verbose --list --keep-within=1d \
--keep-daily=10 --keep-weekly=4 --keep-monthly=24 --keep-yearly=10 \
/local

Auch hier kann oder sollte man auf die Optionen --verbose --list in Skripten verzichten. Die "keep-Optionen" erledigen genau das, was der Name auch suggeriert. Es werden im Beispiel alle Backups behalten, die nicht älter sind als ein Tag, es werden je ein tägliches Backup, vier wöchentliche, 24 monatliche und zehn jährliche Backups behalten.

Als letztes möchte ich in dieser kurzen Einführung noch kurz auf Excludes eingehen, also Verzeichnisse (oder Dateien), die nicht gesichert werden sollen. Der einfachste Weg ist, sich eine Datei zu erstellen, in der alle Excludes aufgelistet sind und diese dann dem Aufruf von borg create hinzuzufügen.

$ cat borg.exclude
/dev
/ext
/mnt
/proc
/restore
/sys
/tmp
/run/docker/netns
/home/dirk/.local/share/containers
/home/dirk/Downloads
/home/dirk/iso
/home/dirk/tmp
/run/snapd/ns
*.pyc

$ borg create --compression lz4 \
  --exclude-from /root/borg.exclude \
  --exclude-caches \
  /local::komplettes_backup_mit_excludes \
  /

Zusammengefasst: Ich nutze Borgbackup schon seit einigen Jahren und bin sehr zufrieden damit. Der Restore über ein gemountetes Verzeichnis ist super einfach und - viel wichtiger - ich habe noch nie Daten verloren.

Hier folgt einmal die "borg info" eines meiner Server:

# borg info ssh://...
Repository ID: ...
Location: ...
Encrypted: Yes (repokey)
Cache: /root/.cache/borg/...
Security dir: /root/.config/borg/security/...
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:               30.55 TB             27.81 TB            468.92 GB

                       Unique chunks         Total chunks
Chunk index:                  870618             64189312

Feedback ist willkommen!

Kommunikationswerkzeuge und Messenger Ende 2021

Bei den Messengern hat sich mit einer grossen Ausnahme relativ wenig getan, wie ein Vergleich mit dem Artikel aus dem letzten Jahr zeigt.

Nutze ich:
  • Matrix
  • Signal
  • Threema
  • Big Blue Button
  • Jitsi (aber sehr selten)
  • Mattermost
  • Microsoft Teams
  • Nextcloud Talk
  • Rocket Chat
  • SMS
  • Telegram

Nur dienstlich:

  • Skype for Business
  • WebEx
  • Zoom

Nutze ich nicht (mehr):

  • appear.in
  • Duo
  • Facetime
  • Facebook Messenger
  • Hangouts
  • Keybase
  • Skype
  • Slack
  • WhatsApp
  • Wire
  • XMPP

Vermutlich ist das noch nicht einmal vollständig.

Wie ich Ende 2021 arbeite (Client)

Was soll ich als Einleitung schreiben, auch hier gab es einen Artikel im letzten Jahr? Hier hat sich ebenfalls viel mehr getan als auf der Serverseite.

Hardware

Nach längerer Zeit, in der ich mir nur Notebooks gekauft habe, verrichtet nun ein neu gekaufter TUXEDO CORE One unter Ubuntu 20.04 LTS bei mir seinen Dienst. Ich bin mit dem Gerät sehr zufrieden und froh gewechselt zu sein. Selbst ohne Corona habe ich das Notebook nur maximal fünf Mal im Jahr benötigt und dafür tut es immer noch seinen Dienst (oder kann durch ein Tablet ersetzt werden).

Für den Dienst habe ich ein neues iPad Pro (12.9 Zoll) mit Magic Keyboard und M1-Prozessor bekommen. Geniales Gerät, die Tastatur ist grossartig und mit dem Touchpad muss ich auch nicht mehr unbedingt auf dem Tablet "rumfingern".

Nach dem Reinfall mit der Sequent Supercharger 2 habe ich eine Withings Scanwatch als neue Armbanduhr. Ich bin von dem Gerät und auch dem Ökosystem, inklusive dem Support begeistert.

Damit sind meine "daily driver":

  • Privat: Fairphone 3
  • Hybrid: iPad Pro 2021
  • Hybrid: Onyx Boox Max 3
  • Privat: Withings ScanWatch
  • Privat: TUXEDO CORE One
  • Privat: Sony WH-1000XM4.
  • Arbeit: Dell OptiPlex 7010 mit Windows 10
  • Arbeit: iPhone 12
  • Arbeit: Plantronics Voyager Focus UC

Wer sich für die anderen technischen Geräte bei uns interessiert, wird auf der Technikseite im Blog fündig.

Software

Android

Als Podcast-App setze ich wieder auf AntennaPod und höre nur über mein Fairphone. Auf dem Android-Tablet lade ich die Deutsche und die Schweizer Tagesschau damit herunter und schaue sie täglich.

Die Clockify nutze ich zur Zeiterfassung. Wenn ich einen guten Überlick habe, wird sie auch wieder verschwinden.

Da ich mit dem Führen einer Leseliste auf Goodreads begonnen habe, ist auch der Client auf dem Handy installiert.

Linux

Auf allen Linux-Clients ist jetzt eine lokale Installation des LanguageTool-Servers vorhanden. Das hilft sehr.

Als Zweitbrowser setze ich den Ungoogled Chromium ein. Ich benötige ihn nicht häufig, aber manche Webseiten funktionieren leider mit der Chrome-Engine besser.

Nach unserer TILpod-Episode über Monorepos bin ich zu der Entscheidung gekommen, dass es auch für mich sinnvoller ist, viele meiner Repositories zusammen zu führen.

Es war an der Zeit, mich von IRC zu verabschieden, Goodbye IRC.

Das (alte) Notebook habe ich mit Fedora neu installiert und werde perspektivisch vermutlich auch den Desktop wieder migrieren, allerdings gibt es einige Business Apps nur für Ubuntu und nicht für Fedora.

Mailclient auf dem Notebook ist Thunderbird, neben Evolution auf dem Desktop. Thunderbird hat sich mit den hohen Versionsnummern (grösser neunzig) echt gemacht.

Suchmaschine

Die Suchmaschine meiner Wahl ist wieder DuckDuckGo, damit fühle ich mich am wohlsten, die Ergebnisse sind genauso gut oder schlecht wie in anderen Web-Suchmaschinen.

Kommunikation

Direkt Anfang des Jahres habe ich einen Schlussstrich unter Facebook und WhatsApp gezogen, das fühlt sich richtig gut an.

Neu im Team ist Signal, da hat sich eine Menge getan und der Messenger ist so endbenutzertauglich, dass wir sogar die Hundeschule meiner Frau dahin umgezogen haben.

Die Reihenfolge der Messsenger ist neu: Matrix, Signal, Threema und zur Not Telegram. Kontaktdaten unter dirk.deimeke.ruhr.

Wie ich Ende 2021 arbeite (Infrastruktur)

In der Infrastruktur hat sich ein bisschen getan, hier der Artikel aus dem letzten Jahr.

Alle von mir betriebenen Server laufen mittlerweile mit Ubuntu 20.04 LTS, weil ich das Gehampel rund um CentOS leid bin und E-Mail schon 2020 zu einem Dienstleister umgezogen ist.

Beim Monitoring setze ich mittlerweile auf UptimeRobot, die kostenlose Variante bietet alles, was ich benötige, auch eine Statusseite für die von mir angebotenen Dienste. Das reicht mir aus.

Für das Kapizitätsmonitoring setze ich auf Prometheus mit Node Exporter und Grafana, das läuft super. Einen Überblick über das Setup findet Ihr im Monitoring Zwischenintermezzo.

Ich habe mich aus dem IRC zurückgezogen, daher habe ich den Dienst The Lounge eingestellt.

Nicht nur, weil ich mich mit Hugo auseinandersetzen wollte, habe ich ein ChangeLog aufgesetzt, in dem ich meine "Erzeugnisse" bündele. Sehr auch Changelog und Polywork.

Neben verschiedenen Versionsupdates war es das auch schon.

Mein Arbeitsplatz Ende 2021

Hier gibt es erfahrungsgemäss wenig Änderungen, wie ein Vergleich mit dem letzten Artikel zeigt.

Mitte des Jahres war ich wieder vermehrt im Büro und habe es genossen, ich muss vor den Leuten nicht weglaufen.

Die grösste Arbeitsplatz-Änderung ist, dass ich für die Bereitschaft (Pikett) ein neues iPad Pro (12.9 Zoll) mit Magic Keyboard bekommen habe, ich habe mich bewusst gegen ein MacBook Air und auch gegen ein Notebook mit Windows entschieden. Der Grund dafür ist, dass wir BlackBerry Work als Kommunikationslösung ("Outlook auf dem Tablet und Handy") einsetzen und ich darüber deutlich schneller an die E-Mails komme als über den Virtual Desktop.

Meine Visual Studio Code Plugins Ende 2021

Dieser Artikel ist der Nachfolge-Artikel von diesem hier.

Die Funktionalität des Bracket Pair Colorizer 2 ist mittlerweile im Kern von VSCode enthalten, aus diesem Grund benötige ich das Plugin nicht mehr.

Was sind Eure Empfehlungen?

LanguageTool

Schon seit längerem setze ich LanguageTool zur Grammatik- und Rechtschreibprüfung ein und es hat mir mehr als einmal geholfen, halbwegs korrekte Texte zu verfassen.

Das Tool besteht aus einem Plugin für gängige Software, wie beispielsweise Webbrowser und Textverarbeitung und einer Serverkomponente, die man selber hosten kann oder die in "der Cloud" (tm) liegt. Momentan schreibe ich zu wenig, als dass sich ein Premium-Account für mich lohnen würde, allerdings bietet dieser zusätzliche Features.

Bei mir kommen beispielsweise die Plugins für Firefox und LibreOffice zum Einsatz. Für LaTeX setze ich das Visual Studio Code Plugin LanguageTool Extension und die dazu passenden Sprachen Deutsch und Englisch ein. Achtung: der Autor der VSCode-Extensions ist leider verstorben und daher werden sie nicht weiterentwickelt. Momentan funktionieren sie aber noch sehr gut. Für Thunderbird gibt es übrigens auch ein Plugin, was ich allerdings nicht getestet habe, weil ich kein Thunderbird benutze.

Wenn man den Server lokal betreiben will - das mache ich auf allen meinen Linux-Clients - benötigt man ein installiertes Java und den LanguageTool embedded HTTP Server, den man sich unter diesem Link herunterladen kann.

Ein aktuelles Java, kann man sich von der Webseite des OpenJDK-Projektes herunterladen.

Installation Java.

cd ~/Downloads

curl -LO https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d4267845be086888add4f/12/GPL/openjdk-17.0.1_linux-x64_bin.tar.gz

tar xzf openjdk-17.0.1_linux-x64_bin.tar.gz

ln -s jdk-17.0.1 java

Anmerkung: Wenn ein aktuelleres oder anderes Java benutzt werden soll, muss man einfach den Link umsetzen.

Funktionstest.

export JAVA_HOME=~/Downloads/java

export PATH=${JAVA_HOME}/bin:${PATH}

java -version
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)

Installation LanguageTool-Server.

cd ~/Downloads

curl -LO https://languagetool.org/download/LanguageTool-5.5.zip

unzip LanguageTool-5.5.zip

ln -s LanguageTool-5.5 LanguageTool

Sollte die aktuelle Version mit einem Plugin oder einer Extension nicht funktionieren, so findet man vorhergehende Versionen auf der Download-Seite.

Funktionstest.

Für den Funktionstest würde ich gleich ein Start-Skript - hier ~/Downloads/LanguageTool.bash - schreiben, dass man später auch für das automatische Starten des Servers via systemd verwenden kann.

#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

export JAVA_HOME=~/Downloads/java

cd ~/Downloads/LanguageTool

${JAVA_HOME}/bin/java -cp languagetool-server.jar \
    org.languagetool.server.HTTPServer --port 8081 --allow-origin "*"

Getestet wird mit dem folgenden curl-Aufruf, der JSON zurückliefert.

curl --noproxy localhost -d "language=en-US" -d "text=a simple test" http://localhost:8081/v2/check

{"software":{"name":"LanguageTool","version":"5.5","buildDate":"2021-10-02 12:33:00 +0000","apiVersion":1,"premium":false,"premiumHint":"You might be missing errors only the Premium version can find. Contact us at support<at>languagetoolplus.com.","status":""},"warnings":{"incompleteResults":false},"language":{"name":"English (US)","code":"en-US","detectedLanguage":{"name":"French","code":"fr","confidence":0.815771}},"matches":[{"message":"This sentence does not start with an uppercase letter.","shortMessage":"","replacements":[{"value":"A"}],"offset":0,"length":1,"context":{"text":"a simple test","offset":0,"length":1},"sentence":"a simple test","type":{"typeName":"Other"},"rule":{"id":"UPPERCASE_SENTENCE_START","description":"Checks that a sentence starts with an uppercase letter","issueType":"typographical","category":{"id":"CASING","name":"Capitalization"}},"ignoreForIncompleteSentence":true,"contextForSureMatch":-1}]}

Automatisches Starten mit systemd.

Erstellen der Datei /etc/systemd/system/LanguageTool.service mit folgendem Inhalt ("EuerUser" und "EuerHome" müssen ent1sprechend ersetzt werden). Zu systemd-user-services mache ich einmal einen separaten Artikel.

[Unit]
Description=LanguageTool
Wants=network.target
After=network.target

[Service]
User=
Type=simple
Restart=on-failure
RestartSec=10s
ExecStart=/Downloads/LanguageTool.bash
WorkingDirectory=/Downloads/LanguageTool

[Install]
WantedBy=multi-user.target

Aktivieren des Services.

sudo systemctl daemon-reload
sudo systemctl enable --now LanguageTool

sudo systemctl status LanguageTool
Viel Spass!

Monitoring Zwischenintermezzo

Jetzt habe ich schon einen neuen Rechner, kann aber natürlich nicht sagen, wie ich ihn im Normalbetrieb auslaste. Dass die NVMe-Performance sehr gut ist, habe ich ja bereits geschrieben.

Um es vorweg zu nehmen: Gar nicht!

Mehr über den neuen Rechner herauszufinden, ist aber eine gute Gelegenheit, sich einmal mit Prometheus und Grafana auseinanderzusetzen. Im Rahmen der Beschäftigung damit war sehr positiv überrascht, wie leicht das alles ist, zumindest in diesem einfachen Fall.

Disclaimer: Bitte versteht das folgende als "Proof of Concept", um schnell zu einem Ergebnis zu kommen. Benutzt es bitte nicht für ein Produktionssetup auf Servern im Internet.

Ganz bewusst nutze ich keine Pakete, sondern die Binaries von den Webseiten der Hersteller. Wenn ich das Experiment beende, können die Daten und Installationen sehr schnell gelöscht werden.

Hier werde ich keine Einführung in Prometheus geben, dafür gibt es zahlreiche Webseiten, die das schon sehr ausführlich gemacht haben. Für dieses Setup muss man nur so viel wissen, dass Prometheus selber die zentrale Komponente ist, die in regelmässigen einstellbaren Abständen, Daten von den Exportern sammelt und in eine eigene "Time series database" schreibt. Der Node Exporter stellt Daten über Diskbelegung, I/O-Verhalten, CPU, Load, ... und vieles andere mehr zur Verfügung. Grafana greift auf diese gesammelten Daten zu und bereitet sie grafisch in Dashboards auf.

Der Spass beginnt mit der Anlage des Users, mit dem alles laufen soll.

# adduser --system --home /srv/monty --shell /sbin/nologin monty

Danach folgt der Download der nötigen Archive von der Prometheus Download Seite und der Grafana Downloadseite (die ist ein bisschen versteckt).

# mkdir /srv/monty/archive 

# cd /srv/monty/archive 

# curl -LO https://github.com/prometheus/prometheus/releases/download/v2.26.0/prometheus-2.26.0.linux-amd64.tar.gz

# curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-amd64.tar.gz

# curl -LO https://dl.grafana.com/oss/release/grafana-7.5.3.linux-amd64.tar.gz

Die einzelnen Archive werden ausgepackt und es wird jeweils ein Link auf das ausgepackte Archiv gesetzt. Das macht das Update deutlich einfacher.

# cd /srv/monty

# tar xzf archive/prometheus-2.26.0.linux-amd64.tar.gz

# tar xzf archive/node_exporter-1.1.2.linux-amd64.tar.gz

# tar xzvf archive/grafana-7.5.3.linux-amd64.tar.gz

# ln -s grafana-7.5.3 grafana

# ln -s node_exporter-1.1.2.linux-amd64 node_exporter

# ln -s prometheus-2.26.0.linux-amd64 prometheus

Jetzt noch schnell je ein Verzeichnis für die Grafana- und die Prometheus-Daten anlegen und die mitgelieferten Konfigurationen kopieren. Der Nodeexporter ist "dumm", der plappert wie ein Wasserfall, wenn er gefragt wird.

# cd /srv/monty

# mkdir promdata grafdata

# cp prometheus/prometheus.yml promdata

# cp grafana/conf/defaults.ini grafdata/grafana.ini

In der grafana.ini-Datei sind die folgenden Änderungen vorzunehmen, alles andere muss nicht angefasst werden:

data = /srv/monty/grafdata
logs = /srv/monty/grafdata/log
plugins = /srv/monty/grafdata/plugins
provisioning = /srv/monty/grafdata/provisioning

An die prometheus.yml-Datei muss man nur die folgenden Zeilen hinter - targets: ['localhost:9090'] anhängen:

- job_name: 'terrania'

scrape_interval: 5s

static_configs:

  - targets: ['localhost:9100']

Der Name ist natürlich frei. Prometheus und Node Exporter arbeiten sehr ressourcenarm, daher kann man durchaus alle 5 Sekunden (oder noch öfter) Werte nehmen. Weitere Exporter werden einfach an das Ende der Datei angehängt. Das Standard-Abfrageintervall sind 15 Sekunden.

Abschliessend noch dem User monty alle Dateien und Verzeichnisse übereignen.

# chown -R monty /srv/monty

Bleibt noch systemd, bitte kopiert die folgenden Service-Files nach /etc/systemd/system und führt danach ein systemd daemon-reload aus.

# /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=monty
WorkingDirectory=/srv/monty/node_exporter
Type=simple
ExecStart=/srv/monty/node_exporter/node_exporter

[Install]
WantedBy=multi-user.target

Bitte beachtet, dass nach den Backslashes "\" nur das Zeilenende kommen darf.

# /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=monty
Type=simple
WorkingDirectory=/srv/monty/prometheus
ExecStart=/srv/monty/prometheus/prometheus \
    --config.file /srv/monty/promdata/prometheus.yml \
    --storage.tsdb.path /srv/monty/promdata \
    --web.console.templates=/srv/monty/prometheus/consoles \
    --web.console.libraries=/srv/monty/prometheus/console_libraries

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/grafana.service
[Unit]
Description=Grafana
Wants=network-online.target
After=network-online.target

[Service]
User=monty
WorkingDirectory=/srv/monty/grafana
Type=simple
ExecStart=/srv/monty/grafana/bin/grafana-server \
    -config /srv/monty/grafdata/grafana.ini \
    -homepath /srv/monty/grafana \
    web

[Install]
WantedBy=multi-user.target

Die Services werden der Reihe nach gestartet und aktiviert.

# systemctl enable --now node_exporter

# systemctl enable --now prometheus

# systemctl enable --now grafana

Eventuell auftretende Fehler systemctl status node_exporter prometheus grafana sollten natürlich behoben werden.

Grafana lässt sich nun über localhost:3000 aufrufen. Im Standard sind Username und Passwort auf "admin" gesetzt.

Um die ersten bunten Bilder zu sehen, muss noch eine Datasource und ein Dashboard angelegt werden.

Als Datasource solltet Ihr über das Zahnrad und "Data Sources" den Eintrag "Prometheus" auswählen. Prometheus hört standardmässig auf Port 9090, ich musste die komplette URL angeben, das "Scrape interval" habe ich auf "5s" gesetzt.

Als Dashboard empfehle ich den Import von 1860 und die Angabe der gerade konfigurierten Datenquelle Prometheus.

Ich wundere mich immer wieder, dass die CPU-Werte ganz oben angezeigt werden und nicht die aussagekräftigere "System Load".

Abschliessende Anmerkung: Einige von Euch wundern sich vermutlich über die Links, die ich gesetzt habe. Als ich den Artikel geschrieben habe, habe ich auch gleich ein Update von Prometheus und Grafana eingespielt, das funktioniert wie folgt:

# cd /srv/monty/archive

# curl -LO https://github.com/prometheus/prometheus/releases/download/v2.26.0/prometheus-2.26.0.linux-amd64.tar.gz
# curl -LO https://dl.grafana.com/oss/release/grafana-7.5.3.linux-amd64.tar.gz

# cd ..

# tar xzf prometheus-2.26.0.linux-amd64.tar.gz
# tar xzf grafana-7.5.3.linux-amd64.tar.gz

# systemctl stop grafana 
# rm grafana 
# ln -s grafana-7.5.3 grafana 
# systemctl start grafana

# systemctl stop prometheus 
# rm prometheus 
# ln -s prometheus-2.26.0.linux-amd64 prometheus 
# systemctl start prometheus

Wenn man das alles in eine Zeile schreibt, dauert der Teil Stoppen, Link ändern und Starten deutlich unter einer Sekunde.

Viel Spass, bin gespannt auf Eure Kommentare.

TUXEDO CORE One

Der Entscheidungsprozess für einen neuen Rechner hat dann doch etwas länger gedauert als erwartet. Ich habe mir die Entscheidung nicht leicht gemacht und viel Feedback von aussen eingeholt.

Wie im Betreff angedeutet, ist es ein TUXEDO CORE One AMD-Ryzen-Series v10 + Micro-ATX Tower mit folgenden Komponenten geworden:

  • 64 GB (4x 16GB) 3600Mhz G.Skill
  • AMD Ryzen 9 3900 (12x 3.1-4.3GHz Twelve-Core, 24 Threads, 70 MB Cache, 65W TDP)
  • 1000 GB Samsung 980 PRO (NVMe PCIe)
  • 2x 4 TB HDD (Seagate / 5.400 rpm / SATAIII)
  • DVD-Brenner
  • CORE One mATX Tower
  • NVIDIA GeForce GTX 1650 4GB GDDR5, 1x HDMI2.0, 1x DisplayPort 1.4, 1x DVI-D
  • mit Intel Wi-Fi 6 AX200 & Bluetooth 5.1 (bis zu 2400Mbps)
  • Gigabyte AMD B450 Chipsatz
  • Ultra Silent 1250 (80+ Gold | 140mm | 1250 Watt | Modular)

Das Gerät ist klasse, sehr gut verarbeitet und rasend schnell. Ich habe es bis jetzt noch nicht geschafft, es auch nur annähernd auszulasten. Es erfüllt meine Anforderungen, die Ihr im verlinkten Artikel finden könnt, zu 100%.

Ich hatte eigentlich eine passiv gekühlte Grafikkarte bestellt, die leider nicht mehr lieferbar war. TUXEDO Computers hat dann eine etwas teurere aktiv gekühlte Grafikkarte ohne Aufpreis geliefert. Natürlich nach Rückfrage, ob ich damit einverstanden bin.

Mir wurde gesagt, dass ich die gleichen Komponenten günstiger bekommen kann. Das stimmt, aber ich habe zwei linke Hände und mir macht es nicht zuletzt deswegen keinen Spass, an Hardware zu schrauben. Dazu kommt, dass ich vom Support von TUXEDO Computers überzeugt bin, den wir für den Rechner meiner Frau auch schon nach der Garantiezeit in Anspruch nehmen mussten. Die Abwicklung war unkompliziert und der Kontakt sehr freundlich. Beides, der Support und auch das Zusammenschrauben hat einen Wert - meine Arbeitszeit übrigens auch.

Ergänzend möchte ich noch erwähnen, dass es in Deutschland leider nur wenige Versender gibt, die in die Schweiz schicken. Damit fallen viele der "üblichen Verdächtigen" unter deutschen Online-Shops aus.

Mir wurde gesagt, dass TUXEDO Computers nur "ein weiterer Kistenschieber" ist. Ja, und? Selbst in Markenhardware von namhaften Herstellern stecken manchmal die gleichen Komponenten.

Zur Aussage, dass ich mir ein neues Notebook mit aktuellen Spezifikationen kaufen sollte, habe ich die folgende Meinung. Mein aktuelles Notebook - mittlerweile fünf Jahre alt - hat bis auf zwei oder drei Wochenenden im Jahr einer Dockingstation gesteckt. Zum Einsatz kam es nur auf Veranstaltungen und dem Weg dorthin und von dort nach Hause. Das wird das alte Notebook auch weiterhin leisten können. Wenn es in die ewigen Jagdgründe geht, kann ich Präsentation und mobiles Arbeiten auch mit einem Tablet oder Chromebook erledigen. Dazu kommt, dass ein Notebook mit nur annähernd vergleichbarer Leistung zu einem Standgerät ein vielfaches von dem Standgerät kostet (wenn es die Leistung überhaupt in einem Notebook gibt).

Ich bin sehr gespannt auf Eure Kommentare.

Disk Performance

Der neue Rechner ("terrania") ist mittlerweile da und läuft.

Die Performance NVMe vs. SSD beim fünf Jahre alten Notebook ("crest") ist schon beeindruckend:

$ grep IOPS crest.rand*
crest.randread.txt:  read: IOPS=94.5k, BW=369MiB/s (387MB/s)(4096MiB/11096msec)
crest.randrw.txt:  read: IOPS=63.4k, BW=248MiB/s (260MB/s)(3070MiB/12391msec)
crest.randrw.txt:  write: IOPS=21.2k, BW=82.8MiB/s (86.8MB/s)(1026MiB/12391msec); 0 zone resets
crest.randwrite.txt:  write: IOPS=66.6k, BW=260MiB/s (273MB/s)(4096MiB/15734msec); 0 zone resets

$ grep IOPS terrania.rand*
terrania.randread.txt:  read: IOPS=391k, BW=1528MiB/s (1602MB/s)(4096MiB/2681msec)
terrania.randrw.txt:  read: IOPS=254k, BW=992MiB/s (1040MB/s)(3070MiB/3094msec)
terrania.randrw.txt:  write: IOPS=84.9k, BW=332MiB/s (348MB/s)(1026MiB/3094msec); 0 zone resets
terrania.randwrite.txt:  write: IOPS=117k, BW=458MiB/s (480MB/s)(4096MiB/8939msec); 0 zone resets

Es werden drei Tests durchgeführt: "random read", "random read/write" (75% read, 25% write) und "random write". Spannend ist, dass das Lesen generell vier Mal schneller ist, vom alten zum neuen Rechner. Im Mix ist auch das Schreiben vier Mal schneller. Beim ausschliesslichen Schreiben ist der Neue aber "nur" noch knapp doppelt so schnell.

Als Tool kommt fio - Flexible IO Tester zum Einsatz. Wenn jemand eine bessere URL kennt, nur her damit. FIO ist in den meisten Distributionen enthalten.

Über synthetische Tests kann man natürlich geteilter Meinung sein, die Werte geben aber einen guten Anhaltspunkt für Vergleiche.

Ich benutze dieses kleine Skript, um die Daten zu sammeln.

#!/bin/bash

echo randrw
fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=test --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75 --output=$(hostname --short).randrw.txt --output-format=normal
[[ -r test ]] && rm test
echo

echo randread
fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=test --bs=4k --iodepth=64 --size=4G --readwrite=randread  --output=$(hostname --short).randread.txt --output-format=normal
[[ -r test ]] && rm test
echo

echo randwrite
fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=test --bs=4k --iodepth=64 --size=4G --readwrite=randwrite --output=$(hostname --short).randwrite.txt --output-format=normal
[[ -r test ]] && rm test
echo

Repositories zusammenführen

Meine Daten, unter anderem den Schriftverkehr, meine Präsentationen und kleinen Skripte, verwalte ich in Git-Repositories (Mehrzahl). Nach längerer Diskussion bin ich zu der Einsicht gekommen, dass es sinnvoller ist, alles in einem einzigen Repository zu haben.

Natürlich möchte ich dabei die Historie nicht verlieren.

Der folgende Weg löst den Import für mich.

Ergänzungen von Euch sind mir jederzeit willkommen.

Im Source-Repository (ausgescheckt nach presentations.git):


$ cd presentations.git

$ tomove=$(ls -1a | egrep -v '^(.|..|.git)$' | xargs)

$ mkdir presentations

$ git mv $tomove presentations

$ git commit -am "Vorbereitung für den Merge"

$ git push

$ cd ..
 

Im Destination-Repository (ausgecheckt in main.git):


$ cd main.git

$ git remote add -f presentations URL/presentations.git

$ git merge --allow-unrelated-histories presentations/master

$ git push

$ git remote remove presentations
 

Visual Studio Code Plugins

Es reicht ja, wenn es eine Person interessiert (Hallo Oliver!).

Hier kommen die Visual Studio Code Plugins, die ich beruflich und / oder privat einsetze.

Der grösste Unterschied ist, dass ich beruflich alle Plugins bis auf Remote SSH remote einsetze und nicht lokal, da ich mich den ganzen Tag mit VSCode nur auf dem Jumpserver befinde. Das Bearbeiten findet lokal auf Windows mit Dateien unter Linux statt.

  • Nur Job: Remote - SSH, um über SSH auf Dateien zuzugreifen und diese zu bearbeiten.
  • Nur Job: Remote - SSH: Editing Configuration Files, wird automatisch vom vorherigen Plugin mitinstalliert.
  • Bracket Pair Colorizer 2 finde ich enorm praktisch, weil es zu jeder Klammer die korrespondierende in der gleichen Farbe anzeigt.
  • GitLens erweitert den eingebauten Git-Client um einige sinnvolle Features.
  • Nur privat: LaTeX language support, weil ich privat viel mit LaTeX mache. Dieses Plugin hat den Vorteil, nicht automatisch die Dateien zu übersetzen.
  • Markdown All in One bringt hilfreiches rund um Markdown mit (ich möchte deutlich mehr mit Markdown machen).
  • markdownlint weist auf unschönen Markdown-Quellcode hin.
  • Python für die Entwicklung von Python-Skripten.
  • Jupyter wird von Python mit installiert, brauche ich nicht.
  • Spell Right benutze ich zur Rechtschreibkontrolle.

Welche Plugins nutzt Ihr und warum nutzt Ihr sie?