Shell

⭐ Maîtrise totale

Process Substitution

Technique avancée permettant d'utiliser la sortie d'une commande comme un fichier.

# Comparer la sortie de deux commandes diff <(ls dir1) <(ls dir2) # Utiliser plusieurs process substitutions paste <(cut -d, -f1 file1.csv) <(cut -d, -f2 file2.csv) # Combiner avec while while read line; do echo "Processing: $line" done < <(find . -name "*.txt") # Redirection de sortie tee >(grep ERROR > errors.log) >(grep WARNING > warnings.log) < logfile.txt

Coprocesses et communication inter-processus

#!/bin/bash # Créer un coprocess coproc bc -l # Envoyer des commandes au coprocess echo "scale=2; 10/3" >&"${COPROC[1]}" read -u "${COPROC[0]}" result echo "Résultat : $result" # Named pipes (FIFO) mkfifo mypipe # Dans un terminal cat > mypipe & # Dans un autre echo "Message" > mypipe # Cleanup rm mypipe # Utiliser flock pour la synchronisation ( flock -x 200 echo "Section critique" sleep 2 ) 200>/tmp/mylockfile

Manipulation avancée de chaînes

#!/bin/bash texte="Hello World Programming" # Longueur echo "${#texte}" # 23 # Extraction de sous-chaîne echo "${texte:6:5}" # World echo "${texte:6}" # World Programming echo "${texte: -11}" # Programming # Remplacement echo "${texte/o/O}" # HellO World Programming echo "${texte//o/O}" # HellO WOrld PrOgramming echo "${texte/World/Universe}" # Hello Universe Programming # Suppression de motifs echo "${texte#Hello }" # World Programming echo "${texte##* }" # Programming echo "${texte%Programming}" # Hello World echo "${texte%% *}" # Hello # Case conversion (Bash 4+) echo "${texte^^}" # HELLO WORLD PROGRAMMING echo "${texte,,}" # hello world programming echo "${texte^}" # Hello world programming

Optimisation et performance

Mesurer le temps d'exécution

# Temps simple time ./script.sh # Temps détaillé { time { # Votre code ici for i in {1..1000}; do echo $i > /dev/null done } } 2>&1 # Profiling avec set set -x # Début du profiling # Votre code set +x # Fin du profiling

Parallélisation

#!/bin/bash # Utiliser GNU Parallel parallel echo ::: A B C D # Traiter des fichiers en parallèle find . -name "*.txt" | parallel gzip # Avec xargs find . -name "*.jpg" | xargs -P 4 -I {} convert {} -resize 50% small_{} # Jobs en arrière-plan manuel for i in {1..10}; do ( ./process.sh $i ) & # Limiter à 4 processus parallèles if (( $(jobs -r | wc -l) >= 4 )); then wait -n fi done wait # Attendre tous les jobs

Debugging avancé

#!/bin/bash # Options de debugging set -x # Affiche chaque commande set -v # Affiche les commandes avant expansion set -e # Arrête sur erreur set -u # Erreur sur variable non définie set -o pipefail # Erreur si une commande du pipe échoue # Combiner toutes les options set -euxo pipefail # Créer une fonction de debug DEBUG=true debug() { if [ "$DEBUG" = true ]; then echo "[DEBUG] $@" >&2 fi } # Utilisation debug "Valeur de x: $x" # Trap pour debugging trap 'echo "Ligne $LINENO: Erreur $?"' ERR # Breakpoint basique read -p "Press enter to continue..." # Logger toutes les commandes exec 5> >(logger -t myscript) BASH_XTRACEFD="5" set -x

Networking et API

#!/bin/bash # Utiliser curl # GET request curl https://api.example.com/data # POST request avec JSON curl -X POST \ -H "Content-Type: application/json" \ -d '{"key":"value"}' \ https://api.example.com/endpoint # Sauvegarder dans un fichier curl -o output.json https://api.example.com/data # Suivre les redirections curl -L https://short.url # Avec authentification curl -u user:password https://api.example.com # Wget pour téléchargements wget https://example.com/file.zip # Téléchargement récursif wget -r -np -k https://example.com/docs/ # Test de connectivité nc -zv hostname 80 timeout 5 bash -c 'cat < /dev/null > /dev/tcp/google.com/80' if [ $? -eq 0 ]; then echo "Port ouvert" fi

Parsing complexe et validation

#!/bin/bash # Parser du JSON avec jq json_data='{"name":"Alice","age":30,"city":"Paris"}' echo "$json_data" | jq '.name' echo "$json_data" | jq '.age' # Parser du XML avec xmllint xmllint --xpath "//title/text()" file.xml # Parser du YAML (avec yq) yq eval '.database.host' config.yaml # Validation d'email validate_email() { local email=$1 local regex="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" if [[ $email =~ $regex ]]; then return 0 else return 1 fi } # Validation d'IP validate_ip() { local ip=$1 local regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$" if [[ $ip =~ $regex ]]; then # Vérifier que chaque octet est <= 255 IFS='.' read -ra octets <<< "$ip" for octet in "${octets[@]}"; do if (( octet > 255 )); then return 1 fi done return 0 fi return 1 }

Script système avancé : Monitoring complet

#!/bin/bash # Script de monitoring système complet LOG_FILE="/var/log/system_monitor.log" ALERT_THRESHOLD_CPU=80 ALERT_THRESHOLD_MEM=90 ALERT_THRESHOLD_DISK=85 log_message() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } check_cpu() { local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) local cpu_int=${cpu_usage%.*} if (( cpu_int > ALERT_THRESHOLD_CPU )); then log_message "⚠️ ALERTE CPU: ${cpu_usage}%" return 1 fi log_message "✓ CPU OK: ${cpu_usage}%" return 0 } check_memory() { local mem_usage=$(free | grep Mem | awk '{print ($3/$2) * 100.0}') local mem_int=${mem_usage%.*} if (( mem_int > ALERT_THRESHOLD_MEM )); then log_message "⚠️ ALERTE MEMOIRE: ${mem_usage}%" return 1 fi log_message "✓ Mémoire OK: ${mem_usage}%" return 0 } check_disk() { local disk_usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//') if (( disk_usage > ALERT_THRESHOLD_DISK )); then log_message "⚠️ ALERTE DISQUE: ${disk_usage}%" return 1 fi log_message "✓ Disque OK: ${disk_usage}%" return 0 } check_services() { local services=("nginx" "mysql" "redis") for service in "${services[@]}"; do if systemctl is-active --quiet "$service"; then log_message "✓ Service $service actif" else log_message "⚠️ ALERTE: Service $service inactif" # Optionnel: redémarrer le service # systemctl restart "$service" fi done } main() { log_message "=== Début du monitoring ===" check_cpu check_memory check_disk check_services log_message "=== Fin du monitoring ===" } # Exécuter le monitoring main # Pour automatiser: ajouter à crontab # */5 * * * * /path/to/monitoring.sh

Best Practices et sécurité

#!/bin/bash # 1. Toujours citer les variables fichier="mon fichier.txt" rm "$fichier" # ✓ Correct # rm $fichier # ✗ Dangereux ! # 2. Utiliser [[ ]] au lieu de [ ] if [[ $var == "value" ]]; then # ✓ Plus sûr echo "ok" fi # 3. Vérifier les codes de retour if ! command -v docker &> /dev/null; then echo "Docker n'est pas installé" exit 1 fi # 4. Utiliser des variables locales dans les fonctions ma_fonction() { local var_locale="valeur" # ... } # 5. Valider les entrées utilisateur read -p "Entrez un nombre: " nombre if ! [[ $nombre =~ ^[0-9]+$ ]]; then echo "Erreur: nombre invalide" exit 1 fi # 6. Éviter eval si possible # eval "$cmd" # ✗ Dangereux ! # Utilisez plutôt des arrays ou des fonctions # 7. Nettoyer les fichiers temporaires TMPFILE=$(mktemp) trap "rm -f $TMPFILE" EXIT # 8. Limiter les privilèges if [ "$EUID" -eq 0 ]; then echo "Ne pas exécuter en tant que root !" exit 1 fi

Projets avancés suggérés

  1. Créer un système de déploiement automatisé avec rollback
  2. Développer un outil de monitoring distribué avec alertes
  3. Implémenter un système de backup incrémental avec rotation
  4. Créer un parser de logs avec analyse statistique et graphiques
  5. Développer un orchestrateur de tâches avec gestion de dépendances
  6. Implémenter un système de cache distribué en pure bash