Gestion des erreurs et meilleures pratiques pour les fonctions
Pour notre dernière section, explorons les techniques de gestion des erreurs et les meilleures pratiques pour les fonctions Bash. Une bonne gestion des erreurs est cruciale pour créer des scripts robustes et maintenables.
Création d'un script avec gestion des erreurs
Créons un nouveau script qui illustre une gestion robuste des erreurs :
cd ~/project/bash_functions
touch error_handling.sh
Ajoutez le contenu suivant :
#!/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"
Enregistrez, rendez le script exécutable et exécutez-le :
chmod +x error_handling.sh
./error_handling.sh
Vous verrez une sortie similaire à la suivante et vous serez invité à entrer des nombres :
[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:
Entrez un nombre, par exemple 20
. Ensuite, vous serez invité à entrer le deuxième nombre :
Enter second number:
Entrez un autre nombre, par exemple 4
, et vous devriez voir :
[2023-11-04 13:45:30] [INFO] 20 / 4 = 5.00
[2023-11-04 13:45:30] [INFO] Calculator finished
Meilleures pratiques pour les fonctions Bash
Sur la base de nos exemples, voici quelques meilleures pratiques pour travailler avec les fonctions Bash :
- Ajoutez des commentaires descriptifs - Documentez ce que chaque fonction fait, ses paramètres et ses valeurs de retour.
- Utilisez des noms de fonction significatifs - Choisissez des noms qui indiquent clairement le but de la fonction.
- Validez les paramètres d'entrée - Vérifiez les entrées pour éviter les erreurs.
- Utilisez des variables locales - Évitez les collisions de noms de variables avec le mot-clé
local
.
- Retournez des codes de sortie appropriés - Utilisez des codes de retour conventionnels (0 pour le succès, non nul pour les erreurs).
- Mettez en œuvre une bonne gestion des erreurs - Enregistrez les erreurs et gérez-les de manière gracieuse.
- Gardez les fonctions ciblées - Chaque fonction devrait faire une chose bien.
- Utilisez la composition de fonctions - Construisez des fonctionnalités complexes en combinant des fonctions plus simples.
- Documentez les valeurs de retour - Documentez clairement comment les valeurs sont retournées (via echo, code de retour, etc.).
- Testez les cas limites - Assurez-vous que les fonctions gèrent correctement les entrées inhabituelles.
En suivant ces pratiques, vous pouvez créer des fonctions Bash plus fiables, maintenables et réutilisables.
Création d'une bibliothèque de fonctions
Pour l'exercice final, créons une bibliothèque de fonctions réutilisable :
touch math_functions.lib
Ajoutez le contenu suivant :
#!/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
}
Maintenant, créons un script qui utilise cette bibliothèque :
touch use_library.sh
Ajoutez le contenu suivant :
#!/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
Enregistrez, rendez le script exécutable et exécutez-le :
chmod +x use_library.sh
./use_library.sh
Vous devriez voir :
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
Cette approche de bibliothèque montre comment vous pouvez créer des collections de fonctions réutilisables qui peuvent être importées dans plusieurs scripts, favorisant ainsi la réutilisation du code et la maintenabilité.