Fr, 8. Juni, 2018

Bash: Ini Dateien Parsen/ Lesen

Bei einigen Servern habe ich einen Cronjob, der ruft ein Shellskript auf, welches den IST Zustand einiger Dienste auflistet. Also, auf einem Server, welche Mysql- und Postgres-Datenbankschemata es gibt, auf dem nächsten welche Apache VHosts existieren und auf dem Fileserver welche Samba-Shares usw.
Schlussendlich landet es auf einem Wiki (Dokuwiki in diesem Fall - hier sind die Seiten Txt-Dateien im Filesystem - das macht die Sache sehr einfach).

Beim Samba Server war es bis anhin recht unschön, weil umständlich gecodet. Nun habe ich 3 kleine Funktionen hinzugefügt, mit denen ich (endlich :-)) eine INI Datei parsen kann.
Die Funktionen kann man in eine Datei mit Leserechten (ohne Execute-Recht) auslagern, die man im Skript sourct (per source oder Punkt-Kommando).

  1. _getInisections [Name der Ini-Datei]
    listet alle Sektionstitel auf
  2. _getInisectiondata [Name der Ini-Datei] [Name der Sektion]
    listet die angegebene Sektion auf. Mit dieser Ausgabe sieht man eine Sektion alleinstehend - und kann sich die Variablen herausziehen … aber wenn man die Variablen kennt, gibt es noch die nächste Funktion
  3. _getIniValue [Name der Ini-Datei] [Name der Sektion] [Name der Variable]
    gibt den Wert einer Variable aus der angegebenen Sektion zurück

In der Samba-Konfiguration (/etc/samba/smb.conf) sind die Variablen und Werte nicht zwingend ab Zeilenanfang - daher sind im Regex Leerzeichen und Tabs hinzugefügt.

# Helper for ini files: get all sections
# param1 - name of the ini file
function _getInisections(){
        local myfile=$1
        grep ”^\[” $myfile | sed ’s,^\[,,’ | sed ’s,\],,’
}
# Helper for ini files: get all content inside a section
# param1 - name of the ini file
# param2 - name of the section in ini file
function _getInisectiondata(){
        local myfile=$1
        local mysection=$2
        mysection=$( sed ”s#/#\/#g” <<< ”$mysection” )
        sed -e ”0,/^&#92;[${mysection}&#92;]/ d” -e ’/^&#92;[/,$ d’ $myfile | grep -v ”^[#;]”
}
# Helper for ini files: get a value of a variable in a given section
# param1 - name of the ini file
# param2 - name of the section in ini file
# param3 - name of the variable to read
function _getIniValue(){
        local myfile=$1
        local mysection=$2
        local myvarname=$3
        _getInisectiondata ${myfile} ${mysection} | grep ”[^&#92;a][&#92; &#92;t]*${myvarname}[&#92; &#92;t]*=.*” | cut -f 2 -d ”=” | sed -e ’s,^&#92; *,,’
}

Und als Anwendungsbeispiel: ein Snippet mit einem Loop über die Samba-Konfiguration. Ausgegeben wird eine Tabelle mit Name des Shares, Beschreibung (Wert “comment”) und Pfad des Shares (Wert “path”):

smbconf=/etc/samba/smb.conf
# Ausgabe des Tabellen-Header in Wiki-Syntax
echo ”^Share^Kommentar^Pfad^”
# Loop ueber alle Sektionen
for mysection in `_getInisections $smbconf | grep -v global`
do
        # Ini-Werte aus der Sektion lesen
        myComment=`_getIniValue ${smbconf} ${mysection} ”comment”`
        mypath=`_getIniValue ${smbconf} ${mysection} ”path”`
        # Ausgabe der Tabellen-Zeile - Pipes sind Spaltentrenner
       echo ”|${mysection}|${myComment}|${mypath}|”
done

UPDATES:

  • 15.05.2019: Korrektur der fehlenden Backslahes (die wirft das Blogtool immer raus, wenn man es nicht als Html-Entity schreibt) plus verbessertes Handling mit laschen Regex und Leerzeichen. Danke an Frank!
  • 04.03.2021: Sektionen mit eckigen Klammern aus Kommentaren ignorieren. Zusätzlich werden Kommentare mit Semikolon am Anfang ebenfalls ignoriert. Ein local macht eine Variable nur innerhalb der Funktion bekannt.
  • 09.02.2022 Update von _getIniValue: [^\a] statt ^
  • 19.03.2023: Ein Follower Projekt: Ich habe aus der class like Bash Funktionen erstellt. Mit Validator und anständiger Dokumentation https://www.axel-hah … docs/bash_iniparser/

Abonnieren