Einführung
Ein Shell-Skript speichert Befehle in einer Datei, damit Sie eine Aufgabe zuverlässig wiederholen können. Zuverlässige Skripte für Einsteiger legen den Interpreter ausdrücklich fest, setzen Variablenexpansionen in Anführungszeichen, prüfen Eingaben vor der Verarbeitung und geben einen Exit-Status zurück, den andere Befehle auswerten können.
In diesem Lab erstellen Sie schrittweise kleine Bash-Skripte. Sie führen Skripte über Bash und als ausführbare Dateien aus, verwenden Variablen und Positionsargumente, lesen interaktive Eingaben ein, verzweigen mit if und Dateitests, wählen Exit-Codes aus, arbeiten mit for-Schleifen und verbinden diese Konzepte in einem einfachen Log-Zusammenfasser.
Erstes Skript erstellen und ausführen
In diesem Schritt erstellen Sie ein Bash-Skript, führen es über einen Interpreter aus und machen es direkt ausführbar.
Wechseln Sie in das Arbeitsverzeichnis des Labs:
cd /home/labex/project/shell-lab
Erstellen Sie hello.sh mit einem Here-Dokument. Die erste Zeile ist ein Shebang. Er legt Bash fest, wenn Sie die Datei direkt ausführen:
cat > hello.sh <<'EOF'
#!/bin/bash
echo "Hello from a Bash script"
pwd
EOF
Sehen Sie sich die Datei an, bevor Sie sie ausführen:
cat hello.sh
Übergeben Sie die Datei ausdrücklich an Bash. Das funktioniert auch, bevor Sie die Ausführungsberechtigung hinzufügen:
bash hello.sh
Fügen Sie die Ausführungsberechtigung hinzu und prüfen Sie den Modus:
chmod u+x hello.sh
ls -l hello.sh
Führen Sie die Datei aus dem aktuellen Verzeichnis aus. ./ gibt einen Pfad an. Die Shell durchsucht das aktuelle Verzeichnis normalerweise nicht automatisch:
./hello.sh
Variablen verwenden und sicher quoten
In diesem Schritt weisen Sie Variablen Werte zu, expandieren sie und sehen, warum doppelte Anführungszeichen Werte mit Leerzeichen schützen.
Erstellen Sie ein Skript mit zwei Variablen:
cat > variables.sh <<'EOF'
#!/bin/bash
course="Linux for Noobs"
workspace="/home/labex/project/shell-lab"
echo "Course: $course"
echo "Workspace: $workspace"
printf 'Quoted argument count: %s\n' "$#"
printf 'First argument: %s\n' "${1:-not provided}"
EOF
Bei einer Variablenzuweisung dürfen in der Shell keine Leerzeichen um = stehen. Doppelte Anführungszeichen ermöglichen die Expansion von $course und halten Linux for Noobs gleichzeitig als einen einzigen Wert zusammen.
Führen Sie das Skript mit einem Argument aus, das Leerzeichen enthält:
bash variables.sh "beginner learner"
Die spezielle Variable $# enthält die Anzahl der Positionsargumente, und $1 ist das erste Argument. ${1:-not provided} liefert einen Ersatzwert, wenn das erste Argument fehlt.
Speichern Sie die Ausgabe zur Prüfung:
bash variables.sh "beginner learner" > variable-output.txt
cat variable-output.txt
Positionsargumente prüfen
In diesem Schritt verlangen Sie ein Argument, geben eine Nutzungshilfe aus und verwenden unterschiedliche Exit-Status für Fehler und Erfolg.
Erstellen Sie greet-argument.sh:
cat > greet-argument.sh <<'EOF'
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Usage: $0 NAME" >&2
exit 2
fi
name=$1
echo "Hello, $name"
exit 0
EOF
Der Testbefehl [ ... ] prüft, ob die Anzahl der Argumente nicht gleich eins ist. >&2 sendet den Nutzungstext an die Standardfehlerausgabe, und exit 2 meldet eine ungültige Verwendung.
Führen Sie das Skript ohne Argument aus und zeigen Sie anschließend sofort $? an, also den Exit-Status des vorherigen Befehls:
bash greet-argument.sh
echo "missing argument status: $?"
Der erwartete Status ist 2. Führen Sie das Skript nun korrekt aus:
bash greet-argument.sh "Ada Lovelace"
echo "valid argument status: $?"
Speichern Sie die erfolgreiche Begrüßung:
bash greet-argument.sh "Ada Lovelace" > argument-greeting.txt
Interaktive Eingaben lesen
In diesem Schritt fordern Sie eine Eingabe an, lesen sicher eine Zeile ein und behandeln eine leere Eingabe.
Erstellen Sie ask-name.sh:
cat > ask-name.sh <<'EOF'
#!/bin/bash
read -r -p "Enter your name: " name
if [ -z "$name" ]; then
echo "A name is required" >&2
exit 1
fi
echo "Welcome, $name"
EOF
read -r liest eine Zeile ein, ohne Backslashes speziell zu behandeln. -p zeigt eine Eingabeaufforderung an, und -z prüft, ob der Wert in Anführungszeichen leer ist.
Führen Sie das Skript aus:
bash ask-name.sh
Geben Sie an der Eingabeaufforderung Folgendes ein:
Grace Hopper
Sie sollten Welcome, Grace Hopper sehen. Für ein reproduzierbares gespeichertes Ergebnis leiten Sie eine Eingabezeile in dasselbe Skript weiter:
printf 'Grace Hopper\n' | bash ask-name.sh > interactive-greeting.txt
cat interactive-greeting.txt
Mit Dateitests verzweigen
In diesem Schritt verwenden Sie if, elif und else zusammen mit Dateitests, um einen Pfad zu klassifizieren.
Erstellen Sie classify-path.sh:
cat > classify-path.sh <<'EOF'
#!/bin/bash
path=${1:-}
if [ -z "$path" ]; then
echo "Usage: $0 PATH" >&2
exit 2
elif [ -d "$path" ]; then
echo "directory: $path"
elif [ -f "$path" ]; then
echo "file: $path"
else
echo "missing: $path" >&2
exit 1
fi
exit 0
EOF
-d prüft, ob ein Verzeichnis vorhanden ist, und -f, ob es sich um eine reguläre Datei handelt. Die Reihenfolge ist wichtig: Eine ungültige Verwendung wird vor der Prüfung des Pfadtyps behandelt.
Testen Sie alle drei möglichen Ergebnisse:
bash classify-path.sh logs
bash classify-path.sh notes.txt
bash classify-path.sh missing.txt
echo "missing path status: $?"
Speichern Sie erfolgreiche Ergebnisse gemeinsam. && führt den zweiten Befehl nur aus, wenn der erste erfolgreich war:
bash classify-path.sh logs > path-results.txt && bash classify-path.sh notes.txt >> path-results.txt
cat path-results.txt
Mehrere Dateien mit einer For-Schleife verarbeiten
In diesem Schritt durchlaufen Sie Logdateien und zählen die passenden Datensätze in jeder Datei.
Erstellen Sie count-errors.sh:
cat > count-errors.sh <<'EOF'
#!/bin/bash
log_dir=${1:-logs}
if [ ! -d "$log_dir" ]; then
echo "Log directory not found: $log_dir" >&2
exit 1
fi
for log_file in "$log_dir"/*.log; do
error_count=$(grep -c '^ERROR ' "$log_file" || true)
printf '%s errors=%s\n' "$(basename "$log_file")" "$error_count"
done
EOF
Die Schleife weist log_file bei jeder Iteration einen passenden Pfad zu. Die Anführungszeichen um "$log_file" schützen Leerzeichen, während basename das Verzeichnispräfix entfernt. grep -c zählt passende Zeilen. || true verhindert, dass keine Treffer einen größeren strikten Ablauf abbrechen.
Führen Sie die Schleife aus und speichern Sie ihre Ausgabe:
bash count-errors.sh logs | tee error-counts.txt
Sie sollten für jede .log-Datei ein Ergebnis sehen.
Prüfung, Schleifen und Exit-Status kombinieren
In diesem Schritt erstellen Sie ein wiederverwendbares Skript, das ein Verzeichnis prüft, seine Logs zusammenfasst und Erfolg oder Fehlschlag eindeutig meldet.
Erstellen Sie summarize-logs.sh:
cat > summarize-logs.sh <<'EOF'
#!/bin/bash
input_dir=${1:-}
output_file=${2:-}
if [ -z "$input_dir" ] || [ -z "$output_file" ]; then
echo "Usage: $0 INPUT_DIR OUTPUT_FILE" >&2
exit 2
fi
if [ ! -d "$input_dir" ]; then
echo "Input directory not found: $input_dir" >&2
exit 1
fi
: > "$output_file"
for log_file in "$input_dir"/*.log; do
lines=$(wc -l < "$log_file")
errors=$(grep -c '^ERROR ' "$log_file" || true)
printf '%s lines=%s errors=%s\n' "$(basename "$log_file")" "$lines" "$errors" >> "$output_file"
done
echo "Wrote summary to $output_file"
exit 0
EOF
Der Befehl : > "$output_file" erstellt das Ziel sicher oder leert es vor Beginn der Schleife. Führen Sie das Skript mit beiden erforderlichen Argumenten aus:
chmod u+x summarize-logs.sh
./summarize-logs.sh logs log-summary.txt
echo "summary status: $?"
cat log-summary.txt
Testen Sie den Fehlerpfad mit einem nicht vorhandenen Verzeichnis:
./summarize-logs.sh missing log-summary.txt
echo "missing directory status: $?"
Der Erfolgsstatus sollte 0 sein, während der Status für das nicht vorhandene Verzeichnis 1 sein sollte.
Zusammenfassung
Sie haben Bash-Skripte erstellt und ausgeführt, Shebangs und Berechtigungen verwendet, Variablen in Anführungszeichen expandiert, Positions- und interaktive Eingaben gelesen sowie aussagekräftige Exit-Status zurückgegeben. Außerdem haben Sie mit if/elif/else verzweigt, Dateien und Verzeichnisse geprüft, Logs mit for-Schleifen durchlaufen und die Konzepte in einem wiederverwendbaren Zusammenfassungsprogramm kombiniert.
Diese Grundlagen machen spätere Automatisierung leichter lesbar, sicherer erneut ausführbar und für andere Befehle oder geplante Jobs einfacher auswertbar.



