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#!/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#!/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# 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#!/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#!/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#!/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#!/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
}#!/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#!/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