Fehlerbehandlung und Best Practices für Funktionen
In unserem letzten Abschnitt wollen wir Techniken zur Fehlerbehandlung und Best Practices für Bash-Funktionen untersuchen. Die richtige Fehlerbehandlung ist von entscheidender Bedeutung für die Erstellung von robusten und wartbaren Skripten.
Erstellen eines Skripts mit Fehlerbehandlung
Erstellen wir ein neues Skript, das eine robuste Fehlerbehandlung zeigt:
cd ~/project/bash_functions
touch error_handling.sh
Fügen Sie den folgenden Inhalt hinzu:
#!/bin/bash
## Enable error handling
set -e ## Exit immediately if a command exits with non-zero status
## Define a function to log messages
log_message() {
local level="$1"
local message="$2"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message"
}
## Function to validate a number is positive
validate_positive() {
local num="$1"
local name="$2"
## Check if the argument is a number
if ! [[ "$num" =~ ^[0-9]+$ ]]; then
log_message "ERROR" "$name must be a number"
return 1
fi
## Check if the number is positive
if [ "$num" -le 0 ]; then
log_message "ERROR" "$name must be positive"
return 2
fi
return 0
}
## Function that divides two numbers
divide() {
local numerator="$1"
local denominator="$2"
## Validate inputs
validate_positive "$numerator" "Numerator" || return $?
validate_positive "$denominator" "Denominator" || return $?
## Check for division by zero
if [ "$denominator" -eq 0 ]; then
log_message "ERROR" "Division by zero is not allowed"
return 3
fi
## Perform division
local result=$(echo "scale=2; $numerator / $denominator" | bc)
echo "$result"
return 0
}
## Function to safely get user input
get_number() {
local prompt="$1"
local input
while true; do
read -p "$prompt: " input
if validate_positive "$input" "Input"; then
echo "$input"
return 0
else
log_message "WARN" "Invalid input. Please try again."
fi
done
}
## Disable automatic exit on error for the main script
set +e
## Main script logic
log_message "INFO" "Starting division calculator"
## Test with valid values
result=$(divide 10 2)
exit_code=$?
if [ $exit_code -eq 0 ]; then
log_message "INFO" "10 / 2 = $result"
else
log_message "ERROR" "Division failed with code $exit_code"
fi
## Test with invalid values
echo ""
log_message "INFO" "Testing with invalid values"
divide 0 5
log_message "INFO" "Exit code: $?"
divide 10 0
log_message "INFO" "Exit code: $?"
divide abc 5
log_message "INFO" "Exit code: $?"
## Interactive mode
echo ""
log_message "INFO" "Interactive mode"
echo "Let's perform a division. Enter positive numbers."
## Get user input safely
num1=$(get_number "Enter first number")
num2=$(get_number "Enter second number")
## Perform division
result=$(divide "$num1" "$num2")
exit_code=$?
if [ $exit_code -eq 0 ]; then
log_message "INFO" "$num1 / $num2 = $result"
else
log_message "ERROR" "Division failed with code $exit_code"
fi
log_message "INFO" "Calculator finished"
Speichern Sie das Skript, machen Sie es ausführbar und führen Sie es aus:
chmod +x error_handling.sh
./error_handling.sh
Sie werden eine Ausgabe ähnlich der folgenden sehen und aufgefordert, Zahlen einzugeben:
[2023-11-04 13:45:23] [INFO] Starting division calculator
[2023-11-04 13:45:23] [INFO] 10 / 2 = 5.00
[2023-11-04 13:45:23] [INFO] Testing with invalid values
[2023-11-04 13:45:23] [ERROR] Numerator must be positive
[2023-11-04 13:45:23] [INFO] Exit code: 2
[2023-11-04 13:45:23] [ERROR] Division by zero is not allowed
[2023-11-04 13:45:23] [INFO] Exit code: 3
[2023-11-04 13:45:23] [ERROR] Numerator must be a number
[2023-11-04 13:45:23] [INFO] Exit code: 1
[2023-11-04 13:45:23] [INFO] Interactive mode
Let's perform a division. Enter positive numbers.
Enter first number:
Geben Sie eine Zahl ein, beispielsweise 20
. Dann werden Sie zur Eingabe der zweiten Zahl aufgefordert:
Enter second number:
Geben Sie eine weitere Zahl ein, beispielsweise 4
, und Sie sollten Folgendes sehen:
[2023-11-04 13:45:30] [INFO] 20 / 4 = 5.00
[2023-11-04 13:45:30] [INFO] Calculator finished
Best Practices für Bash-Funktionen
Basierend auf unseren Beispielen sind hier einige Best Practices für die Arbeit mit Bash-Funktionen:
- Fügen Sie beschreibende Kommentare hinzu - Dokumentieren Sie, was jede Funktion tut, ihre Parameter und Rückgabewerte.
- Verwenden Sie aussagekräftige Funktionsnamen - Wählen Sie Namen, die eindeutig den Zweck der Funktion anzeigen.
- Validieren Sie Eingabeparameter - Überprüfen Sie die Eingaben, um Fehler zu vermeiden.
- Verwenden Sie lokale Variablen - Verhindern Sie Namenskonflikte von Variablen mit dem Schlüsselwort
local
.
- Geben Sie geeignete Exit-Codes zurück - Verwenden Sie konventionelle Rückgabecodes (0 für Erfolg, von Null verschiedene Werte für Fehler).
- Implementieren Sie eine richtige Fehlerbehandlung - Protokollieren Sie Fehler und behandeln Sie sie gracefully.
- Halten Sie Funktionen fokussiert - Jede Funktion sollte eine Aufgabe gut erledigen.
- Verwenden Sie Funktionszusammensetzung - Bauen Sie komplexe Funktionalität auf, indem Sie einfachere Funktionen kombinieren.
- Dokumentieren Sie Rückgabewerte - Dokumentieren Sie eindeutig, wie Werte zurückgegeben werden (über echo, Rückgabecode usw.).
- Testen Sie Randfälle - Stellen Sie sicher, dass Funktionen ungewöhnliche Eingaben korrekt verarbeiten.
Indem Sie diese Praktiken befolgen, können Sie zuverlässigere, wartbarere und wiederverwendbare Bash-Funktionen erstellen.
Erstellen einer Funktionsbibliothek
Für die letzte Übung wollen wir eine wiederverwendbare Funktionsbibliothek erstellen:
touch math_functions.lib
Fügen Sie den folgenden Inhalt hinzu:
#!/bin/bash
## math_functions.lib - A library of mathematical functions
## Add two numbers
add() {
echo $(($1 + $2))
}
## Subtract second number from first
subtract() {
echo $(($1 - $2))
}
## Multiply two numbers
multiply() {
echo $(($1 * $2))
}
## Divide first number by second (with decimal precision)
divide() {
if [ "$2" -eq 0 ]; then
return 1
fi
echo "scale=2; $1 / $2" | bc
return 0
}
## Calculate power: first number raised to second number
power() {
echo $(($1 ** $2))
}
## Check if a number is even
is_even() {
if (($1 % 2 == 0)); then
return 0
else
return 1
fi
}
## Check if a number is odd
is_odd() {
if is_even "$1"; then
return 1
else
return 0
fi
}
Jetzt erstellen wir ein Skript, das diese Bibliothek verwendet:
touch use_library.sh
Fügen Sie den folgenden Inhalt hinzu:
#!/bin/bash
## Source the math functions library
source math_functions.lib
## Display a header
echo "Math Functions Demo"
echo "------------------"
## Test the functions
echo "Addition: 5 + 3 = $(add 5 3)"
echo "Subtraction: 10 - 4 = $(subtract 10 4)"
echo "Multiplication: 6 * 7 = $(multiply 6 7)"
## Test division with error handling
div_result=$(divide 20 5)
if [ $? -eq 0 ]; then
echo "Division: 20 / 5 = $div_result"
else
echo "Division error: Cannot divide by zero"
fi
## Test division by zero
div_result=$(divide 20 0)
if [ $? -eq 0 ]; then
echo "Division: 20 / 0 = $div_result"
else
echo "Division error: Cannot divide by zero"
fi
echo "Power: 2 ^ 8 = $(power 2 8)"
## Test the even/odd functions
echo ""
echo "Number properties:"
for num in 1 2 3 4 5; do
echo -n "Number $num is "
if is_even $num; then
echo "even"
else
echo "odd"
fi
done
Speichern Sie das Skript, machen Sie es ausführbar und führen Sie es aus:
chmod +x use_library.sh
./use_library.sh
Sie sollten Folgendes sehen:
Math Functions Demo
------------------
Addition: 5 + 3 = 8
Subtraction: 10 - 4 = 6
Multiplication: 6 * 7 = 42
Division: 20 / 5 = 4.00
Division error: Cannot divide by zero
Power: 2 ^ 8 = 256
Number properties:
Number 1 is odd
Number 2 is even
Number 3 is odd
Number 4 is even
Number 5 is odd
Dieser Ansatz mit der Bibliothek zeigt, wie Sie wiederverwendbare Funktionssammlungen erstellen können, die in mehreren Skripten importiert werden können, was die Codewiederverwendung und Wartbarkeit fördert.