#!/bin/bash # # Script : sync_ntfs_archive_to_xattr.sh # Objectif : Synchroniser l'attribut NTFS "Archive" en xattr Linux "user.archive" ou "user.noarchive" # Auteur : Pour Johnny # Version : 2.0 - Optimisée ################################################# # Codes couleurs ANSI RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' RESET='\033[0m' ############################## # CONFIGURATION ############################## # Chemin local où ton partage SMB est monté MOUNT_POINT="/mnt/partage" # Partage SMB complet pour smbinfo (exemple //IP_SERVEUR/NOM_PARTAGE) SMB_SHARE="//192.168.1.100/partage" # User SMB pour interrogation (doit avoir accès en lecture) SMB_USER="ton_user" # Dossier temporaire pour logs LOG_DIR="./logs" # Configuration email EMAIL_TO="destinataire@example.com" EMAIL_FROM="systeme@example.com" EMAIL_SUBJECT="Rapport de synchronisation NTFS Archive" # Définir le niveau de parallélisme (nombre de processus simultanés) PARALLEL_JOBS=8 # Vérifier si les commandes nécessaires sont disponibles check_dependencies() { local missing=0 for cmd in find xargs setfattr smbinfo msmtp grep awk; do if ! command -v "$cmd" &> /dev/null; then echo -e "${RED}[ERREUR]${RESET} Commande '$cmd' non trouvée. Veuillez l'installer." >&2 missing=1 fi done if [ $missing -eq 1 ]; then exit 1 fi } # Fonction de logging log() { local level="$1" local message="$2" local color="" case "$level" in "INFO") color="${GREEN}" ;; "WARN") color="${YELLOW}" ;; "ERROR") color="${RED}" ;; "DEBUG") color="${CYAN}" ;; *) color="${RESET}" ;; esac echo -e "${color}[$level]${RESET} $message" echo "[$level] $message" >> "$LOG_FILE" } # Vérifier que le point de montage est accessible check_mount_point() { if [ ! -d "$MOUNT_POINT" ]; then log "ERROR" "Le point de montage $MOUNT_POINT n'existe pas." exit 1 fi if ! mountpoint -q "$MOUNT_POINT"; then log "WARN" "$MOUNT_POINT n'est pas un point de montage valide." fi } # Traiter un fichier process_file() { local fichier="$1" local relative_path="${fichier#$MOUNT_POINT/}" # Utilisation de smbinfo pour lire les File Attributes local ATTRIBUTES ATTRIBUTES=$(smbinfo filebasicinfo "$SMB_SHARE/$relative_path" --user="$SMB_USER" 2>/dev/null | grep "File Attributes" | awk '{print $3}') if [[ -z "$ATTRIBUTES" ]]; then log "WARN" "Impossible de lire les attributs pour $fichier" return 1 fi # Convertir l'attribut de hexadécimal en décimal local DEC_ATTRIBUTES=$((16#$ATTRIBUTES)) # Vérifier si le bit Archive (0x20) est présent if (( ($DEC_ATTRIBUTES & 0x20) == 0x20 )); then # Archive est SET setfattr -n user.archive -v 1 "$fichier" 2>/dev/null setfattr -x user.noarchive "$fichier" 2>/dev/null log "INFO" "user.archive=1 posé sur $relative_path" echo "$relative_path" >> "$ARCHIVE_FILES" else # Archive est UNSET setfattr -n user.noarchive -v 1 "$fichier" 2>/dev/null setfattr -x user.archive "$fichier" 2>/dev/null log "INFO" "user.noarchive=1 posé sur $relative_path" echo "$relative_path" >> "$NOARCHIVE_FILES" fi } export -f process_file export LOG_FILE export SMB_SHARE export SMB_USER export MOUNT_POINT export ARCHIVE_FILES export NOARCHIVE_FILES export -f log # Envoi du rapport par email send_email_report() { local total_files=$1 local archive_files=$2 local noarchive_files=$3 local errors=$4 local duration=$5 { echo "Subject: $EMAIL_SUBJECT" echo "From: $EMAIL_FROM" echo "To: $EMAIL_TO" echo "Content-Type: text/html; charset=UTF-8" echo echo "
" echo "Exécuté le $(date)
" echo "Ce message a été généré automatiquement.
" echo "" } | msmtp --from="$EMAIL_FROM" "$EMAIL_TO" if [ $? -eq 0 ]; then log "INFO" "Rapport email envoyé avec succès à $EMAIL_TO" else log "ERROR" "Échec de l'envoi du rapport email" fi } ############################## # SCRIPT PRINCIPAL ############################## # Vérifier les dépendances check_dependencies # Création des dossiers nécessaires mkdir -p "$LOG_DIR" LOG_FILE="$LOG_DIR/sync_xattr_$(date +%Y%m%d_%H%M%S).log" ARCHIVE_FILES="$LOG_DIR/archive_files_$(date +%Y%m%d_%H%M%S).txt" NOARCHIVE_FILES="$LOG_DIR/noarchive_files_$(date +%Y%m%d_%H%M%S).txt" ERROR_LOG="$LOG_DIR/errors_$(date +%Y%m%d_%H%M%S).txt" # Vérifier le point de montage check_mount_point # Initialiser les fichiers > "$ARCHIVE_FILES" > "$NOARCHIVE_FILES" > "$ERROR_LOG" # Marquer le début de l'exécution START_TIME=$(date +%s) log "INFO" "===== DÉBUT DE LA SYNCHRONISATION =====" log "INFO" "Point de montage: $MOUNT_POINT" log "INFO" "Partage SMB: $SMB_SHARE" # Traitement parallèle des fichiers echo -e "${MAGENTA}Recherche des fichiers...${RESET}" find "$MOUNT_POINT" -type f -print0 | xargs -0 -n1 -P "$PARALLEL_JOBS" -I{} bash -c 'process_file "$@"' _ {} 2>>"$ERROR_LOG" # Statistiques END_TIME=$(date +%s) EXECUTION_TIME=$((END_TIME - START_TIME)) DURATION=$(date -u -d @${EXECUTION_TIME} +"%T") TOTAL_FILES=$(wc -l < <(cat "$ARCHIVE_FILES" "$NOARCHIVE_FILES" 2>/dev/null)) ARCHIVE_COUNT=$(wc -l < "$ARCHIVE_FILES" 2>/dev/null || echo 0) NOARCHIVE_COUNT=$(wc -l < "$NOARCHIVE_FILES" 2>/dev/null || echo 0) ERROR_COUNT=$(grep -c "" "$ERROR_LOG" 2>/dev/null || echo 0) # Résumé final log "INFO" "===== FIN DE LA SYNCHRONISATION =====" log "INFO" "Fichiers traités: $TOTAL_FILES" log "INFO" "Fichiers avec Archive SET: $ARCHIVE_COUNT" log "INFO" "Fichiers avec Archive UNSET: $NOARCHIVE_COUNT" log "INFO" "Erreurs rencontrées: $ERROR_COUNT" log "INFO" "Durée d'exécution: $DURATION" # Envoi du rapport par email send_email_report "$TOTAL_FILES" "$ARCHIVE_COUNT" "$NOARCHIVE_COUNT" "$ERROR_COUNT" "$DURATION" echo -e "${GREEN}===== SYNCHRONISATION TERMINÉE =====${RESET}" echo -e "${BLUE}Rapport complet disponible dans:${RESET} $LOG_FILE" echo -e "${BLUE}Durée d'exécution:${RESET} $DURATION" exit 0