Outils & Référence

🐧 Scripts Bash — Linux — Scripts prêts à l'emploi

📜 Scripts Utiles

15 scripts Bash prêts à l'emploi pour l'administration Linux quotidienne.

📜 12 scripts 🟢 3 débutant 🔵 6 confirmé 🔴 3 expert
Nettoyage des logs anciens
Débutant logscronnettoyage

Supprime les fichiers de logs de plus de N jours dans un dossier. À planifier en cron hebdomadaire.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
LOG_DIR="/var/log"        # Dossier des logs
JOURS=30                  # Supprimer logs > 30 jours
EXTENSIONS=("*.log" "*.gz" "*.old")
# ────────────────────────────────────────────────────

echo "[$(date)] Nettoyage des logs dans $LOG_DIR..."

for ext in "${EXTENSIONS[@]}"; do
    trouve=$(find "$LOG_DIR" -name "$ext" -mtime +$JOURS 2>/dev/null)
    if [ -n "$trouve" ]; then
        echo "$trouve" | xargs rm -f
        echo "Supprimés : $(echo "$trouve" | wc -l) fichiers $ext"
    fi
done

# Libérer l'espace des journaux systemd
journalctl --vacuum-time=${JOURS}d --quiet

echo "[$(date)] Nettoyage terminé."
# Cron : 0 2 * * 0 /opt/scripts/clean_logs.sh >> /var/log/clean_logs.log 2>&1
Surveillance espace disque + alerte email
Confirmé diskalerteemailmonitoring

Vérifie l'espace disque sur chaque partition et envoie un email si le seuil est dépassé.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
SEUIL=80                  # Alerte si usage > 80%
EMAIL="admin@monsite.fr"  # Destinataire
HOSTNAME=$(hostname)
# ────────────────────────────────────────────────────

ALERTE=0
MESSAGE="Alerte disque sur $HOSTNAME :\n\n"

while IFS= read -r line; do
    usage=$(echo "$line" | awk '{print $5}' | tr -d '%')
    partition=$(echo "$line" | awk '{print $6}')
    if [ "$usage" -gt "$SEUIL" ] 2>/dev/null; then
        MESSAGE+="⚠️  $partition : ${usage}% utilisé\n"
        ALERTE=1
    fi
done < <(df -h | grep -vE '^Filesystem|tmpfs|udev|cdrom')

if [ "$ALERTE" -eq 1 ]; then
    echo -e "$MESSAGE" | mail -s "⚠️ Alerte disque $HOSTNAME" "$EMAIL"
    echo "Alerte envoyée à $EMAIL"
else
    echo "Espace disque OK (seuil: $SEUIL%)"
fi
# Cron : */30 * * * * /opt/scripts/check_disk.sh
Sauvegarde MySQL / MariaDB
Débutant mysqlbackupcronbdd

Dump de toutes les bases de données MySQL avec rotation automatique des sauvegardes.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
DB_USER="root"
DB_PASS="motdepasse"      # Ou utiliser ~/.my.cnf
BACKUP_DIR="/backup/mysql"
RETENTION=7               # Garder 7 jours
DATE=$(date +%Y%m%d_%H%M%S)
# ────────────────────────────────────────────────────

mkdir -p "$BACKUP_DIR"

# Dump de toutes les bases
databases=$(mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" 2>/dev/null     | grep -Ev "(Database|information_schema|performance_schema|sys)")

for db in $databases; do
    FILE="$BACKUP_DIR/${db}_${DATE}.sql.gz"
    mysqldump -u"$DB_USER" -p"$DB_PASS"         --single-transaction --routines --triggers "$db"         2>/dev/null | gzip > "$FILE"
    echo "✅ $db → $(du -sh $FILE | cut -f1)"
done

# Rotation — supprimer les sauvegardes > RETENTION jours
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION -delete
echo "🗑️  Rotation : fichiers > ${RETENTION}j supprimés"
# Cron : 0 1 * * * /opt/scripts/backup_mysql.sh >> /var/log/backup_mysql.log 2>&1
Gestion des utilisateurs en masse
Confirmé usersuseraddCSVadmin

Crée plusieurs utilisateurs Linux depuis un fichier CSV. Génère automatiquement les mots de passe.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
CSV_FILE="/tmp/users.csv"   # Format: login,prenom,nom,groupe
DEFAULT_GROUP="techniciens"
SHELL="/bin/bash"
# CSV exemple :
# jdupont,Jean,Dupont,techniciens
# amartin,Alice,Martin,admins
# ────────────────────────────────────────────────────

if [ ! -f "$CSV_FILE" ]; then
    echo "❌ Fichier $CSV_FILE introuvable"; exit 1
fi

while IFS=',' read -r login prenom nom groupe; do
    [[ "$login" =~ ^# ]] && continue  # Ignorer les commentaires

    # Vérifier si l'utilisateur existe déjà
    if id "$login" &>/dev/null; then
        echo "⚠️  $login existe déjà — ignoré"
        continue
    fi

    # Générer un mot de passe aléatoire
    PASS=$(openssl rand -base64 12)

    useradd -m -s "$SHELL" -c "$prenom $nom" -G "${groupe:-$DEFAULT_GROUP}" "$login"
    echo "$login:$PASS" | chpasswd
    passwd --expire "$login"  # Forcer le changement au 1er login

    echo "✅ $login ($prenom $nom) — Pass: $PASS"
done < "$CSV_FILE"

echo "Utilisateurs créés. Les mots de passe sont à transmettre de façon sécurisée."
Vérification des services critiques
Débutant systemctlservicesmonitoring

Vérifie que les services critiques tournent et les redémarre automatiquement si nécessaire.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
SERVICES=("nginx" "mysql" "ssh" "fail2ban" "ufw")
EMAIL="admin@monsite.fr"
HOSTNAME=$(hostname)
# ────────────────────────────────────────────────────

ERREURS=0
RAPPORT="Rapport services $HOSTNAME - $(date)\n\n"

for service in "${SERVICES[@]}"; do
    if systemctl is-active --quiet "$service"; then
        RAPPORT+="✅ $service : actif\n"
    else
        RAPPORT+="❌ $service : ARRÊTÉ — tentative de redémarrage\n"
        ERREURS=$((ERREURS + 1))

        # Tentative de redémarrage
        systemctl start "$service" 2>/dev/null
        sleep 3

        if systemctl is-active --quiet "$service"; then
            RAPPORT+="   ↳ ✅ Redémarrage réussi\n"
        else
            RAPPORT+="   ↳ ❌ Échec du redémarrage — intervention manuelle requise\n"
        fi
    fi
done

echo -e "$RAPPORT"
if [ "$ERREURS" -gt 0 ]; then
    echo -e "$RAPPORT" | mail -s "⚠️ Services arrêtés sur $HOSTNAME" "$EMAIL"
fi
# Cron : */5 * * * * /opt/scripts/check_services.sh
Inventaire système complet
Confirmé inventairehardwarerapport

Génère un rapport complet du système : CPU, RAM, disques, réseau, OS, services actifs.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
OUTPUT="/tmp/inventaire_$(hostname)_$(date +%Y%m%d).txt"
# ────────────────────────────────────────────────────

{
echo "════════════════════════════════════════════"
echo " INVENTAIRE SYSTÈME — $(hostname)"
echo " Date : $(date)"
echo "════════════════════════════════════════════"
echo ""
echo "── OS ───────────────────────────────────────"
cat /etc/os-release | grep -E "^NAME|^VERSION="
uname -r
echo ""
echo "── CPU ──────────────────────────────────────"
grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs
echo "Cœurs : $(nproc)"
echo ""
echo "── RAM ──────────────────────────────────────"
free -h | awk 'NR==2{print "Total:"$2" | Utilisé:"$3" | Libre:"$4}'
echo ""
echo "── DISQUES ──────────────────────────────────"
df -h | grep -vE "tmpfs|udev|loop"
echo ""
echo "── RÉSEAU ───────────────────────────────────"
ip -br addr show | grep -v lo
echo ""
echo "── SERVICES ACTIFS ──────────────────────────"
systemctl list-units --type=service --state=running     --no-pager --no-legend | awk '{print $1}' | head -20
echo ""
echo "── DERNIERS LOGINS ──────────────────────────"
last | head -10
} > "$OUTPUT"

echo "✅ Inventaire généré : $OUTPUT"
cat "$OUTPUT"
Rotation et compression des logs applicatifs
Confirmé logrotatecompressionlogs

Compresse les fichiers de logs du jour précédent et supprime les archives trop anciennes.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
APP_LOG_DIR="/var/log/myapp"
ARCHIVE_DIR="/var/log/myapp/archives"
RETENTION_DAYS=90
DATE_HIER=$(date -d "yesterday" +%Y%m%d)
# ────────────────────────────────────────────────────

mkdir -p "$ARCHIVE_DIR"

# Compresser les logs d'hier
for f in "$APP_LOG_DIR"/*.log; do
    [ -f "$f" ] || continue
    TAILLE_AVANT=$(du -sh "$f" | cut -f1)
    gzip -c "$f" > "$ARCHIVE_DIR/$(basename $f)_${DATE_HIER}.gz"
    > "$f"  # Vider le fichier (pas le supprimer — l'app continue d'écrire)
    echo "✅ $(basename $f) : $TAILLE_AVANT → archivé"
done

# Supprimer archives trop anciennes
find "$ARCHIVE_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete
echo "🗑️  Archives > ${RETENTION_DAYS}j supprimées"

# Afficher l'espace récupéré
echo "📊 Espace $APP_LOG_DIR : $(du -sh $APP_LOG_DIR | cut -f1)"
Scan des connexions SSH suspectes
Expert sshsecuriteauth.logfail2ban

Analyse auth.log pour détecter les tentatives de brute-force SSH et affiche les IPs les plus actives.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
LOG_FILE="/var/log/auth.log"    # Debian/Ubuntu
# LOG_FILE="/var/log/secure"    # RHEL/CentOS
SEUIL_ALERTE=10                 # Alerte si > N tentatives
EMAIL="admin@monsite.fr"
# ────────────────────────────────────────────────────

echo "=== Tentatives SSH échouées (dernières 24h) ==="
DEPUIS=$(date -d "24 hours ago" "+%b %e")

# Top IPs attaquantes
echo ""
echo "── Top 10 IPs ──────────────────────────────"
grep "Failed password" "$LOG_FILE"     | awk '{print $(NF-3)}'     | sort | uniq -c | sort -rn | head -10     | awk '{printf "  %4d tentatives → %s
", $1, $2}'

# Compter le total
TOTAL=$(grep -c "Failed password" "$LOG_FILE" 2>/dev/null || echo 0)
echo ""
echo "── Total tentatives : $TOTAL"

# Connexions réussies
echo ""
echo "── Connexions réussies (dernières 24h) ──────"
grep "Accepted" "$LOG_FILE" | tail -20     | awk '{print "  "$1,$2,$3,"→ user:"$9,"depuis:"$11}'

# Alerte si beaucoup de tentatives récentes
RECENTES=$(grep "Failed password" "$LOG_FILE"     | grep "$(date '+%b %e')" | wc -l)
if [ "$RECENTES" -gt "$SEUIL_ALERTE" ]; then
    echo "⚠️  $RECENTES tentatives aujourd'hui — alerte envoyée"
    echo "⚠️ $RECENTES tentatives SSH sur $(hostname) aujourd'hui"         | mail -s "Alerte SSH $(hostname)" "$EMAIL"
fi
Synchronisation rsync vers serveur distant
Confirmé rsyncbackupsshsynchronisation

Synchronise un dossier local vers un serveur distant via SSH avec exclusions et logging.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
SOURCE="/var/www/html/"
DEST_USER="backup"
DEST_HOST="192.168.1.50"
DEST_PATH="/backup/www/"
SSH_KEY="/root/.ssh/id_rsa_backup"
LOG_FILE="/var/log/rsync_backup.log"
EXCLUDES=("*.tmp" "*.cache" ".git/" "node_modules/")
# ────────────────────────────────────────────────────

DEBUT=$(date +%s)
echo "[$(date)] Début synchronisation $SOURCE → $DEST_USER@$DEST_HOST:$DEST_PATH" | tee -a "$LOG_FILE"

# Construire les options d'exclusion
EXCL_OPTS=""
for ex in "${EXCLUDES[@]}"; do
    EXCL_OPTS="$EXCL_OPTS --exclude=$ex"
done

rsync -avz --delete     -e "ssh -i $SSH_KEY -o StrictHostKeyChecking=no"     $EXCL_OPTS     "$SOURCE"     "$DEST_USER@$DEST_HOST:$DEST_PATH"     2>&1 | tee -a "$LOG_FILE"

STATUS=$?
FIN=$(date +%s)
DUREE=$((FIN - DEBUT))

if [ $STATUS -eq 0 ]; then
    echo "[$(date)] ✅ Sync terminée en ${DUREE}s" | tee -a "$LOG_FILE"
else
    echo "[$(date)] ❌ Erreur rsync (code: $STATUS)" | tee -a "$LOG_FILE"
fi
Audit des permissions SUID/SGID
Expert securitesuidpermissionsaudit

Recherche les fichiers avec des permissions SUID/SGID qui peuvent représenter des risques de sécurité.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
RAPPORT="/tmp/audit_suid_$(date +%Y%m%d).txt"
DIRS_A_SCANNER=("/" )
EMAIL="admin@monsite.fr"
# ────────────────────────────────────────────────────

{
echo "=== AUDIT SUID/SGID — $(hostname) — $(date) ==="
echo ""

echo "── Fichiers SUID (s'exécutent en tant que owner) ─────"
find / -xdev -perm -4000 -type f 2>/dev/null     | xargs ls -la 2>/dev/null     | awk '{printf "%-50s %s %s
", $9, $3, $4}'

echo ""
echo "── Fichiers SGID ──────────────────────────────────────"
find / -xdev -perm -2000 -type f 2>/dev/null     | xargs ls -la 2>/dev/null     | awk '{printf "%-50s %s %s
", $9, $3, $4}'

echo ""
echo "── Fichiers world-writable (dangereux) ────────────────"
find / -xdev -perm -0002 -type f 2>/dev/null     | grep -v proc | grep -v sys | head -20

echo ""
echo "── Comptes sans mot de passe ──────────────────────────"
awk -F: '($2 == "" ) {print $1}' /etc/shadow 2>/dev/null

} > "$RAPPORT"

echo "✅ Rapport généré : $RAPPORT"
wc -l "$RAPPORT"
# Optionnel : envoyer par email
# mail -s "Audit SUID $(hostname)" "$EMAIL" < "$RAPPORT"
Déploiement automatique depuis Git
Expert gitdeployCI/CDautomatisation

Script de déploiement : pull Git, installation des dépendances, restart des services.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
APP_DIR="/var/www/monapp"
GIT_BRANCH="main"
SERVICES_A_REDEMARRER=("nginx" "php8.2-fpm")
LOG_FILE="/var/log/deploy.log"
SLACK_WEBHOOK=""          # Optionnel
# ────────────────────────────────────────────────────

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"; }

log "=== Début déploiement ==="
COMMIT_AVANT=$(cd "$APP_DIR" && git rev-parse --short HEAD)

# Pull Git
log "Git pull $GIT_BRANCH..."
cd "$APP_DIR" || { log "❌ Dossier introuvable"; exit 1; }
git fetch --all 2>&1 | tee -a "$LOG_FILE"
git reset --hard "origin/$GIT_BRANCH" 2>&1 | tee -a "$LOG_FILE"
COMMIT_APRES=$(git rev-parse --short HEAD)

if [ "$COMMIT_AVANT" = "$COMMIT_APRES" ]; then
    log "⏩ Aucun changement (commit: $COMMIT_AVANT)"
    exit 0
fi

log "📦 Nouveau commit : $COMMIT_AVANT → $COMMIT_APRES"

# Installer les dépendances si composer.json a changé
if git diff "$COMMIT_AVANT" HEAD -- composer.json | grep -q .; then
    log "Mise à jour Composer..."
    composer install --no-dev --optimize-autoloader 2>&1 | tee -a "$LOG_FILE"
fi

# Redémarrer les services
for svc in "${SERVICES_A_REDEMARRER[@]}"; do
    systemctl reload-or-restart "$svc" && log "✅ $svc redémarré" || log "❌ Erreur $svc"
done

log "=== Déploiement terminé ==="
Rapport de connexions réseau actives
Confirmé netstatssconnexionsreseau

Affiche un résumé des connexions réseau actives, ports en écoute et processus associés.

script
#!/bin/bash
# ─── Variables à modifier ───────────────────────────
OUTPUT="/tmp/netreport_$(date +%Y%m%d_%H%M).txt"
SEUIL_CONNEXIONS=100    # Alerte si > N connexions établies
# ────────────────────────────────────────────────────

{
echo "=== RAPPORT RÉSEAU — $(hostname) — $(date) ==="
echo ""
echo "── Ports en écoute ──────────────────────────"
ss -tlnp | awk 'NR>1 {printf "%-25s %-20s %s
", $4, $1, $6}'

echo ""
echo "── Connexions ESTABLISHED ───────────────────"
ss -tnp state established | awk 'NR>1' | head -30

echo ""
echo "── Statistiques par état ────────────────────"
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

echo ""
echo "── Top IPs connectées ───────────────────────"
ss -tan state established     | awk 'NR>1 {print $5}'     | cut -d: -f1     | sort | uniq -c | sort -rn | head -10

TOTAL_CONN=$(ss -tan state established | awk 'NR>1' | wc -l)
echo ""
echo "── Total connexions établies : $TOTAL_CONN"
} | tee "$OUTPUT"

if [ "$TOTAL_CONN" -gt "$SEUIL_CONNEXIONS" ]; then
    echo "⚠️  Attention : $TOTAL_CONN connexions (seuil: $SEUIL_CONNEXIONS)"
fi
Ajouter Les Fibrés à mes sources préférées
Retrouvez plus souvent nos guides dans vos résultats Google