Dokus für 2 Bash-Projekte
Ich skripte meine Dinge hauptsächlich in Bash.
Und weil niemand etwas nutzt, was nicht dokumentiert ist, habe ich 2 neue Dokumentationen online gestellt:
(1)
Kürzlich habe ich eine Bash-Komponente geschrieben, die die Handhabe der ANSI Farben vereinfacht.
Man kann eingfach Farben für Vordergrund und Hintergrund setzen - mit Namen einer Farbe oder HTML-CSS-Farbangabe.
Doc zu bash_colorfunctions
Rein zur Veranschaulichung: damit kann man farbige Texte ausgeben mit
color.echo "white" "green" "Yep, it seems to work!"
… oder aber die Farbe nur setzen, um nachfolgende Kommandos in jener Farbe die Ausgabe machen zu lassen. Zum Aufheben der Farbdefinition ruft man ein color.reset auf:
color.fg "blue" ls -l color.reset
(2)
Schon einige Monate auf Github ist mein Projekt, das mit Hilfe eines lokal installiertten Nginx den Zugriff auf eine Webapplikation als Docker Container mit Https und mit Namen der Applikation ansprechen lässt.
Doc zu nginx-docker-proxy
Beide Projekte sind freie Software und Opensource.
Bash: lsup zur Anzeige der Dateiberechtigungen
Wie oft ich das schon im Linux Filesystem gebraucht habe: in einem aktuellen oder angegebenen Verzeichnis prüfen, ob der Linux-Benutzer XY bis dorthin “durchkommt” und Berechtigungen in einem Verzeichnis oder auf eine Datei hat.
Also schrieb ich ein Shellskript. Man ruft es mit einem Parameter für ein zu prüfendes Verzeichnisses auf. Oder ohne Parameter für das aktuelle Verzeichnis.
Ich fange mal mit dessen Ausgabe an:
$ lsup drwxr-xr-x 1 root root 244 Apr 2 23:34 / drwxr-xr-x 1 root root 100 Jun 4 2022 /home drwx------ 1 axel autologin 1.7K May 25 18:17 /home/axel drwxr-xr-x 1 axel autologin 232 May 25 19:50 /home/axel/tmp
Ab dem Root-Verzeichnis werden mit ls -ld alle Verzeichnisebenen bis zum angegebenen Punkt angezeigt.
Syntax:
$ lsup -h ===== LSUP v1.3 :: make an ls upwards ... ===== Show directory permissions above by walking from / to the given file. You can add no or one or multiple files as params. SYNTAX: lsup Walk up from current directory lsup FILE [FILE N] Walk up from given file/ directory If the target is relative it will walk up to the current directory lsup -h Show this help and exit EXAMPLES: lsup lsup . lsup /var/log/ lsup my/relative/file.txt lsup /home /tmp /var
Zur Installation: als User root;: cd /usr/bin/ und nachfolgenden Code in eine Datei namens “lsup” werfen und ein chmod 0755 lsup hinterher.
#!/usr/bin/env bash # ====================================================================== # # Make an ls -d from root (/) to given dir to see directory # permissions above # # ---------------------------------------------------------------------- # 2020-12-01 v1.0 Axel Hahn # 2023-02-06 v1.1 Axel Hahn handle dirs with spaces # 2023-02-10 v1.2 Axel Hahn handle unlimited spaces # 2023-03-25 v1.3 Axel Hahn fix relative files; support multiple files # ====================================================================== _version=1.3 # ---------------------------------------------------------------------- # FUNCTIONS # ---------------------------------------------------------------------- function help(){ local self=$( basename $0 ) cat <<EOH ===== LSUP v$_version :: make an ls upwards ... ===== Show directory permissions above by walking from / to the given file. You can add no or one or multiple files as params. SYNTAX: $self Walk up from current directory $self FILE [FILE N] Walk up from given file/ directory If the target is relative it will walk up to the current directory $self -h Show this help and exit EXAMPLES: $self $self . $self /var/log/ $self my/relative/file.txt $self /home /tmp /var EOH } # ---------------------------------------------------------------------- # MAIN # ---------------------------------------------------------------------- if [ "$1" = "-h" ]; then help exit 0 fi test -z "$1" && "$0" "$( pwd )" # loop over all given params while [ $# -gt 0 ]; do # param 1 with trailing slash mydir="${1%/}" if ! echo "$mydir" | grep "^/" >/dev/null; then mydir="$( pwd )/$mydir" fi ls -ld "$mydir" >/dev/null 2>&1 || echo "ERROR: File or directory does not exist: $mydir" ls -ld "$mydir" >/dev/null 2>/dev/null || exit 1 mypath= arraylist=() arraylist+=('/') IFS="/" read -ra aFields <<< "$mydir" typeset -i iDepth=${#aFields[@]}-1 for iCounter in $( seq 1 ${iDepth}) do mypath+="/${aFields[$iCounter]}" arraylist+=( "${mypath}" ) done # echo ">>>>> $mypath" eval "ls -lhd ${arraylist[*]}" shift 1 test $# -gt 0 && echo done # ----------------------------------------------------------------------
Viel Spass damit!
Pimped Apache Status - PHP 8.2 kompatibel
Der Pimped Apachestatus ist ein Webtool, dass die etwas schwer verdauliche Apache Serverstatus Page aufbereitet. Es gibt verschiedene Ansichten, sortier- und filterbare Tabellen und Graphen. Das ganze funktioniert nicht nur für einen einzelnen Server, sondern auch für mehrere Webhosts, z.B loadbalante Webeiten.
Am Wochenende gab es ein Update, in dem einige Vendor-Bibliotheken aktualisiert wurden.
Da die als kompatibel bestätigte Version 8.0 alsbald ausläuft, wurde es mit neueren PHP Versionen getestet. Es ist nunmehr PHP 8.2 kompatibel.
Zum Aktualisieren meldet sich der Updater. Bei Installationen mit git bitte git pull verwenden.
Weiterführende Links:
Timeshift und Prozentrechnung
Timeshift speichert Snapshots eines Linux-Systems. Es kann sich u.a. als Hook in den Paketmanager einklinken und vor jedem Update einen Snapshot anlegen, um im Falle eines Nicht-Funktionierens zurückzurollen.
- Wenn die Snapshots auch auf der Systemdisk abgelegt werden, wird das Grub-Menü um die Auswahl der letzten Snapshots erweitert.
- Falls nicht, wird ein Rsync zum Sichern des Snapshots bemüht. Wenn man sein Linux booten kann (also notfalls von USB Stick), kann man Timeshift auch so einen anderen Stand wiederherstellen lassen.
Einen kleinen Schönheitsfehler gibt es aber. Im CLI Modus gibt Timeshift eine Fortschrittsinfo aus. Dumm nur, wenn es bei 100% gar nicht fertig ist.
Naja, ich kann darüber hinwegsehen. Wenn der Moment kommt, wo man mal ein Backup braucht, ist man froh um jeden verfügbaren Zwischenstand von so vielen Informationen wie möglich.
Ich fahre auf meinen Linux-PCs mit einer Kombination von Timeshift und Restic (IML Backup). Aber man will ja selbst keinen interaktiven Aufwand und sich nicht darum kümmern. Aber ich weiss, dass ich mich auf das Funktionieren beider Varianten in deren Kombination mit Snapshots und Datei-Backups verlassen kann.
Weiterführende Links
Fehlermuster im Streamripper
Ich schrieb vor nicht allzu langer Zeit einen Blogeintrag, um in Streamripper2 die Aufnahme-Funktion besser zu nutzen.
Diese muss man konfigurieren - also schlusendlich einen Kommandozeilenaufruf hinterlegen. Klassischerweise wird für Radiostreams das Tool Streamripper konfiguriert - und um eine optische Ausgabe zu haben, setzte man einen Konsolenaufruf davor. Ich fand das sehr bescheiden - sehr oft war bei egenen Versuchen war das Konsolenfenster gleich wieder zu und damit auch eine etwaige Fehlermeldung weg. Das ist doch nur unbefriedigend.
So fing alles an. Ich kann zum Glück etwas Shellprogrammierung.
Es sollte zunächst ein kleiner Wrapper sein, der anzeigt, welches Kommando mit welchen Parametern aufgerufen wird - und im Falle eines Abbruchs mich auch den Fehlertext lesen lässt.
Aber das wurde schnell etwas mehr, weil ich mit den ersten Versionen des Wrapperskripts nun auch die verschiedenen Fehlerkonstellationen von Streamripper sehen konnte. Mit Hilfe von Curl wurden die Http Response Header angezeigt, was weitere Dinge aufzeigt. So ergaben sich diese Fehlermuster:
Problem: Fehler 404 oder 410.
Lösung: keine - der Stream existiert nicht mehr.
Problem: Fehler 50x
Lösung: Ein Streamingserver arbeitet derzeit nicht oder reagiert nicht schnell genug (Timeout). Lösen kann ich das nicht, aber eine Meldung ausgeben, damit man weiss, dass es wohl ein nur temporäres Problem gibt und man es später wieder versuchen kann.
Problem: die URL ist kein abspielbarer Stream, sondern eine Playlist.
Lösung: Die Playlist wird ausgelesen und die erste Streaming-URL daraus extrahiert. Anm.: Es gibt durchaus auch Playlisten-Typen, die Streamripper versteht.
Problem: Streamipper wird mit einem 403 abgewiesen.
Lösung: Manche Streamingserver verweigern den Zugriff je nach Useragent und unterbinden den Abruf durch den Streamripper. Aber im Kommandozeilenaufruf des Streamrippers kann man den Useragent umschalten.
Problem: Streamriupper meldet -28 [SR_ERROR_INVALID_METADATA]
Lösung: Keine - das ist ein Fehler im Streamripper selbst: er fordert Daten mit Http1.1 an, versteht aber selbst nur Http 1.0 und kommt dann mit der Antwort des Streamingservers nicht klar. Neben dem kurzen kryptischen Fehlercode wird dann ein ergänzender Hinweis eingeblendet. Es gibt einen nicht offiziellen Patch, mit dem man Streamripper neu complilieren kann - da die letzte Streamripperversion 2008 erschien, wird es wohl nicht mehr offiziell gefixt.
Weil es im Streamripper noch Plugins auf MODarchive und Jamendo gibt: ich habe noch Downloads mit Curl ergänzt:
- für Trackerfiles von MODarchive hinzugefügt (die Benamung der Zieldatei hole ich aus dem Http Response Header aus dem Attachment Filenamen)
- für jamendo MP3s (die Benamung der Zieldati erfolgt nach Aufruf von ffprobe - welches zu ffmpeg gehört - und wird aus Titel, Künstler und Jahr zusammengesetzt)
Im Dezember erschien die Version 1.1 - diese prüft die benötigten Tools und hat eine Erweiterung in der Cleanup-Funktionalität erfahren.
Die kleinen Heilungsfunktionen und verwertbare Meldungen für ein Debugging im Fehlerfalls sind doch immer hilfreich. Das scheint auch anderen zu gefallen. Mario Salzer verlinkte den Wrapper auf fossil.include-once.org - ich setze hiermit einen Link auch gern zu ihm zurück.
weiterführende Links:
Update ahCrawler v0.156
Ich habe ein Update des ahCrawler veröffentlicht.
In diesem Release kamen hinzu
- meine Docker-Entwicklungsumgebung wurde aufgenommen
- die Dokumentation wurde neu geschrieben als Markdown und ebenfalls im Repo aufgenommen
- es gibt zahlreiche Updates im Bereich der Suche im Backend und Frontend.
Das führte dazu, dass die Verzeichnisstruktur des Repos verändert werden musste. Alle bisherigen Files konnten unterhalb Webroot in einem beliebigen Unterverzeichnis geklont werden. Nun wurden alle Webfiles in den Unterordner “public_html” verschoben. Git basierte Installationen machen eine laufende Instanz mit einem Update kaputt, aber ich hoffe, ich habe es gut genug dokumentiert.
weiterführende Links:
Streamtuner2 - Aufnahmen/ Downloads
Ich habe auf meinem Linux PC Streamtuner2 installiert. Das ist ein Browser von (Radio)Streaming Diensten mit deren Kategorien an Musikrichtungen. Was beim Druck auf [Play] zur Wiedergabe oder [Record] zur Aufnahme passieren soll, lässt sich konfigurieren.
Die Wiedergabe - es ist VLC vorkonfiguriert - funktioniert wunderbar. Das reicht wohl Vielen.
Zur Aufnahmefunktion … huh, da wird es langsam kompliziert. Vorkonfiguriert war das Öffnen eines Terminals. Das nimmt naturgemäss ja noch nichts auf. Das Standardwerkzeug unter Linux ist der Streamripper. Den muss man erst einmal konfigurieren.
Das habe ich gemacht. Einige Radiostreams wieden mir angezeigt, dass sie mitgeschnitten würden. Falls nicht, blitzte - wenn überhaupt - für Sekundenbruchteile ein Fenster hoch. Was nicht geht, warum es nicht geht - das zu analysieren, ist bei dieser Verfahrensweise aussichstlos. Was für ein Frust! Und all die Jahre, die Streamtuner und Streamripper existieren, gab es keine tatsächlich schlaue Lösung in der Doku?
Aber: hey, ich kann ja die Record Taste nach Audio-Typ in der Konfiguration belegen, wie ich will! Dann schreiben wir doch ein Skript, auf dass man sehen kann, was da passiert - und wenn nicht, wieso denn nicht.
Schritt 1
Gesagt - getan: ein Skript zeigt die übergebene URL an und was der Streamripper tut - oder aber bei Abbruch allenfalls an Fehlermeldung zurückwirft. Das Skript ist dann nicht einfach fertig - sondern wartet noch eine vordefinierte Zeit. Das war schön und ein Segen, das endlich einmal tatsächlich sehen zu können, an welcher Stelle und bei welchem Typ Url oder MIME Type er die Segel streicht.
Schritt 2
Manche Muster erkennt man: Streamripper kann bei bestimmten Playlist-URLs diese nicht parsen - er braucht dann hier eine Direkt-URL eines Streams, die man aber aus der Playlist ziehen könnte.
Oder es gibt Plugins, die einen Download eines Files anbieten - also gar keine Radiostreams sind, z.B Jamendo und MODarchive. Und beide benötigen unterschiedliche Handhabungsweisen, was bei einem Download zur Benamung der Zieldatei passieren muss.
Oh, es wird ja kompliziert - gut, wenn man noch nen Tick besser skripten kann.
Schritt 3
Wir bauen mal mehr Logik ein. Und Debugging Ausgabe, wie den Http Response Header.
Mein Downloader-Skript bekommt also eine URL. Es muss feststellen, ob es eine Datei oder eine Streaming URL ist. Dazu prüfen wir mal die URL, ob sie Weiterleitungen besitzt. Das letzte “Location:” im Http-Header bei aktiviertem Follow-Redirects ist meine finale URL zum Analysieren.
Jene Url ist entweder ein Stream oder eine Datei. Wenn es eine Datei ist, dann könnte es entweder eine Playlist sein, aus der man eine Streaming URL beziehen muss - oder eine Datei zum Download.
Seine Streaming Url oder ggf. aus der Playlist extrahierte Streaming URL wird an den Streamripper übergeben.
Ein Download File wird hingegen mit Curl heruntergeladen und je nach Typ wird eine Zieldatei geschrieben.
Ich glaube, mit einer solchen Ausgabeform kann man mit der Aufnahmefunktion und etwaigen bereits etwas mehr anfangen:
UPDTAES:
2022-11-14 - the helper script reached version 1.0 now.
weiterführende Links:
- Gihub: axelhahn st2_record_helper
- Streamtuner 2 internet radio directory browser
- Streamripper record streams as mp3 to your hard drive
- Mitteilung auf Fosstodon
Neues Feature beim IML-Backup: Hooks
Nachdem vor 2 Wochen das Prune und Verify separat ausführbar und konfigurierbar wurden, gibt es nun ein weiteres Feature: Hooks.
Das Backup läuft wie folgt ab
- Initialisierung
- Start der Backups der lokalen Datenbanken (z.B. Mysql, Sqlite)
- Backup der definierten lokalen Verzeichnisse
- Prune (Ausdünnen und Löschen alter Backup-Daten)
- Verify
Die Hooks dienen zum Starten von eigenen Skripten … vor dem Start des Backups und danach sowie auch an mehreren Punkten während des Backups.
Es gibt initial diese Verzeichnisse, die du Skripte ablegen kannst, um sie zu definierten Zeitpunkten zu starten:
> tree -d hooks/ hooks/ |-- 10-before-backup | `-- always |-- 12-before-db-service | `-- always |-- 14-before-db-dump (UNUSED) | `-- always |-- 16-after-db-dump (UNUSED) | |-- always | |-- on-error | `-- on-ok |-- 18-after-db-service | |-- always | |-- on-error | `-- on-ok |-- 20-before-transfer | `-- always |-- 22-before-folder-transfer | `-- always |-- 24-after-folder-transfer | |-- always | |-- on-error | `-- on-ok |-- 26-after-prune | |-- always | |-- on-error | `-- on-ok |-- 28-after-verify | |-- always | |-- on-error | `-- on-ok `-- 30-post-backup |-- always |-- on-error `-- on-ok 34 directories
Als am ehesten einleuchtende Beispiele:
- Vor dem Start des Backups kann man Sachen lokal synchronisieren, die ebenfalls ins Backup einfliessen sollen.
- Nach dem Backup kann man beispielsweise Notifikationen ins Monitoring oder per E-mail auslösen.
Bei “nach einer Aktion” zu startenden Hooks kann man jeweils getrennte Sets von Skripten starten, sobald eine Aktion OK war … oder aber fehlerhaft … oder aber auch immer (unabhängig vom Status).
Und wie ist es implementiert? Schauen wir mal auf die Bash-Interna.
Es gibt zu den definierten Zeitpunkten im Skript einen Aufruf einer Hook-Funktion - mit dem Hook-Verzeichnis als Namen als Parameter 1 und für “nach einer Aktion” zu startende Hooks den Exitcode als optionalen 2. Parameter. Als willkürliches Beispiel:
_j_runHooks "24-after-folder-transfer" "$myrc"
Die Hookfunktion ruft bei Exitcode 0 die Skripte im “on-ok” Untrverzeichnis - und bei Exitcode > 0 jene vom “on-error”. Anschliessend (oder bei Aufruf ohne einen Exitcode) werden vom jeweiligen Hook die Skripte im Unterverzeichnis “always” verarbeitet.
Die Ausführung der Skripte erfolgt in alphabetischer Reihenfolge - mit der Benamung kann man also die Abfolge der Abarbeitung mehrerer Skripte beeinflussen.
Die Hookfunktion sieht so aus (genaugenommen erschreckend einfach):
... # ------------------------------------------------------------ # execute hook skripts in a given directory in alphabetic order # param string name of hook directory # param string optional: integer of existcode or "" for non-on-result hook # ------------------------------------------------------------ function _j_runHooks(){ local _hookbase="$1" local _exitcode="$2" local _hookdir="$( dirname $0 )/hooks/$_hookbase" if [ -z "$_exitcode" ]; then _hookdir="$_hookdir/always" elif [ "$_exitcode" = "0" ]; then _hookdir="$_hookdir/on-ok" else _hookdir="$_hookdir/on-error" fi for hookscript in $( ls -1a "$_hookdir" | grep -v "^." | sort ) do if [ -x "$_hookdir/$hookscript" ]; then h3 "HOOK: start $_hookdir/$hookscript ..." $_hookdir/$hookscript else h3 "HOOK: SKIP $_hookdir/$hookscript (not executable) ..." fi done # if an exitcode was given as param then run hooks without exitcode # (in subdir "always") if [ -n "$_exitcode" ]; then _j_runHooks "$_hookbase" fi echo } ...
weiterführende Links:
IML CI Server von PHP 7 auf PHP 8.1 portiert
Der IML CI Server ist ein seit 2015 produktives Werkzeug, mit dem bei uns am Institut gut 50 Projekte ausgerollt werden. Bediente Programmiersprachen für unsere Projekte sind PHP, NodeJs und Ruby - aber eine Zielsprache ist nicht limitiert. Der CI Server erzwingt den Workflow der Installations-Reihenfolge über Preview -> Stage -> Live.
Einschub:
F: Warum beschreibe ich das hier auf einer privaten Webseite?
A: Opensource wird an unserem Institut in einem Ausmass genutzt, dass ohne Opensource Produkte bei unserem Betrieb so ziemlich nichts ginge. Aber auch hauseigene Opensource-Projekte werden auf unserer offiziellen Seite ferngehalten. Begriffe, wie “Opensource” oder “GPL” sind genauso inexistent, wie “mein” hier beschriebener CI Server in der Rubrik Software-Entwicklung.
Wie das Rollout im Groben funktioniert:
Build
- Mit einem Git clone wird der Sourcecode des Projektes in ein temporäres Build-Verzeichnis geholt.
- Das Projekt kann mit einem definierten Hook-Skript Aktionen triggern, um Module nachzuladen, etwas compilieren, Javascript+CSS minimieren … was auch immer
- Was dann noch im Build-Verzeichnis überbleibt, wird zu einem Archiv zusammengepackt und eine Metainfo-Datei angelegt.
- Der CI Server kann die Installation triggern. Mitgeliefert werden 2 Plugins für einen SSH-Aufruf und Ansible AWX. Damit etwaige Tools die Installation starten können - und ohne Zugriff auf den CI-Server im internen Netz haben zu müssen, kann man das Paket per Rsync zu mehreren Zielsystemen syncen, z.B. zu einem Puppet Master oder einem abgesicherten Software-Download-Server (das ist ein seperates Open Source-Projekt).
Installation auf der ersten Phase (Preview)
- Das Paket wartet in der Queue im Modus “zur Installation bereit”. Die Queue besitzt eine zeitliche Freigabe. Man kann erzwingen, dass eine Installation beipielsweise nur von Montag bis Donnerstag im Zeitfenster 14:00-15:00 Uhr erfolgen darf.
- Im Projekt-spezifischen Setup ist festgelegt, ob das Rollout per SSH oder AWX mit entsprechender Parametrisierung erfolgt … und auch welche Zielsysteme existieren. Das AWX Rollout-Plugin holt sich per API die Templates, Inventories und Playbooks vom AWX Server, die in den Prohjekteinstellungen als Dropdown zur Auswahl stehen. Nach einem Build wird das Rollout-Plugin auf die erste Projekt-Phase angewendet, um das Projekt zu installieren.
- Die Implementierung der Installation ist keine Komponente des CI Servers. Es gibt aber eine Bash-Implementierung für ein Installations-Werkzeug (ebenfalls ein separates Opensource Projekt).
- Unsere Installation umfasst … (sicherer) Download des Software Archivs … Entpacken dessen … Start eines Hook-Skripts zur Installation und anderen Aktionen (Cleanup des Cache, Restart von Services) … Generieren von systemspezifischen Konfigurationsdateien mittels Templates
- Feedback an den CI Server, damit dieser weiss, wie weit das Paket ausgerollt wurde.
Rollout auf Stage und Live
Rein technisch ist das identisch mit dem, was zur Installation auf Preview gesagt wurde.
Damit ein Paket von einer zur nächsten Phase freigegeben werden kann, bedingt es die Interaktion - den Klick eines [Accept] Buttons plus Bestätigung, dass man die Featrues und Software-Zustand für OK befunden hat.
Zum Update auf PHP 8.1 habe ich für eine Entwicklungsumgebung mit rootless Docker die benötigte Konfiguration aufgebaut - diese ist im Repository im Unterverzeichnis “docker” enthalten (zuvor habe ich mit einer lokalen Virtualbox-Instanz entwickelt). Das wird Weiterentwicklungen vereinfachen.
Das Update beinhaltet rein die Portierung auf ein aktuelles PHP 8.1 um es auf einem Server mit aktuellesten OS zum Laufen zu bringen. Andere Komponenten, wie Bootstrap 3 sind gnadenlos veraltet und dürfen wohl in naher Zukunft aktualisiert werden.
Screenshots
In der Übersichtsseite aller Projekte kann man filtern, um die Ansicht zum Auffinden “seines” Projektes zu reduzieren.
Ein neuer Build erhält basierend auf dem Hash der Commit ID einen Farbcode. Damit lässt sich optisch darstellen, wie weit ein neuer Build bereits ausgerollt ist. In jeder Phase gibt es [Info] Buttons, die einem Details im Popup aufzeigen.
Erstellen eines neuen Projektes.
Wahlt man ein Projekt, sieht man zunächst eine Seite mit Repo, Archiv (der Builds) und die Phasen des Projekts
In den Projekt-Einstellungen .. Tab Rollout: hier das AWX-Plugin mit den allg. Voreinstellungen. Jedes einzelne Feld lässt sich in jeder der Phasen äbernehmen oder aber nochmals übersteuern.
weiterführende Links:
- Repo: IML CI Server (Opensource; GPL 3.0)
- Docs: IML CI Server auf os-docs.iml.unibe.ch (WIP)
- Repo: IML CI Paket Server (Opensource; GPL 3.0) - Software-Archiv für ein öffentlich zugängliches System, welches nur sichere Downloads mit one time Tokens zulässt
- Docs: IML CI Paket Server auf os-docs.iml.unibe.ch
- Repo: IML CI Deployment Client (Opensource; GPL 3.0) - Bash-Skript zur Installation via IML CI Paket Server, Ondeploy-Hook, Generierung von Konfigurationen aus Templates
- Docs: IML CI Deployment Client auf os-docs.iml.unibe.ch
Update meiner Open source docs
Unter https://www.axel-hahn.de/docs/[POJEKT] habe ich diverse Hilfen für PHP- und Javascript Tools bereitgestellt, die ich mit einem Parser generieren lasse. Jener Ansatz ist etwas älter und länger her - und stellt bereits geraume Zeit so einige meiner Dokumentationen bereit…
Eigentlich suchte ich nach einem mehr generischen Ansatz, um heutzutage in Git übliche Markdown-Dateien in statisches HTML umzuwandeln. Es gibt da diverse Tools, aber ich bin beim PHP-CLI Tool Daux hängengeblieben. Insbesondere, weil ich hier im Gegensatz zu anderen angetesten Werkzeugen keine Extra Konfiguration für einen Navigationsbaum als Config-Datei hinterlegen muss. Auch hat der Entwickler sehr schnell reagiert und auf gemeldete Feature Requests reagiert. Kurz: ich habe nun diverse einzelne Dokumentationen verschiedener Produkte und Klassen mit Daux gebaut. Das sind jeweils statische Verzeichnisse mit statischen HTML-Dateien + Javascript und Css out of the Box in jedem Browser laufen, wenn man sie vom Filesystem oder aber USB-Stick startet.
Was diverse Markdown zu Html Generatoren bieten, ist ein eingebauer Webserver für eine Vorschau. Der hilft beim Schreiben der Markdown-Dateien. Mittlerweile in Markdown Quasi-Standard ist der Support von mathematischen Formeln oder aber Graphen (mermaid.js) - das soweit ich auf Github, Gitlab oder aber lokal im Visual Studio Code per Markdown Preview gesehen habe.
Soweit so gut. Und wenn ich nun zig alleinstehende Dokumentationen habe und eine Index-Seite haben will?
Ich habe dazu einen Ansatz zum Generieren einer Index-Seite wie folgt gewählt:
- ich möchte Gruppen: nach Programmiersprache oder nach einer sonstigen Rubrik
- in jeder Rubrik werden N Projekt-Dokumenationen verlinkt
- … wobei jene referenziert wird als Git-Repository, um diese mit Daux on the fly generieren zu lassen
- … oder aber: weil ich noch meine geparsten Dokumentationen habe: ich kann anderweitig bestehende Dokumentationen ebenfalls einbetten
- die Index-Seite soll flexibel sein und verschiedene Templates/ CSS/ Javascritpt unterstützen
Ich habe dazu ein Bash-Skript geschrieben, das mit jq eine JSON Config-Datei parst und mittels eines Templates die Seitenelemente generieren lässt. Die Flexibilität steckt in den Templates - dese bestimmen, ob es ein
OK, all das ist zu viel Text … so sieht meine Übersichtsseite mit dem Template mit Gruppen und Boxen sieht so aus: Axels Docs
weiterführende Links: (en)
- Axels Docs-Index-Seite
- daux.io Hilfe-generator - Markdown zu HTML
- Github: axelhahn/multidoc-generator
- Statische Hilfe zum multidoc-generator
- Mermaid.js