Testsuite zum Auflösen des Installationsverzeichnisses

Testsuite zum Auflösen des Installationsverzeichnisses

Postby hbuhrmester » 13.12.2015, 00:40

Linux-Skripte können auf verschiedene Weise aufgerufen werden: direkt aus dem Installationsverzeichnis heraus, aus einem anderen Verzeichnis, oder mit einem symbolischen Link in ~/bin.

Das Skript sollte in der Lage sein, in das eigene Installationsverzeichnis zu wechseln, egal wie es aufgerufen wird. Dazu wird unter Linux readlink -f verwendet. Damit wird zunächst der Installationspfad des Skripte normalisiert. Mit dirname und basename kann man dann das Installationsverzeichnis und den Skriptnamen extrahieren.

Mit GNU readlink unter Linux funktioniert das einfach und zuverlässig.

Wenn man andere Plattformen unterstützen will, muss man eventuell andere Lösungen suchen. Das BSD readlink aus dem Mac OS X unterstützt die Option -f nicht und ist somit etwas eingeschränkt. Darüber gibt es diverse Diskussionen im Internet:

https://stackoverflow.com/questions/598 ... -stored-in
https://stackoverflow.com/questions/105 ... f-on-a-mac

Auf GitHub hat jemand eine Testsuite zusammengestellt, um verschiedene Lösungen zu vergleichen:

Bash test: get the directory of a script
https://gist.github.com/tvlooy/cbfbdb111a4ebad8b93e

Die einzigen Lösungen, die zuverlässig funktionieren, sind "readlink -f" und eine "overcomplicated stackoverflow solution".

Für das Skript DownloadUpdates.sh könnte man eine ähnliche Testsuite definieren, um alle Anwendungsfälle zu testen:

  1. Aufruf mit bash und dem Skriptnamen: bash DownloadUpdates.sh

    So würde man ein Skript eigentlich nicht aufrufen, da der Skriptinterpreter in der ersten Zeile festgelegt wird. Aber Zip-Archive, die unter Windows erstellt werden, enthalten keine Dateiberechtigungen für Linux; die Skripte sind deshalb zunächst nicht ausführbar. Deshalb heißt es auch in der Hilfe am Anfang des Skripts:

    Please start this program with
    bash $Prog

  2. Direkter Aufruf aus demselben Verzeichnis: ./DownloadUpdates.sh

    Das ist der einfachste Fall und sollte immer funktionieren.

  3. Aufruf aus einem anderen Verzeichnis, gerne auch mit Leerzeichen im Pfad

  4. Aufruf mit einem symbolischen Link aus dem Verzeichnis ~/bin

  5. Rekursiver Aufruf des Skripts

    Das Skript DownloadUpdates.sh ruft sich unter Umständen mehrfach selber auf:

    Wenn man das Skript ohne Parameter startet, kommt man zum interaktiven Setup der Updates, Sprachen und optionalen Downloads. Danach ruft das Skript sich selber mit diesen Parametern auf.

    Wenn man eine der eingebauten Listen wie "All Windows 32 bit" verwendet, ruft das Skript sich wiederum mehrfach selber auf, um diese Listen abzuarbeiten.

Eine Testsuite für ein Skript ähnlich DownloadUpdates.sh sollte alle diese Anwendungsfälle berücksichtigen.

Dazu werden zunächst fünf Skripte script_1.sh bis script_5.sh erstellt. Jedes Skript verwendet eine andere Methode, um das Arbeitsverzeichnis zu setzen. Dann gibt das Skript aus:

  • die Befehlszeile, mit der es aufgerufen wurde
  • das aktuelle Arbeitsverzeichnis, soweit es das Skript herausgefunden hat
  • Dann soll das Skript eine andere Datei aus demselben Verzeichnis einlesen, die "Hello, World!" ausgibt.

Anschließend ruft das Skript sich mehrfach rekursiv auf, um auch diesen speziellen Anwendungsfall zu untersuchen.

Gespeichert werden die Skripte im Verzeichnis "~/tmp/WSUS Offline Update/sh". Das erwartete Ergebnis ist, dass die Skripte bei jedem Test dieses Verzeichnis "/home/anwender/tmp/WSUS Offline Update/sh" und anschließend "Hello, World!" ausgeben.

Die verwendeten Skripte sind:

Skript 1, entsprechend WSUS Offline Update 10.2

Code: Select all
#!/bin/bash

script_name="script_1.sh"

# Print command line
echo "Command line: $0 $*"

# Resolve installation path as in WSUS Offline Update 10.2
cd $( dirname $(readlink -f "$0") )

# Print working directory
echo "Working directory: $(pwd)"

# Include another file
source "hello-world.txt"

# Simulate recursive calls
case "$1" in
    "")
        bash "$script_name" all-x86
    ;;
    all-x86)
        bash "$script_name" w60 glb
        #bash "$script_name" w61 glb
        #bash "$script_name" w62 glb
        #bash "$script_name" w63 glb
        #bash "$script_name" w100 glb
    ;;
    w60 | w61 | w62 | w63 | w100)
        echo "Recognized parameter $1"
    ;;
    *)
        echo "Unknown parameter 1: $1"
    ;;
esac



Skript 2, entsprechend WSUS Offline Update 10.2.1

Code: Select all
#!/bin/bash

script_name="script_2.sh"

# Print command line
echo "Command line: $0 $*"

# Resolve installation path as in WSUS Offline Update 10.2.1
SCRIPT_DIR=$(readlink -f ${0%/*})
cd "$SCRIPT_DIR"

# Print working directory
echo "Working directory: $(pwd)"

# Include another file
source "hello-world.txt"

# Simulate recursive calls
case "$1" in
    "")
        bash "$script_name" all-x86
    ;;
    all-x86)
        bash "$script_name" w60 glb
        #bash "$script_name" w61 glb
        #bash "$script_name" w62 glb
        #bash "$script_name" w63 glb
        #bash "$script_name" w100 glb
    ;;
    w60 | w61 | w62 | w63 | w100)
        echo "Recognized parameter $1"
    ;;
    *)
        echo "Unknown parameter 1: $1"
    ;;
esac



Skript 3, entsprechend WSUS Offline Update trunk-r709

Code: Select all
#!/bin/bash

script_name="script_3.sh"

# Print command line
echo "Command line: $0 $*"

# Resolve installation path as in WSUS Offline Update trunk-r709
cd "$( dirname $(readlink -f "$0") )"

# Print working directory
echo "Working directory: $(pwd)"

# Include another file
source "hello-world.txt"

# Simulate recursive calls
case "$1" in
    "")
        bash "$script_name" all-x86
    ;;
    all-x86)
        bash "$script_name" w60 glb
        #bash "$script_name" w61 glb
        #bash "$script_name" w62 glb
        #bash "$script_name" w63 glb
        #bash "$script_name" w100 glb
    ;;
    w60 | w61 | w62 | w63 | w100)
        echo "Recognized parameter $1"
    ;;
    *)
        echo "Unknown parameter 1: $1"
    ;;
esac



Skript 4, kurze und einfache Lösung

Code: Select all
#!/bin/bash

script_name="script_4.sh"

# Print command line
echo "Command line: $0 $*"

# Resolve installation path, short and simple
cd "$(dirname "$(readlink -f "$0")")"

# Print working directory
echo "Working directory: $(pwd)"

# Include another file
source "hello-world.txt"

# Simulate recursive calls
case "$1" in
    "")
        bash "$script_name" all-x86
    ;;
    all-x86)
        bash "$script_name" w60 glb
        #bash "$script_name" w61 glb
        #bash "$script_name" w62 glb
        #bash "$script_name" w63 glb
        #bash "$script_name" w100 glb
    ;;
    w60 | w61 | w62 | w63 | w100)
        echo "Recognized parameter $1"
    ;;
    *)
        echo "Unknown parameter 1: $1"
    ;;
esac



Skript 5, längere Lösung mit Bestimmung der Verzeichnis- und Skriptnamen

Code: Select all
#!/bin/bash

script_name="script_5.sh"

# Print command line
echo "Command line: $0 $*"

# Resolve installation path, more elaborate solution to get home directory
# and script name
canonical_name=$(readlink -f "$0")
script_name=$(basename "$canonical_name")
home_directory=$(dirname "$canonical_name")
cd "$home_directory"

# Print working directory
echo "Working directory: $(pwd)"

# Include another file
source "hello-world.txt"

# Simulate recursive calls
case "$1" in
    "")
        bash "$script_name" all-x86
    ;;
    all-x86)
        bash "$script_name" w60 glb
        #bash "$script_name" w61 glb
        #bash "$script_name" w62 glb
        #bash "$script_name" w63 glb
        #bash "$script_name" w100 glb
    ;;
    w60 | w61 | w62 | w63 | w100)
        echo "Recognized parameter $1"
    ;;
    *)
        echo "Unknown parameter 1: $1"
    ;;
esac



Aufgerufen werden sie von einem weiteren Kontrollskript:

Code: Select all
#!/bin/bash

# Filename: control_script.sh

for script_name in script_1.sh script_2.sh script_3.sh script_4.sh script_5.sh
do
    echo "Testing script: $script_name"
    echo ""

    echo "Invocation with \"bash $script_name\""
    bash "$script_name"
    echo ""

    echo "Direct call of the script from within the same directory"
    ./"$script_name"
    echo ""

    echo "Calling the script from the home directory"
    pushd ~ > /dev/null
    "tmp/WSUS Offline Update/sh/$script_name"
    popd > /dev/null
    echo ""

    echo "Using a symbolic link in ~/bin"
    pushd ~/bin > /dev/null
    if [[ ! -h "$script_name" ]]; then
        ln -s "../tmp/WSUS Offline Update/sh/$script_name"
    fi
    "$script_name"
    if [[ -h "$script_name" ]]; then
        rm "$script_name"
    fi
    popd > /dev/null
    echo ""
done



Die Textdatei hello-world.txt hat nur den Inhalt:

Code: Select all
echo "Hello, World!"



Die gesamten Ergebnisse:

Code: Select all
~/tmp/WSUS Offline Update/sh$ ./control_script.sh
Testing script: script_1.sh

Invocation with "bash script_1.sh"
Command line: script_1.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender
script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
bash: script_1.sh: Datei oder Verzeichnis nicht gefunden

Direct call of the script from within the same directory
Command line: ./script_1.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender
./script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
bash: script_1.sh: Datei oder Verzeichnis nicht gefunden

Calling the script from the home directory
Command line: tmp/WSUS Offline Update/sh/script_1.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender
tmp/WSUS Offline Update/sh/script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
bash: script_1.sh: Datei oder Verzeichnis nicht gefunden

Using a symbolic link in ~/bin
Command line: /home/anwender/bin/script_1.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender
/home/anwender/bin/script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_1.sh all-x86
Working directory: /home/anwender
/home/anwender/bin/script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_1.sh w60 glb
Working directory: /home/anwender
/home/anwender/bin/script_1.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Recognized parameter w60

Testing script: script_2.sh

Invocation with "bash script_2.sh"
Command line: script_2.sh
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_2.sh all-x86
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_2.sh w60 glb
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Direct call of the script from within the same directory
Command line: ./script_2.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_2.sh all-x86
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_2.sh w60 glb
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Calling the script from the home directory
Command line: tmp/WSUS Offline Update/sh/script_2.sh
readlink: zusätzlicher Operand „Offline“
„readlink --help“ gibt weitere Informationen.
Working directory: /home/anwender
tmp/WSUS Offline Update/sh/script_2.sh: Zeile 16: hello-world.txt: Datei oder Verzeichnis nicht gefunden
bash: script_2.sh: Datei oder Verzeichnis nicht gefunden

Using a symbolic link in ~/bin
Command line: /home/anwender/bin/script_2.sh
Working directory: /home/anwender/bin
/home/anwender/bin/script_2.sh: Zeile 16: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_2.sh all-x86
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/bin
script_2.sh: Zeile 16: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_2.sh w60 glb
script_2.sh: Zeile 10: cd: /home/anwender/tmp/WSUS Offline Update/sh/script_2.sh: Ist kein Verzeichnis
Working directory: /home/anwender/bin
script_2.sh: Zeile 16: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Recognized parameter w60

Testing script: script_3.sh

Invocation with "bash script_3.sh"
Command line: script_3.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_3.sh all-x86
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_3.sh w60 glb
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Direct call of the script from within the same directory
Command line: ./script_3.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_3.sh all-x86
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_3.sh w60 glb
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Calling the script from the home directory
Command line: tmp/WSUS Offline Update/sh/script_3.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender
tmp/WSUS Offline Update/sh/script_3.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
bash: script_3.sh: Datei oder Verzeichnis nicht gefunden

Using a symbolic link in ~/bin
Command line: /home/anwender/bin/script_3.sh
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/bin
/home/anwender/bin/script_3.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_3.sh all-x86
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/bin
script_3.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Command line: script_3.sh w60 glb
dirname: zusätzlicher Operand „Offline“
„dirname --help“ gibt weitere Informationen.
Working directory: /home/anwender/bin
script_3.sh: Zeile 15: hello-world.txt: Datei oder Verzeichnis nicht gefunden
Recognized parameter w60

Testing script: script_4.sh

Invocation with "bash script_4.sh"
Command line: script_4.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Direct call of the script from within the same directory
Command line: ./script_4.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Calling the script from the home directory
Command line: tmp/WSUS Offline Update/sh/script_4.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Using a symbolic link in ~/bin
Command line: /home/anwender/bin/script_4.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_4.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Testing script: script_5.sh

Invocation with "bash script_5.sh"
Command line: script_5.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Direct call of the script from within the same directory
Command line: ./script_5.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Calling the script from the home directory
Command line: tmp/WSUS Offline Update/sh/script_5.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60

Using a symbolic link in ~/bin
Command line: /home/anwender/bin/script_5.sh
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh all-x86
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Command line: script_5.sh w60 glb
Working directory: /home/anwender/tmp/WSUS Offline Update/sh
Hello, World!
Recognized parameter w60



Diskussion der einzelnen Ergebnisse:

Skript 1, entsprechend WSUS Offline Update 10.2

Das aktuelle Arbeitsverzeichnis wird immer falsch gesetzt, und die Textdatei hello-world.txt kann nie gefunden werden.

Skript 2, entsprechend WSUS Offline Update 10.2.1

Beim Aufruf aus demselben Verzeichnis mit "bash script_2.sh" oder "./script_2.sh" meldet cd Fehler, weil das angebliche Installationsverzeichnis kein Verzeichnis ist. Da aber kein Verzeichniswechsel benötigt wird, funktioniert es trotzdem.

Der Aufruf aus dem Home-Verzeichnis und mit einem symbolischen Link schlägt fehl.

Skript 3, entsprechend WSUS Offline Update trunk-r709

Beim Aufruf aus demselben Verzeichnis meldet dirname Fehler. Da aber kein Verzeichniswechsel benötigt wird, funktioniert es trotzdem.

Der Aufruf aus dem Home-Verzeichnis und mit einem symbolischen Link schlägt fehl.

Skript 4, kurze und einfache Lösung

Das Arbeitsverzeichnis wird immer richtig gesetzt und die Textdatei immer gelesen.

Skript 5, längere Lösung mit Bestimmung der Verzeichnis- und Skriptnamen

Das Arbeitsverzeichnis wird immer richtig gesetzt und die Textdatei immer gelesen.
hbuhrmester
 
Posts: 525
Joined: 11.10.2013, 20:59

Return to Linux

Who is online

Users browsing this forum: No registered users and 10 guests