Das BICsuite Run Program Teil 5: Umgehung von Einschränkungen

Die maximale Länge von Run Program ist auf 512 Zeichen begrenzt. Normalerweise fühlt sich dies nicht wie eine Einschränkung an. Manchmal jedoch, insbesondere beim Erstellen langer Inline-Skripte, wird die Grenze leicht erreicht.

Aber selbst, wenn die Länge des Feldes Run Program begrenzt ist: Die Commandline, die über einen Parameter ausgeführt wird, ist es nicht. Dies liegt daran, dass die maximale Länge eines Parameterwerts auch praktisch nicht begrenzt ist, Parameter können verwendet werden, um die Beschränkung von 512 Byte zu umgehen. Es ist natürlich vermessen, so etwas zu schreiben, weil wir alle wissen, dass alle Ressourcen endlich sind. Daher wird auch die maximale Länge der Parameter begrenzt sein. Benötigen Parameterwerte hingegen mehr Speicher, als das System überhaupt bietet, ist es an der Zeit, das Konzept der Implementierung zu überdenken.

Wenn wir uns das vorherige Beispiel ansehen, wäre es naheliegend, etwas in dieser Art zu schreiben, wobei REPORTIPS ein Parameter vom Typ Konstante ist, der das auszuführende Skript enthält:

run program = /bin/bash -c "$REPORTIPS"

Aber auch hier besteht die größte Herausforderung darin, das Quoting richtig zu machen, damit alle Variablen vom richtigen Interpreter ausgewertet werden. In unserem Fall sollte NUM vom Scheduling-Server interpretiert werden, $foo und $bar von der Shell und nicht zuletzt $3 von awk.

Wir haben gesehen, dass die Parameterersetzung ein rekursiver Prozess ist; Während die Parameterreferenz durch ihren Wert ersetzt wird, wird der Wert geparst und wenn Parameter gefunden werden, werden diese ebenfalls ersetzt.

Es wäre eine verwirrende Aufgabe, das richtig zu machen, deshalb bietet BICsuite einige Hilfestellungen. Dem Skript kann ein Pragma hinzugefügt werden, das den Server anweist, nicht nach Dollarzeichen, sondern nach einem anderen Zeichen zu suchen. Es würde dann so aussehen:

# BICSUITE_PRAGMA_VPFX:&;
lastb -i -f /var/log/btmp |
awk ’$3 ~ /[0-9]+.[0-9]+.[0-9]+.[0-9]+/ { cnt[$3]++ }
    END {
    for (ip in cnt)
        if (cnt[ip] > "&NUM")
        print ip "\t" cnt[ip]
    }’ | (
while read foo bar; do
    if ! grep -q " $foo/" /etc/sysconfig/iptables; then
        if [ "&VERBOSE" == "Y" ]; then
        echo "# $foo $bar";
        fi;
        echo "-A INPUT -s $foo/32 -j DROP";
        echo "-A OUTPUT -d $foo/32 -j DROP";
    fi;
done) | sort

Was wir hier sehen, ist die Verwendung eines „Pragmas“, BICSUITE_PRAGMA_VPFX (“VPFX” steht für Variable PreFiX), gefolgt von einem Doppelpunkt und einem neuen Zeichen, in diesem Fall einem kaufmännischen Und (&). Da dieses Pragma kein Bash-Befehl ist (und selbst wenn es ein anderes System wäre), setzen wir ein Hash-Zeichen davor, damit es wie ein Kommentar zur Bash aussieht. Das Pragma bewirkt, dass der Scheduling Server nicht nach Dollar, sondern nach dem kaufmännischen Und-Zeichen sucht. Auf diese Weise bleiben alle Variablenreferenzen, egal ob im awk-Code oder im Bash-Code, unberührt. Nur &NUM und &VERBOSE werden durch ihre Werte ersetzt.

Aufgrund der doppelten Anführungszeichen im Ausführungsprogramm wird das Skript als einzelner Parameter an die Bash übergeben. Daher folgt das Anführungszeichen innerhalb des Parameterwertes nun den normalen Bash-Regeln, was das Ganze wesentlich einfacher macht.

Systemabhängige Besonderheiten

Es ist bekannt, dass unterschiedliche Betriebssysteme sich in Bezug auf Textzeilen unterschiedlich verhalten, insbesondere wenn es darum geht, eine Zeile zu beenden. Bei Unix-ähnlichen Systemen reicht ein Linefeed aus, um eine Zeile zu beenden. Windows-Systeme benötigen nicht nur einen Linefeed, sondern auch einen Carriage Return davor. Und Apple-Systeme wollen nur einen Carriage Return. Je nachdem, wie und wo eine Jobdefinition erstellt wird (über die GUI, über sdmsh oder mit einem anderen Dienstprogramm), enthält der Parameterwert unterschiedliche Zeilenenden.

Leider hängt das Verhalten der Bash von diesen Zeilenenden und dem Betriebssystem ab, das die Bash ausführt. Wenn beispielsweise die unter Linux ausgeführte Bash auf einen Carriage Return trifft, wird sie verwirrt (und sieht sie nicht als reinen Leerraum) und das Skript wird nicht ausgeführt. Um die Skripte on the fly reparieren zu können, existiert ein noch nicht dokumentierter Konfigurationsparameter für Jobserver namens CONVERT_NEWLINE (erfordert den neuesten Patch für Release 2.9 und höher; der Konfigurationsparameter ist für Version 2.8 und früher nicht verfügbar). Wenn dieser Parameter gesetzt ist, werden die Zeilenenden entsprechend dem Wert des Parameters konvertiert:

Wert  Effekt
   0  Keine Änderung (Default-Einstellung)
   1  CR-LF wird zu LF konvertiert
   2  LF ohne CR wird zu CR-LF konvertiert

Wie jeder Scope-Konfigurationsparameter kann er auf jeder Ebene innerhalb der Hierarchie eingestellt werden und der eingestellte Wert gilt für den gesamten Teilbaum, sofern er nicht überschrieben wird. Da der Konfigurationsparameter (noch) nicht über die GUI gesetzt werden kann, muss er über die Shell in der GUI oder über sdmsh gesetzt werden. Angenommen, der Parameter muss für den Geltungsbereich GLOBAL.SVR1 gesetzt werden, sieht die Anweisung so aus:

alter scope GLOBAL.’SVR1’
with
        config = (
            ’CONVERT_NEWLINE’ = ’1’
        );

Teil 1: Einführung und einfache Anwendung

Teil 2: Fortgeschrittene Anwendung

Teil 3: Backticks

Teil 4: Andere Interpreter

Teil 5: Umgehung von Einschränkungen

Teil 6: Sicherheitsüberlegungen und Fazit