Das BICsuite Run Program Teil 2: Fortgeschrittene Anwendung

Im vorherigen Abschnitt wurde gezeigt, wie Sie Anführungszeichen für das Job Scheduling in Run Program von BICsuite und schedulix verwenden können. Aber manchmal müssen wir auf Umgebungsvariablen zugreifen, um das Verhalten unseres Programms an die speziellen Anforderungen der Ausführungsumgebung anzupassen. Als Beispiel nehmen wir an, dass eine Eingabedatei im Verzeichnis $HOME/input liegt. Wir möchten das unserem Programm printargs mitteilen. Dazu nehmen wir an, dass printargs zwei Kommandozeilenargumente erwartet, -i gibt an, dass die Eingabe in dem Verzeichnis zu finden ist, das durch das darauffolgende Argument angegeben wird.

Wir hätten gerne einen Aufruf in Run Program, der etwa so aussieht:

run program = printargs -i "$HOME/input" …

Aber wir wissen bereits, dass es so nicht funktionieren wird. Der Scheduling Server wird bemängeln, dass er den Parameter HOME nicht auflösen kann. Wenn wir versuchen, das Dollar-Zeichen mit einem Backslash zu escapen, wird das System mit der Zeichenkette $HOME/input arbeiten, ohne zu ahnen, dass der String noch immer unaufgelöste Variablen enthält. Also werden beide Ansätze nicht funktionieren.

Bei genauerer Betrachtung fällt uns auf, dass eine variable Referenz wie $HOME Teil der Shell-Syntax ist. Um die $HOME Variable aufzulösen, müssen wir also eine Shell ins Spiel bringen. Das führt uns zu diesem Versuch:

run program = sh -c "printargs -i \$HOME/input "’$TESTPARM = ’"$TESTPARM"

Das Resultat sieht schon ganz gut aus:

Number of arguments: 6 
arg[0] = -> printargs <- 
arg[1] = -> -i <- 
arg[2] = -> /opt/schedulix/input <- 
arg[3] = -> = <- 
arg[4] = -> Hello <- 
arg[5] = -> World <-

Wie man sieht, werden die Argumente des Shell Aufrufs nicht ausgegeben, sondern nur die Argumente des Programms printargs, das über die Shell gestartet wurde. Aber es gibt noch immer ein paar Details, die wir untersuchen können. Zunächst werfen wir einen Blick in der GUI auf die Run Commandline im Run-Tab des Jobs. Hier sehen wir:

sh "-c" "printargs -i $HOME/input $TESTPARM = Hello World"

Es ist wichtig zu verstehen, dass die angezeigte Run Commandline nicht unbedingt exakt identisch ist mit der Commandline, die ausgeführt wurde. Tatsächlich wird der Aufruf in Run Program ausgewertet und in eine Liste einzelner Argumente aufgeteilt. Diese Liste wird wieder in einen String konvertiert, wobei jedes Argument in doppelte Anführungszeichen gesetzt wird. Das Rendering der Run Commandline funktioniert in den meisten Fällen sehr zuverlässig und liefert ein gutes Bild davon, was geschieht. Im vorherigen Fall ist es leicht zu sehen, dass die tatsächliche Reihe der Argumente so aussieht:

Number of arguments: 3 
arg[0] = -> sh <- 
arg[1] = -> -c <- 
arg[2] = -> printargs -i $HOME/input $TESTPARM = Hello World <-

Jetzt sind wir auch in der Lage, das vorherige Ergebnis unseres Versuchs zu verstehen. Die Shell ruft den Befehl printargs auf und liefert die Argumente, die sie in der Befehlszeichenfolge findet. Sie kann $HOME auflösen, kann aber die Variable $TESTPARM nicht finden. Letzteres wird daher durch einen leeren String ersetzt, während ersteres durch /home/schedulix ersetzt wird.

Auch wenn wir jetzt verstehen, warum die Ausgabe so aussieht, entspricht das noch nicht dem, was wir uns erhofft hatten. Am Ende wollten wir nur das -i $HOME/input zu den Argumenten des Programms printargs hinzufügen, und wir wollten das ursprüngliche Verhalten des Druckens von $TESTPARM = Hello World als einzelnes Argument beibehalten.

Es ist die Shell, die unser sorgfältig gequotetes Run Program zerreißt. Daher müssen wir die Anführungszeichen ausgeklügelt einsetzen, um es richtig zu machen:

run program = sh -c "printargs -i \$HOME/input ’\$TESTPARM = $TESTPARM’"

Die gesamte Befehlszeile, die von der Shell ausgeführt werden muss, ist in doppelte Anführungszeichen eingeschlossen. Diese doppelten Anführungszeichen werden vom Scheduling-Server entfernt, bevor die Liste der Argumente an den Jobserver übergeben wird. Da das folgende $TESTPARM (aus Sicht des Scheduling-Servers) in doppelten Anführungszeichen steht, wird es aufgelöst. Das erste \$TESTPARM bezieht sich nicht auf einen Parameter, da das Dollarzeichen mit Escapezeichen versehen wurde und unverändert bleibt, jedoch ohne den Backslash, der vom Scheduling-Server gefressen wird.

Führen wir diesen Job aus, erhalten wir das gewünschte Resultat:

Number of arguments: 4 
arg[0] = -> printargs <- 
arg[1] = -> -i <- 
arg[2] = -> /opt/schedulix/input <- 
arg[3] = -> $TESTPARM = Hello World <-

Das sieht ziemlich gut aus. Aufgrund dieses tollen Ergebnisses werden wir vielleicht etwas übermütig und wünschen uns, dass der Inhalt des Parameters TESTPARM in doppelte Anführungszeichen eingeschlossen werden muss (aus dem gleichen Grund, warum printargs die Pfeile verwendet). Das stellt sich als schwierig heraus!

Die Lösung des Problems sieht so aus:

run program = sh -c "printargs -i \$HOME/input ’\$TESTPARM = "’"’"$TESTPARM"’"’"’"

Es wäre unfair, diese beeindruckenden Reihen abwechselnde einfacher und doppelter Anführungszeichen nicht zu erklären. Schauen wir also genauer hin:


Wenn wir jetzt die Start- und Endanführungszeichen vorsichtig entfernen, finden wir den String, der von der Shell verdaut wird. Der Übersichtlichkeit halber stellen wir zunächst fest, dass alles, was dem Argument $HOME/input folgt, vom Scheduling-Server als ein einzelnes Argument betrachtet wird. Einige Teile werden jedoch durch Werte ersetzt und einige Backslashes sowie einige Anführungszeichen werden entfernt, bevor es als Argument an die Shell übergeben wird.

Daher beginnt die (Shell-)Kommandozeile mit printargs -i \$HOME/input und wird dann von einem einfachen Anführungszeichen gefolgt (Zeile 2). Das nächste Zeichen ist ein doppeltes Anführungszeichen (Zeile 6). Der Parameter TESTPARM wird aufgelöst und durch seinen Wert ersetzt (Zeile 9). Ein weiteres doppeltes und dann ein einfaches Anführungszeichen wird hinzugefügt, was zu diesem Aufruf führt:

printargs -i $HOME/input ’$TESTPARM = "Hello World"’

Was dann als ein Argument an die Shell übermittelt wird. Ein Versuch mit unserem Test-Job zeigt, dass es so funktioniert:

Number of arguments: 4 
arg[0] = -> printargs <- 
arg[1] = -> -i <- 
arg[2] = -> /opt/schedulix/input <- 
arg[3] = -> $TESTPARM = "Hello World" <-

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