Guide

Nouvelles mises à jour et améliorations de Macfleet.

Gestion d'Utilitaire de Disque d'Entreprise sur macOS

Gérez le stockage et les opérations de disque sur vos appareils MacFleet en utilisant des commandes diskutil avancées et des outils de gestion de stockage d'entreprise. Ce tutoriel couvre la gestion de disque, la sécurité de stockage, la surveillance de conformité et la gestion du cycle de vie de stockage d'entreprise.

Comprendre la Gestion de Disque macOS

macOS fournit plusieurs outils en ligne de commande pour la gestion de disque et de stockage :

  • diskutil - Utilitaire de disque principal pour la gestion de volumes et partitions
  • df - Afficher l'utilisation d'espace disque du système de fichiers
  • du - Afficher l'utilisation d'espace répertoire
  • fsck - Utilitaire de vérification et réparation du système de fichiers
  • APFS - Système de fichiers Apple avec fonctionnalités avancées

Opérations de Disque de Base

Lister Tous les Disques

#!/bin/bash

# Liste de disques de base
diskutil list

echo "Inventaire de disques terminé avec succès"

Informations de Disque Améliorées

#!/bin/bash

# Informations de disque améliorées avec analyse détaillée
get_comprehensive_disk_info() {
    echo "=== Analyse Complète de Disque ==="
    
    # Liste de disques de base
    echo "Inventaire de Disques :"
    diskutil list
    
    echo -e "\nRésumé d'Utilisation de Disque :"
    df -h
    
    echo -e "\nInformations de Conteneur APFS :"
    diskutil apfs list
    
    echo -e "\nInformations de Disque Physique :"
    system_profiler SPStorageDataType
    
    echo -e "\nStatut SMART :"
    for disk in $(diskutil list | grep "^/dev/disk[0-9]" | awk '{print $1}'); do
        echo "Statut SMART pour $disk :"
        smartctl -H "$disk" 2>/dev/null || echo "  Données SMART non disponibles"
    done
}

# Exécuter l'analyse complète
get_comprehensive_disk_info

Catégories de Gestion de Stockage

Classifications de Types de Stockage

#!/bin/bash

# Catégories de stockage d'entreprise pour gestion et application de politiques
declare -A STORAGE_CATEGORIES=(
    ["systeme_critique"]="Volumes système, partitions de démarrage, partitions de récupération"
    ["donnees_utilisateur"]="Répertoires home utilisateur, documents personnels, données d'application"
    ["stockage_application"]="Binaires d'application, frameworks, bibliothèques système"
    ["espace_developpement"]="Environnements de développement, code source, artefacts de build"
    ["contenu_media"]="Vidéos, images, fichiers audio, ressources créatives"
    ["archives_sauvegarde"]="Time Machine, sauvegardes système, stockage d'archives"
    ["cache_temporaire"]="Fichiers cache, données temporaires, journaux système"
    ["volumes_securite"]="Volumes chiffrés, conteneurs sécurisés, stockage de clés"
    ["stockage_reseau"]="Lecteurs réseau montés, stockage cloud, volumes distants"
    ["peripheriques_externes"]="Clés USB, disques durs externes, stockage amovible"
)

# Niveaux de risque de stockage
declare -A RISK_LEVELS=(
    ["systeme_critique"]="critique"
    ["donnees_utilisateur"]="eleve"
    ["stockage_application"]="moyen"
    ["espace_developpement"]="moyen"
    ["contenu_media"]="faible"
    ["archives_sauvegarde"]="eleve"
    ["cache_temporaire"]="faible"
    ["volumes_securite"]="critique"
    ["stockage_reseau"]="moyen"
    ["peripheriques_externes"]="eleve"
)

# Priorités de gestion
declare -A MANAGEMENT_PRIORITIES=(
    ["systeme_critique"]="protection_maximale"
    ["donnees_utilisateur"]="protection_elevee"
    ["stockage_application"]="protection_standard"
    ["espace_developpement"]="protection_standard"
    ["contenu_media"]="protection_basique"
    ["archives_sauvegarde"]="protection_maximale"
    ["cache_temporaire"]="priorite_nettoyage"
    ["volumes_securite"]="protection_maximale"
    ["stockage_reseau"]="priorite_surveillance"
    ["peripheriques_externes"]="verification_securite"
)

print_storage_categories() {
    echo "=== Catégories de Gestion de Stockage ==="
    for category in "${!STORAGE_CATEGORIES[@]}"; do
        echo "Catégorie : $category"
        echo "  Description : ${STORAGE_CATEGORIES[$category]}"
        echo "  Niveau de Risque : ${RISK_LEVELS[$category]}"
        echo "  Priorité de Gestion : ${MANAGEMENT_PRIORITIES[$category]}"
        echo ""
    done
}

# Afficher les catégories disponibles
print_storage_categories

Politiques de Gestion de Disque

Moteur de Politique de Stockage

#!/bin/bash

# Politiques de gestion de stockage pour différentes exigences organisationnelles
declare -A STORAGE_POLICIES=(
    ["entreprise_standard"]="Stockage d'entreprise standard avec sauvegarde et surveillance"
    ["securite_elevee_financiere"]="Stockage haute sécurité pour données financières et sensibles"
    ["flux_creatif"]="Optimisé pour équipes créatives avec gros fichiers média"
    ["environnement_developpement"]="Axé développement avec contrôle de version et optimisation de build"
    ["conformite_stricte"]="Conformité stricte avec exigences de rétention et audit des données"
    ["optimise_performance"]="Axé performance avec optimisation SSD et mise en cache"
    ["efficace_cout"]="Stockage rentable avec hiérarchisation intelligente et nettoyage"
)

# Configurations de politique
get_storage_policy() {
    local policy_type="$1"
    
    case "$policy_type" in
        "entreprise_standard")
            cat << EOF
{
    "chiffrement_requis": true,
    "frequence_sauvegarde": "quotidienne",
    "periode_retention": "90_jours",
    "compression_activee": true,
    "deduplication": true,
    "niveau_surveillance": "standard",
    "analyse_securite": true,
    "nettoyage_automatique": false,
    "optimisation_performance": "equilibree",
    "cadres_conformite": ["iso27001"],
    "surveillance_sante_disque": true,
    "quotas_stockage": {
        "donnees_utilisateur": "100GB",
        "stockage_application": "50GB",
        "cache_temporaire": "10GB"
    }
}
EOF
            ;;
        "securite_elevee_financiere")
            cat << EOF
{
    "chiffrement_requis": true,
    "niveau_chiffrement": "aes256",
    "frequence_sauvegarde": "continue",
    "periode_retention": "2555_jours",
    "compression_activee": false,
    "deduplication": false,
    "niveau_surveillance": "complet",
    "analyse_securite": true,
    "nettoyage_automatique": false,
    "optimisation_performance": "securite_prioritaire",
    "cadres_conformite": ["sox", "pci_dss", "nist"],
    "surveillance_sante_disque": true,
    "sauvegardes_immuables": true,
    "journalisation_acces": "detaillee",
    "verification_integrite": "continue",
    "quotas_stockage": {
        "donnees_utilisateur": "50GB",
        "stockage_application": "25GB",
        "cache_temporaire": "5GB",
        "journaux_audit": "illimite"
    }
}
EOF
            ;;
        "flux_creatif")
            cat << EOF
{
    "chiffrement_requis": false,
    "frequence_sauvegarde": "basee_projet",
    "periode_retention": "365_jours",
    "compression_activee": false,
    "deduplication": false,
    "niveau_surveillance": "performance",
    "analyse_securite": false,
    "nettoyage_automatique": true,
    "optimisation_performance": "vitesse_prioritaire",
    "cadres_conformite": ["confidentialite_client"],
    "surveillance_sante_disque": true,
    "optimisation_gros_fichiers": true,
    "acceleration_cache": true,
    "quotas_stockage": {
        "donnees_utilisateur": "500GB",
        "contenu_media": "2TB",
        "archives_projet": "1TB",
        "cache_temporaire": "100GB"
    }
}
EOF
            ;;
        *)
            echo "Politique de stockage inconnue : $policy_type"
            return 1
            ;;
    esac
}

# Appliquer une politique de stockage
apply_storage_policy() {
    local policy="$1"
    local config_file="/tmp/politique_stockage.json"
    
    echo "Application de la politique de stockage : $policy"
    
    get_storage_policy "$policy" > "$config_file"
    
    if [[ ! -f "$config_file" ]]; then
        echo "❌ Échec de génération de la configuration de politique"
        return 1
    fi
    
    echo "✅ Politique de stockage appliquée avec succès"
    echo "Configuration : $config_file"
    
    # Afficher les paramètres clés de la politique
    echo "=== Résumé de Politique ==="
    echo "Chiffrement Requis : $(jq -r '.chiffrement_requis' "$config_file")"
    echo "Fréquence Sauvegarde : $(jq -r '.frequence_sauvegarde' "$config_file")"
    echo "Période Rétention : $(jq -r '.periode_retention' "$config_file")"
    echo "Niveau Surveillance : $(jq -r '.niveau_surveillance' "$config_file")"
    echo "Optimisation Performance : $(jq -r '.optimisation_performance' "$config_file")"
    
    return 0
}

Opérations de Disque Avancées

Effacement Sécurisé de Disque

#!/bin/bash

# Effacement sécurisé de disque amélioré avec vérification
secure_erase_volume() {
    local identifier="$1"
    local security_level="$2"
    local new_name="$3"
    local filesystem_type="${4:-APFS}"
    
    echo "=== Effacement Sécurisé de Volume ==="
    echo "Cible : $identifier"
    echo "Niveau de Sécurité : $security_level"
    echo "Nouveau Nom : $new_name"
    echo "Système de Fichiers : $filesystem_type"
    
    # Vérifier que le disque existe
    if ! diskutil info "$identifier" &>/dev/null; then
        echo "❌ Erreur : Identifiant de disque '$identifier' non trouvé"
        return 1
    fi
    
    # Obtenir les informations de disque avant effacement
    local disk_info
    disk_info=$(diskutil info "$identifier")
    echo "Informations de Disque :"
    echo "$disk_info"
    
    # Invite de confirmation
    echo ""
    echo "⚠️  ATTENTION : Ceci effacera définitivement toutes les données sur $identifier"
    echo "Volume actuel : $(echo "$disk_info" | grep "Volume Name:" | awk -F': ' '{print $2}')"
    echo "Taille : $(echo "$disk_info" | grep "Disk Size:" | awk -F': ' '{print $2}')"
    
    read -p "Tapez 'CONFIRMER' pour procéder à l'effacement : " confirmation
    if [[ "$confirmation" != "CONFIRMER" ]]; then
        echo "❌ Opération annulée par l'utilisateur"
        return 1
    fi
    
    # Effectuer l'effacement sécurisé basé sur le niveau de sécurité
    case "$security_level" in
        "basique")
            echo "Effacement basique en cours..."
            diskutil eraseVolume "$filesystem_type" "$new_name" "$identifier"
            ;;
        "securise")
            echo "Effacement sécurisé en cours (DoD 5220.22-M)..."
            diskutil secureErase freespace 3 "$identifier"
            diskutil eraseVolume "$filesystem_type" "$new_name" "$identifier"
            ;;
        "militaire")
            echo "Effacement niveau militaire en cours (7 passes)..."
            diskutil secureErase freespace 4 "$identifier"
            diskutil eraseVolume "$filesystem_type" "$new_name" "$identifier"
            ;;
        *)
            echo "❌ Niveau de sécurité inconnu : $security_level"
            return 1
            ;;
    esac
    
    # Vérifier la completion de l'effacement
    if diskutil info "$identifier" | grep -q "Volume Name.*$new_name"; then
        echo "✅ Effacement sécurisé terminé avec succès"
        echo "Nouveau volume : $new_name"
        echo "Système de fichiers : $filesystem_type"
        
        # Journaliser l'opération
        audit_log "Effacement sécurisé terminé : $identifier -> $new_name (Sécurité : $security_level)"
        
        return 0
    else
        echo "❌ Échec de vérification d'effacement"
        return 1
    fi
}

# Exemple d'utilisation
# secure_erase_volume "disk2s1" "securise" "VolumeNettoyé" "APFS"

Système de Gestion de Stockage d'Entreprise

#!/bin/bash

# Système de Gestion de Stockage d'Entreprise MacFleet
# Gestion complète de disque et stockage

# Configuration
CONFIG_DIR="/etc/macfleet/stockage"
LOG_FILE="/var/log/macfleet_gestion_stockage.log"
DATA_DIR="/var/data/macfleet/stockage"
REPORTS_DIR="/var/reports/macfleet/stockage"
AUDIT_LOG="/var/log/macfleet_audit_stockage.log"
BACKUP_DIR="/var/backups/macfleet/stockage"

# Créer les répertoires requis
create_directories() {
    local directories=("$CONFIG_DIR" "$DATA_DIR" "$REPORTS_DIR" "$BACKUP_DIR")
    
    for dir in "${directories[@]}"; do
        if [[ ! -d "$dir" ]]; then
            sudo mkdir -p "$dir"
            sudo chmod 755 "$dir"
        fi
    done
}

# Fonctions de journalisation
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') [ERREUR] $1" | tee -a "$LOG_FILE" >&2
}

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

# Gestion d'inventaire de stockage
initialize_storage_database() {
    local db_file="$DATA_DIR/inventaire_stockage.json"
    
    if [[ ! -f "$db_file" ]]; then
        cat > "$db_file" << EOF
{
    "version": "1.0",
    "cree": "$(date -Iseconds)",
    "peripheriques_stockage": {},
    "configurations_volume": {},
    "surveillance_sante": {},
    "metriques_performance": {},
    "evaluations_securite": {}
}
EOF
        log_action "Base de données de stockage initialisée : $db_file"
    fi
}

# Découverte complète de stockage
discover_storage_infrastructure() {
    local discovery_file="$DATA_DIR/decouverte_stockage_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Début de découverte complète d'infrastructure de stockage"
    
    echo "=== Découverte d'Infrastructure de Stockage ==="
    
    # Périphériques de stockage physiques
    echo "Découverte des périphériques de stockage physiques..."
    local physical_devices
    physical_devices=$(system_profiler SPStorageDataType -json)
    
    # Volumes et partitions logiques
    echo "Analyse des volumes logiques..."
    local logical_volumes
    logical_volumes=$(diskutil list -plist | plutil -convert json -o -)
    
    # Conteneurs et volumes APFS
    echo "Examen des conteneurs APFS..."
    local apfs_containers
    apfs_containers=$(diskutil apfs list -plist | plutil -convert json -o -)
    
    # Volumes montés réseau
    echo "Vérification des volumes réseau..."
    local network_volumes
    network_volumes=$(mount | grep -E "(nfs|smb|afp)" | jq -R . | jq -s .)
    
    # Périphériques externes
    echo "Détection des périphériques externes..."
    local external_devices
    external_devices=$(diskutil list external -plist | plutil -convert json -o -)
    
    # Statut de chiffrement
    echo "Évaluation du statut de chiffrement..."
    local encryption_status=()
    while IFS= read -r volume; do
        if [[ -n "$volume" ]]; then
            local encrypted="false"
            if diskutil info "$volume" | grep -q "FileVault.*Yes"; then
                encrypted="true"
            fi
            encryption_status+=("{\"volume\": \"$volume\", \"chiffre\": $encrypted}")
        fi
    done <<< "$(diskutil list | grep -E "^\s+[0-9]+:" | awk '{print $NF}')"
    
    # Générer rapport de découverte complet
    cat > "$discovery_file" << EOF
{
    "horodatage_decouverte": "$(date -Iseconds)",
    "nom_hote": "$(hostname)",
    "stockage_physique": $physical_devices,
    "volumes_logiques": $logical_volumes,
    "conteneurs_apfs": $apfs_containers,
    "volumes_reseau": $network_volumes,
    "peripheriques_externes": $external_devices,
    "statut_chiffrement": [$(IFS=,; echo "${encryption_status[*]}")],
    "info_systeme": {
        "version_os": "$(sw_vers -productVersion)",
        "stockage_total": "$(df -h / | tail -1 | awk '{print $2}')",
        "stockage_disponible": "$(df -h / | tail -1 | awk '{print $4}')"
    }
}
EOF
    
    log_action "Découverte de stockage terminée : $discovery_file"
    
    # Afficher le résumé
    echo ""
    echo "Résumé de Découverte :"
    echo "  Périphériques Physiques : $(echo "$physical_devices" | jq '.SPStorageDataType | length' 2>/dev/null || echo "0")"
    echo "  Volumes Logiques : $(echo "$logical_volumes" | jq '.AllDisks | length' 2>/dev/null || echo "0")"
    echo "  Conteneurs APFS : $(echo "$apfs_containers" | jq '.Containers | length' 2>/dev/null || echo "0")"
    echo "  Volumes Réseau : $(echo "$network_volumes" | jq '. | length' 2>/dev/null || echo "0")"
    echo "  Périphériques Externes : $(echo "$external_devices" | jq '.AllDisks | length' 2>/dev/null || echo "0")"
    echo "  Rapport de Découverte : $discovery_file"
    
    return 0
}

# Surveillance de santé de volume
monitor_volume_health() {
    local identifier="$1"
    local health_report="/tmp/sante_volume_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Surveillance de Santé de Volume ==="
    echo "Volume Cible : $identifier"
    
    # Initialiser le rapport de santé
    cat > "$health_report" << EOF
{
    "identifiant_volume": "$identifier",
    "horodatage_analyse": "$(date -Iseconds)",
    "nom_hote": "$(hostname)",
    "verifications_sante": {}
}
EOF
    
    # Vérification de volume
    echo "Exécution de vérification de volume..."
    local verify_output
    verify_output=$(diskutil verifyVolume "$identifier" 2>&1)
    local verify_status=$?
    
    # Analyser les résultats de vérification
    local verification_passed=false
    if [[ $verify_status -eq 0 ]] && echo "$verify_output" | grep -q "appears to be OK"; then
        verification_passed=true
    fi
    
    # Vérification statut SMART (si supporté)
    echo "Vérification du statut SMART..."
    local smart_status="inconnu"
    local physical_disk
    physical_disk=$(diskutil info "$identifier" | grep "Part of Whole" | awk '{print $4}')
    
    if [[ -n "$physical_disk" ]]; then
        if smartctl -H "$physical_disk" 2>/dev/null | grep -q "PASSED"; then
            smart_status="reussi"
        elif smartctl -H "$physical_disk" 2>/dev/null | grep -q "FAILED"; then
            smart_status="echec"
        fi
    fi
    
    # Analyse d'utilisation de disque
    echo "Analyse d'utilisation de disque..."
    local disk_usage
    disk_usage=$(df -h "$identifier" 2>/dev/null | tail -1)
    local usage_percent
    usage_percent=$(echo "$disk_usage" | awk '{print $5}' | tr -d '%')
    
    # Test de performance
    echo "Exécution de test de performance..."
    local write_speed read_speed
    local test_file="/Volumes/$(diskutil info "$identifier" | grep "Mount Point" | awk -F': ' '{print $2}' | xargs)/test_vitesse_$$"
    
    if [[ -w "$(dirname "$test_file")" ]]; then
        # Test d'écriture (10MB)
        write_speed=$(dd if=/dev/zero of="$test_file" bs=1m count=10 2>&1 | grep "bytes/sec" | awk '{print $(NF-1)}')
        
        # Test de lecture
        read_speed=$(dd if="$test_file" of=/dev/null bs=1m 2>&1 | grep "bytes/sec" | awk '{print $(NF-1)}')
        
        # Nettoyage
        rm -f "$test_file"
    else
        write_speed="non_disponible"
        read_speed="non_disponible"
    fi
    
    # Mettre à jour le rapport de santé
    jq --argjson verification "$verification_passed" \
       --arg smart_status "$smart_status" \
       --argjson usage_percent "${usage_percent:-0}" \
       --arg write_speed "$write_speed" \
       --arg read_speed "$read_speed" \
       '.verifications_sante = {
          "verification_systeme_fichiers": $verification,
          "statut_smart": $smart_status,
          "pourcentage_utilisation_disque": $usage_percent,
          "vitesse_ecriture_mbps": $write_speed,
          "vitesse_lecture_mbps": $read_speed
        }' "$health_report" > "${health_report}.tmp" && mv "${health_report}.tmp" "$health_report"
    
    # Évaluation de santé
    local health_score=100
    local issues=()
    
    if [[ "$verification_passed" != "true" ]]; then
        ((health_score -= 30))
        issues+=("corruption_systeme_fichiers")
    fi
    
    if [[ "$smart_status" == "echec" ]]; then
        ((health_score -= 50))
        issues+=("echec_smart")
    fi
    
    if [[ ${usage_percent:-0} -gt 90 ]]; then
        ((health_score -= 20))
        issues+=("espace_disque_critique")
    elif [[ ${usage_percent:-0} -gt 80 ]]; then
        ((health_score -= 10))
        issues+=("alerte_espace_disque")
    fi
    
    # Ajouter score de santé et problèmes au rapport
    jq --argjson health_score "$health_score" \
       --argjson issues "$(printf '%s\n' "${issues[@]}" | jq -R . | jq -s .)" \
       '.evaluation_sante = {
          "score_global": $health_score,
          "problemes_detectes": $issues,
          "recommandations": []
        }' "$health_report" > "${health_report}.tmp" && mv "${health_report}.tmp" "$health_report"
    
    # Afficher les résultats
    echo ""
    echo "Résultats d'Évaluation de Santé :"
    echo "  Score de Santé Global : $health_score/100"
    echo "  Vérification Système de Fichiers : $([ "$verification_passed" = "true" ] && echo "✅ RÉUSSI" || echo "❌ ÉCHEC")"
    echo "  Statut SMART : $smart_status"
    echo "  Utilisation Disque : ${usage_percent:-0}%"
    echo "  Vitesse Écriture : $write_speed"
    echo "  Vitesse Lecture : $read_speed"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "  Problèmes Détectés :"
        for issue in "${issues[@]}"; do
            echo "    - $issue"
        done
    else
        echo "  ✅ Aucun problème détecté"
    fi
    
    echo "  Rapport de Santé : $health_report"
    
    # Journaliser la vérification de santé
    audit_log "Vérification santé volume terminée : $identifier (Score : $health_score/100)"
    
    return 0
}

# Fonction principale avec routage de commandes
main() {
    local command="$1"
    shift
    
    # Initialiser
    create_directories
    initialize_storage_database
    
    case "$command" in
        "lister")
            # Liste de disques améliorée
            get_comprehensive_disk_info
            ;;
        "verification_sante")
            monitor_volume_health "$@"
            ;;
        "effacement_securise")
            secure_erase_volume "$@"
            ;;
        "decouvrir")
            discover_storage_infrastructure
            ;;
        "appliquer_politique")
            apply_storage_policy "$@"
            ;;
        "afficher_categories")
            print_storage_categories
            ;;
        "afficher_politiques")
            for policy in entreprise_standard securite_elevee_financiere flux_creatif environnement_developpement conformite_stricte optimise_performance efficace_cout; do
                echo "Politique : $policy"
                get_storage_policy "$policy" | jq .
                echo ""
            done
            ;;
        *)
            echo "Système de Gestion de Stockage d'Entreprise MacFleet"
            echo "Utilisation : $0 <commande> [options]"
            echo ""
            echo "Commandes :"
            echo "  lister                                       - Liste et analyse de disques améliorées"
            echo "  verification_sante <identifiant>             - Surveillance complète de santé de volume"
            echo "  effacement_securise <id> <niveau> <nom>      - Effacement sécurisé de volume"
            echo "  decouvrir                                    - Découverte d'infrastructure de stockage"
            echo "  appliquer_politique <politique>              - Appliquer politique de gestion de stockage"
            echo "  afficher_categories                          - Afficher catégories de stockage"
            echo "  afficher_politiques                          - Afficher politiques de stockage"
            echo ""
            echo "Exemples :"
            echo "  $0 lister"
            echo "  $0 verification_sante disk1s1"
            echo "  $0 effacement_securise disk2s1 securise DisqueNettoye"
            echo "  $0 decouvrir"
            echo "  $0 appliquer_politique entreprise_standard"
            ;;
    esac
}

# Exécuter la fonction principale avec tous les arguments
main "$@"

Configuration de Déploiement en Flotte

Exemple de Configuration de Flotte

{
    "nom_flotte": "Stockage d'Entreprise MacFleet",
    "date_deploiement": "2025-07-07",
    "hotes": [
        "mac-poste-01.entreprise.com",
        "mac-serveur-01.entreprise.com",
        "mac-dev-01.entreprise.com"
    ],
    "politiques_stockage": {
        "defaut": "entreprise_standard",
        "hotes_securises": "securite_elevee_financiere",
        "hotes_creatifs": "flux_creatif"
    },
    "planning_surveillance": {
        "verifications_sante": "quotidiennes",
        "surveillance_performance": "hebdomadaire",
        "audits_securite": "mensuels"
    }
}

Exemple de Liste de Volumes pour Opérations en Masse

# Liste de Volumes pour Opérations en Masse
# Format : identifiant|nom|systeme_fichiers
disk1s1|Macintosh HD|APFS
disk2s1|Volume Données|APFS
disk3s1|Disque Sauvegarde|APFS
disk4s1|Stockage Externe|ExFAT

Considérations de Sécurité

Sécurité de Stockage

  • Application de Chiffrement - S'assurer que tous les volumes sensibles sont chiffrés avec FileVault
  • Effacement Sécurisé - Plusieurs niveaux de sécurité pour destruction appropriée des données
  • Contrôles d'Accès - Surveiller et contrôler l'accès aux ressources de stockage
  • Surveillance d'Intégrité - Vérification continue de l'intégrité du stockage
  • Détection de Menaces - Analyser l'accès non autorisé et activités suspectes

Cadre de Conformité

  • Rétention de Données - Application automatisée des politiques de rétention de données
  • Pistes d'Audit - Journalisation complète de toutes les opérations de stockage
  • Standards de Chiffrement - Conformité avec AES-256 et autres exigences de chiffrement
  • Vérification de Sauvegarde - Vérification automatisée de l'intégrité des sauvegardes
  • Récupération après Sinistre - Procédures de récupération après sinistre axées stockage

Optimisation de Performance

Performance de Stockage

  • Optimisation SSD - Activation TRIM et optimisation d'usure
  • Optimisation APFS - Défragmentation de conteneur et gestion d'instantanés
  • Gestion de Cache - Mise en cache intelligente et optimisation mémoire
  • Surveillance I/O - Surveillance en temps réel de la performance I/O de stockage
  • Détection de Goulots d'Étranglement - Détection et résolution automatisées des problèmes de performance

Guide de Dépannage

Problèmes Courants

Échecs de Vérification de Disque

  • Exécuter First Aid depuis Utilitaire de Disque
  • Démarrer depuis Mode Récupération pour réparations de volume système
  • Vérifier problèmes matériels avec Diagnostics Apple

Dégradation de Performance

  • Surveiller statut SMART pour santé du lecteur
  • Vérifier fragmentation sur anciens systèmes de fichiers
  • Vérifier espace libre adéquat (maintenir 10-15% libre)

Problèmes de Montage/Démontage

  • Vérifier processus utilisant le volume : lsof /Volumes/NomVolume
  • Forcer le démontage si nécessaire : diskutil unmount force /dev/diskXsY
  • Vérifier intégrité système de fichiers avant remontage

Commandes de Diagnostic

# Vérifier santé de disque
diskutil verifyVolume disk1s1

# Surveiller I/O de disque
iostat -d 1

# Vérifier utilisation système de fichiers
df -h

# Voir statut SMART
smartctl -a /dev/disk0

Notes Importantes

  • Sécurité des Données - Toujours sauvegarder les données critiques avant d'effectuer des opérations de disque
  • Privilèges Administratifs - La plupart des opérations de disque nécessitent un accès sudo/administrateur
  • Tests - Tester tous les scripts sur systèmes non-production avant déploiement en flotte
  • Planification de Récupération - Maintenir des lecteurs de récupération amorçables et stratégies de sauvegarde
  • Surveillance - Implémenter surveillance continue pour détection précoce de problèmes
  • Documentation - Conserver des enregistrements détaillés de toutes les configurations et changements de stockage

Gestion des Images Disque sur macOS

Créez et gérez des images disque sur vos appareils MacFleet pour un empaquetage efficace des données, la distribution de logiciels et le déploiement système. Ce tutoriel couvre la création d'images disque à partir de dossiers, les options de formatage avancées, le chiffrement, la compression et les workflows de gestion d'images à l'échelle de l'entreprise.

Comprendre les Images Disque

Les images disque sont des conteneurs de fichiers qui répliquent la structure exacte et le contenu des volumes de stockage, offrant des capacités puissantes pour le déploiement d'entreprise :

Avantages des Images Disque

  • Distribution de Logiciels - Empaqueter applications et configurations pour le déploiement
  • Sauvegarde de Données - Créer des instantanés portables du contenu des dossiers
  • Déploiement Système - Standardiser les configurations sur plusieurs appareils
  • Transport Sécurisé - Images chiffrées pour le transfert de données sensibles
  • Contrôle de Version - Maintenir différentes versions de paquets logiciels
  • Efficacité Réseau - Images compressées réduisent le temps de transfert

Types d'Images Disque

  • .dmg - Apple Disk Image (format principal)
  • .iso - Format ISO 9660 pour compatibilité multi-plateforme
  • .sparseimage - Images sparse qui grandissent selon les besoins
  • .sparsebundle - Format bundle pour stockage réseau

Création Basique d'Images Disque

Dossier Simple vers Image Disque

#!/bin/bash

# Créer une image disque basique à partir d'un dossier
SOURCE_FOLDER="$1"
IMAGE_NAME="$2"
OUTPUT_PATH="$3"

if [[ -z "$SOURCE_FOLDER" || -z "$IMAGE_NAME" || -z "$OUTPUT_PATH" ]]; then
    echo "❌ Utilisation : $0 <dossier_source> <nom_image> <chemin_sortie>"
    echo "Exemple : $0 /Users/Shared MonImage /Users/username/Documents"
    exit 1
fi

# Valider que le dossier source existe
if [[ ! -d "$SOURCE_FOLDER" ]]; then
    echo "❌ Le dossier source n'existe pas : $SOURCE_FOLDER"
    exit 1
fi

# Créer le répertoire de sortie s'il n'existe pas
mkdir -p "$OUTPUT_PATH"

echo "💿 Création d'une image disque à partir du dossier..."
echo "Source : $SOURCE_FOLDER"
echo "Nom de l'image : $IMAGE_NAME"
echo "Sortie : $OUTPUT_PATH/$IMAGE_NAME.dmg"

# Créer l'image disque
if hdiutil create -fs HFS+ -srcfolder "$SOURCE_FOLDER" -volname "$IMAGE_NAME" "$OUTPUT_PATH/$IMAGE_NAME.dmg"; then
    echo "✅ Image disque créée avec succès"
    
    # Obtenir la taille de l'image
    IMAGE_SIZE=$(du -h "$OUTPUT_PATH/$IMAGE_NAME.dmg" | cut -f1)
    echo "Taille de l'image : $IMAGE_SIZE"
    
    # Obtenir la taille du dossier source pour comparaison
    SOURCE_SIZE=$(du -sh "$SOURCE_FOLDER" | cut -f1)
    echo "Taille du dossier source : $SOURCE_SIZE"
else
    echo "❌ Échec de création de l'image disque"
    exit 1
fi

Création d'Image Disque Avancée

#!/bin/bash

# Création d'image disque avancée avec options
create_advanced_disk_image() {
    local source_folder="$1"
    local image_name="$2"
    local output_path="$3"
    local filesystem="${4:-HFS+}"
    local compression="${5:-UDBZ}"
    local encryption="${6:-false}"
    
    if [[ ! -d "$source_folder" ]]; then
        echo "❌ Dossier source non trouvé : $source_folder"
        return 1
    fi
    
    mkdir -p "$output_path"
    
    echo "💿 Création d'une image disque avancée..."
    echo "Source : $source_folder"
    echo "Système de fichiers : $filesystem"
    echo "Compression : $compression"
    echo "Chiffrement : $encryption"
    
    # Construire la commande hdiutil
    local cmd="hdiutil create"
    cmd="$cmd -fs $filesystem"
    cmd="$cmd -srcfolder '$source_folder'"
    cmd="$cmd -volname '$image_name'"
    
    # Ajouter la compression si spécifiée
    if [[ "$compression" != "none" ]]; then
        cmd="$cmd -format $compression"
    fi
    
    # Ajouter le chiffrement si demandé
    if [[ "$encryption" == "true" ]]; then
        cmd="$cmd -encryption AES-256"
        cmd="$cmd -stdinpass"
        echo "🔐 Chiffrement activé - vous serez invité à saisir un mot de passe"
    fi
    
    cmd="$cmd '$output_path/$image_name.dmg'"
    
    # Exécuter la commande
    if [[ "$encryption" == "true" ]]; then
        echo "Entrez le mot de passe pour le chiffrement de l'image disque :"
        read -s password
        echo "$password" | eval "$cmd"
    else
        eval "$cmd"
    fi
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Image disque avancée créée avec succès"
        
        # Afficher les informations de l'image
        echo ""
        echo "=== Informations de l'Image ==="
        hdiutil imageinfo "$output_path/$image_name.dmg" | grep -E "Format|Compressed|Encrypted|Checksum"
        
        return 0
    else
        echo "❌ Échec de création de l'image disque"
        return 1
    fi
}

# Exemples d'utilisation
# create_advanced_disk_image "/Users/Shared" "DonneesPartagees" "/tmp" "HFS+" "UDBZ" "false"
# create_advanced_disk_image "/Applications/MonApp.app" "MonApp" "/tmp" "HFS+" "UDZO" "true"

Options de Système de Fichiers et Format

Systèmes de Fichiers Supportés

#!/bin/bash

# Afficher les options de système de fichiers et format disponibles
show_disk_image_options() {
    echo "=== Systèmes de Fichiers Disponibles ==="
    echo "HFS+     - Mac OS Extended (par défaut)"
    echo "HFS+J    - Mac OS Extended (Journalisé)"
    echo "HFSX     - Mac OS Extended (Sensible à la casse)"
    echo "JHFS+X   - Mac OS Extended (Sensible à la casse, Journalisé)"
    echo "MS-DOS   - FAT32 (compatible avec Windows)"
    echo "UDF      - Universal Disk Format"
    echo "APFS     - Apple File System (macOS 10.13+)"
    echo ""
    
    echo "=== Options de Format d'Image ==="
    echo "UDRO     - Lecture seule, taille plus petite"
    echo "UDCO     - Compression ADC (obsolète)"
    echo "UDZO     - Compression zlib (plus commun)"
    echo "UDBZ     - Compression bzip2 (meilleure compression)"
    echo "ULFO     - Compression lzfse (macOS 10.11+)"
    echo "ULMO     - Compression lzma"
    echo "UFBI     - Appareil entier"
    echo "SPARSE   - Image sparse (grandit selon les besoins)"
    echo "SPARSEBUNDLE - Bundle sparse (convivial réseau)"
    echo ""
    
    echo "=== Options de Chiffrement ==="
    echo "AES-128  - Chiffrement AES 128 bits"
    echo "AES-256  - Chiffrement AES 256 bits (recommandé)"
}

# Créer une image disque avec des options spécifiques
create_custom_disk_image() {
    local source="$1"
    local name="$2"
    local output="$3"
    local fs="$4"
    local format="$5"
    local encrypt="$6"
    
    echo "Création d'une image disque personnalisée avec :"
    echo "  Système de fichiers : $fs"
    echo "  Format : $format"
    echo "  Chiffrement : $encrypt"
    
    local cmd="hdiutil create -fs '$fs' -format '$format'"
    
    if [[ "$encrypt" != "none" ]]; then
        cmd="$cmd -encryption '$encrypt' -stdinpass"
    fi
    
    cmd="$cmd -srcfolder '$source' -volname '$name' '$output/$name.dmg'"
    
    if [[ "$encrypt" != "none" ]]; then
        echo "Entrez le mot de passe de chiffrement :"
        read -s password
        echo "$password" | eval "$cmd"
    else
        eval "$cmd"
    fi
}

# Exemple d'utilisation
# show_disk_image_options
# create_custom_disk_image "/chemin/vers/dossier" "MonImage" "/chemin/sortie" "HFS+" "UDBZ" "AES-256"

Opérations par Lots sur les Images Disque

Création par Lots

#!/bin/bash

# Créer des images disque par lots à partir de plusieurs dossiers
batch_create_disk_images() {
    local base_path="$1"
    local output_dir="$2"
    local filesystem="${3:-HFS+}"
    local format="${4:-UDBZ}"
    
    if [[ ! -d "$base_path" ]]; then
        echo "❌ Chemin de base non trouvé : $base_path"
        return 1
    fi
    
    mkdir -p "$output_dir"
    
    echo "🔄 Démarrage de la création d'images disque par lots..."
    echo "Chemin de base : $base_path"
    echo "Répertoire de sortie : $output_dir"
    echo "Système de fichiers : $filesystem"
    echo "Format : $format"
    echo ""
    
    local success_count=0
    local failed_count=0
    local total_size=0
    
    # Traiter chaque sous-répertoire
    find "$base_path" -type d -mindepth 1 -maxdepth 1 | while read -r folder; do
        local folder_name=$(basename "$folder")
        local image_path="$output_dir/${folder_name}.dmg"
        
        echo "Traitement : $folder_name"
        
        # Ignorer si l'image existe déjà
        if [[ -f "$image_path" ]]; then
            echo "  ⏭️  L'image existe déjà, ignorer"
            continue
        fi
        
        # Créer l'image disque
        if hdiutil create -fs "$filesystem" -format "$format" \
           -srcfolder "$folder" -volname "$folder_name" \
           "$image_path" >/dev/null 2>&1; then
            
            local size=$(du -h "$image_path" | cut -f1)
            echo "  ✅ Créée avec succès ($size)"
            ((success_count++))
            
            # Ajouter au calcul de taille totale
            local size_bytes=$(du -b "$image_path" | cut -f1)
            total_size=$((total_size + size_bytes))
        else
            echo "  ❌ Échec de création de l'image"
            ((failed_count++))
        fi
    done
    
    echo ""
    echo "=== Résumé de l'Opération par Lots ==="
    echo "Réussies : $success_count"
    echo "Échouées : $failed_count"
    echo "Taille totale : $(numfmt --to=iec $total_size)"
}

# Exemple d'utilisation
# batch_create_disk_images "/Users/Shared/Projets" "/tmp/images_projets" "HFS+" "UDBZ"

Vérification et Analyse d'Images

#!/bin/bash

# Vérifier et analyser les images disque
verify_disk_image() {
    local image_path="$1"
    
    if [[ ! -f "$image_path" ]]; then
        echo "❌ Fichier image non trouvé : $image_path"
        return 1
    fi
    
    echo "🔍 Vérification de l'image disque : $(basename "$image_path")"
    
    # Informations basiques de l'image
    echo ""
    echo "=== Informations Basiques ==="
    echo "Taille du fichier : $(du -h "$image_path" | cut -f1)"
    echo "Type de fichier : $(file "$image_path" | cut -d: -f2- | xargs)"
    
    # Informations détaillées de l'image
    echo ""
    echo "=== Informations Détaillées de l'Image ==="
    hdiutil imageinfo "$image_path" | grep -E "Format|Partition|Compressed|Encrypted|Checksum|Total"
    
    # Vérifier l'intégrité de l'image
    echo ""
    echo "=== Vérification d'Intégrité ==="
    if hdiutil verify "$image_path" >/dev/null 2>&1; then
        echo "✅ Intégrité de l'image vérifiée avec succès"
    else
        echo "❌ Échec de vérification d'intégrité de l'image"
        return 1
    fi
    
    # Test de capacité de montage
    echo ""
    echo "=== Test de Montage ==="
    local mount_point=$(mktemp -d)
    
    if hdiutil attach "$image_path" -mountpoint "$mount_point" -nobrowse -quiet; then
        echo "✅ L'image se monte avec succès"
        
        # Obtenir les informations du volume
        echo "Info du volume : $(df -h "$mount_point" | tail -1 | awk '{print $2 " total, " $3 " utilisé, " $4 " disponible"}')"
        
        # Compter le contenu
        local file_count=$(find "$mount_point" -type f | wc -l | xargs)
        local dir_count=$(find "$mount_point" -type d | wc -l | xargs)
        echo "Contenu : $file_count fichiers, $dir_count répertoires"
        
        # Démonter
        hdiutil detach "$mount_point" -quiet
        rmdir "$mount_point"
    else
        echo "❌ Échec de montage de l'image"
        rmdir "$mount_point"
        return 1
    fi
    
    echo ""
    echo "✅ Vérification de l'image terminée avec succès"
    return 0
}

# Vérification par lots
verify_multiple_images() {
    local image_dir="$1"
    
    if [[ ! -d "$image_dir" ]]; then
        echo "❌ Répertoire d'images non trouvé : $image_dir"
        return 1
    fi
    
    echo "🔍 Vérification de toutes les images disque dans : $image_dir"
    echo ""
    
    local verified=0
    local failed=0
    
    find "$image_dir" -name "*.dmg" -type f | while read -r image; do
        echo "Vérification : $(basename "$image")"
        if verify_disk_image "$image" >/dev/null 2>&1; then
            echo "  ✅ Vérifiée"
            ((verified++))
        else
            echo "  ❌ Échouée"
            ((failed++))
        fi
    done
    
    echo ""
    echo "Vérification terminée : $verified réussies, $failed échouées"
}

Gestion d'Images Disque d'Entreprise

#!/bin/bash

# Outil de Gestion d'Images Disque MacFleet
# Création et gestion complètes d'images disque pour environnements d'entreprise

# Configuration
LOG_FILE="/var/log/macfleet_diskimage.log"
BACKUP_DIR="/var/backups/macfleet/images"
REPORT_DIR="/var/reports/macfleet/images"
CONFIG_FILE="/etc/macfleet/image_policy.conf"
TEMP_DIR="/tmp/macfleet_images"

# Paramètres par défaut
DEFAULT_FILESYSTEM="HFS+"
DEFAULT_FORMAT="UDBZ"
DEFAULT_ENCRYPTION="AES-256"
ENABLE_COMPRESSION=true
ENABLE_VERIFICATION=true
MAX_IMAGE_SIZE="10G"
CLEANUP_TEMP_FILES=true

# Fonction de journalisation
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Configurer les répertoires
setup_directories() {
    for dir in "$BACKUP_DIR" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")" "$TEMP_DIR"; do
        if [[ ! -d "$dir" ]]; then
            sudo mkdir -p "$dir"
            log_action "Répertoire créé : $dir"
        fi
    done
}

# Vérifier l'espace disque disponible
check_disk_space() {
    local target_dir="$1"
    local required_space="$2"  # en octets
    
    local available_space=$(df "$target_dir" | tail -1 | awk '{print $4}')
    available_space=$((available_space * 1024))  # Convertir en octets
    
    if [[ "$available_space" -lt "$required_space" ]]; then
        echo "❌ Espace disque insuffisant"
        echo "Requis : $(numfmt --to=iec $required_space)"
        echo "Disponible : $(numfmt --to=iec $available_space)"
        return 1
    fi
    
    return 0
}

# Créer une image disque d'entreprise avec journalisation et validation complètes
create_enterprise_disk_image() {
    local source_path="$1"
    local image_name="$2"
    local output_dir="$3"
    local filesystem="${4:-$DEFAULT_FILESYSTEM}"
    local format="${5:-$DEFAULT_FORMAT}"
    local encrypt="${6:-false}"
    local description="$7"
    
    log_action "Démarrage de la création d'image disque d'entreprise : $image_name"
    
    # Validation
    if [[ ! -d "$source_path" ]]; then
        echo "❌ Chemin source non trouvé : $source_path"
        log_action "ERREUR : Chemin source non trouvé : $source_path"
        return 1
    fi
    
    # Calculer la taille source
    local source_size_bytes=$(du -sb "$source_path" | cut -f1)
    local source_size_human=$(du -sh "$source_path" | cut -f1)
    
    echo "📁 Analyse source :"
    echo "  Chemin : $source_path"
    echo "  Taille : $source_size_human ($source_size_bytes octets)"
    
    # Vérifier l'espace disque (estimer 2x la taille source pour sécurité)
    local estimated_space=$((source_size_bytes * 2))
    if ! check_disk_space "$output_dir" "$estimated_space"; then
        log_action "ERREUR : Espace disque insuffisant pour la création d'image"
        return 1
    fi
    
    # Créer le répertoire de sortie
    mkdir -p "$output_dir"
    
    local output_path="$output_dir/$image_name.dmg"
    local start_time=$(date +%s)
    
    echo ""
    echo "💿 Création de l'image disque..."
    echo "  Nom : $image_name"
    echo "  Système de fichiers : $filesystem"
    echo "  Format : $format"
    echo "  Sortie : $output_path"
    
    # Construire la commande
    local cmd="hdiutil create -fs '$filesystem' -format '$format'"
    cmd="$cmd -srcfolder '$source_path' -volname '$image_name'"
    
    # Ajouter le chiffrement si demandé
    if [[ "$encrypt" == "true" ]]; then
        cmd="$cmd -encryption '$DEFAULT_ENCRYPTION' -stdinpass"
        echo "  Chiffrement : Activé ($DEFAULT_ENCRYPTION)"
    fi
    
    cmd="$cmd '$output_path'"
    
    # Exécuter la création d'image
    local creation_success=false
    
    if [[ "$encrypt" == "true" ]]; then
        echo ""
        echo "🔐 Entrez le mot de passe pour le chiffrement de l'image disque :"
        read -s password
        if echo "$password" | eval "$cmd" >/dev/null 2>&1; then
            creation_success=true
        fi
    else
        if eval "$cmd" >/dev/null 2>&1; then
            creation_success=true
        fi
    fi
    
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))
    
    if [[ "$creation_success" == "true" ]]; then
        local image_size_bytes=$(du -b "$output_path" | cut -f1)
        local image_size_human=$(du -h "$output_path" | cut -f1)
        local compression_ratio=$(echo "scale=2; $image_size_bytes * 100 / $source_size_bytes" | bc)
        
        echo ""
        echo "✅ Image disque créée avec succès"
        echo "  Temps de création : ${duration}s"
        echo "  Taille de l'image : $image_size_human"
        echo "  Ratio de compression : ${compression_ratio}%"
        
        # Vérifier l'image si activé
        if [[ "$ENABLE_VERIFICATION" == "true" ]]; then
            echo ""
            echo "🔍 Vérification de l'intégrité de l'image..."
            if hdiutil verify "$output_path" >/dev/null 2>&1; then
                echo "✅ Vérification d'image réussie"
                log_action "Image créée et vérifiée : $image_name ($image_size_human)"
            else
                echo "❌ Échec de vérification d'image"
                log_action "ERREUR : Échec de vérification d'image : $image_name"
                return 1
            fi
        fi
        
        # Générer les métadonnées de l'image
        create_image_metadata "$output_path" "$source_path" "$description"
        
        return 0
    else
        echo "❌ Échec de création de l'image disque"
        log_action "ERREUR : Échec de création de l'image disque : $image_name"
        return 1
    fi
}

# Créer un fichier de métadonnées pour l'image
create_image_metadata() {
    local image_path="$1"
    local source_path="$2"
    local description="$3"
    
    local metadata_file="${image_path%.dmg}.json"
    
    cat > "$metadata_file" << EOF
{
    "nom_image": "$(basename "$image_path")",
    "date_creation": "$(date -Iseconds)",
    "chemin_source": "$source_path",
    "chemin_image": "$image_path",
    "description": "$description",
    "taille_fichier": $(du -b "$image_path" | cut -f1),
    "taille_fichier_lisible": "$(du -h "$image_path" | cut -f1)",
    "somme_controle_md5": "$(md5 -q "$image_path")",
    "somme_controle_sha256": "$(shasum -a 256 "$image_path" | cut -d' ' -f1)",
    "info_format": $(hdiutil imageinfo "$image_path" -plist | plutil -convert json -o - -)
}
EOF
    
    echo "📄 Métadonnées sauvegardées : $metadata_file"
}

# Générer un rapport d'images complet
generate_image_report() {
    local image_dir="${1:-$BACKUP_DIR}"
    local report_file="$REPORT_DIR/rapport_images_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "📊 Génération du rapport d'images disque..."
    
    {
        echo "Rapport de Gestion d'Images Disque MacFleet"
        echo "Généré : $(date)"
        echo "Répertoire d'Images : $image_dir"
        echo "======================================"
        echo ""
        
        if [[ ! -d "$image_dir" ]]; then
            echo "❌ Répertoire d'images non trouvé : $image_dir"
            return 1
        fi
        
        # Compter et analyser les images
        local total_images=$(find "$image_dir" -name "*.dmg" -type f | wc -l)
        local total_size_bytes=0
        local verified_count=0
        local failed_count=0
        
        echo "=== Résumé ==="
        echo "Total d'images disque : $total_images"
        
        if [[ "$total_images" -eq 0 ]]; then
            echo "Aucune image disque trouvée dans le répertoire"
            return 0
        fi
        
        echo ""
        echo "=== Détails des Images ==="
        printf "%-30s %-10s %-15s %-10s\n" "Nom" "Taille" "Format" "Statut"
        printf "%-30s %-10s %-15s %-10s\n" "----" "------" "------" "------"
        
        find "$image_dir" -name "*.dmg" -type f | sort | while read -r image_path; do
            local image_name=$(basename "$image_path")
            local image_size=$(du -h "$image_path" | cut -f1)
            local image_size_bytes=$(du -b "$image_path" | cut -f1)
            
            # Obtenir les infos de format
            local format_info=$(hdiutil imageinfo "$image_path" 2>/dev/null | grep "Format Description" | cut -d: -f2- | xargs)
            if [[ -z "$format_info" ]]; then
                format_info="Inconnu"
            fi
            
            # Vérifier l'intégrité
            local status="Inconnu"
            if hdiutil verify "$image_path" >/dev/null 2>&1; then
                status="✅ Valide"
                ((verified_count++))
            else
                status="❌ Échouée"
                ((failed_count++))
            fi
            
            printf "%-30s %-10s %-15s %-10s\n" "$image_name" "$image_size" "$format_info" "$status"
            
            total_size_bytes=$((total_size_bytes + image_size_bytes))
        done
        
        echo ""
        echo "=== Statistiques ==="
        echo "Taille totale : $(numfmt --to=iec $total_size_bytes)"
        echo "Images vérifiées : $verified_count"
        echo "Vérification échouée : $failed_count"
        echo "Taille moyenne : $(numfmt --to=iec $((total_size_bytes / total_images)))"
        
        # Recommandations de stockage
        echo ""
        echo "=== Recommandations ==="
        if [[ "$failed_count" -gt 0 ]]; then
            echo "⚠️  $failed_count images ont échoué la vérification - enquêter et recréer"
        fi
        
        if [[ "$total_size_bytes" -gt $((50 * 1024 * 1024 * 1024)) ]]; then  # 50GB
            echo "💡 Considérez archiver les anciennes images pour libérer de l'espace"
        fi
        
        echo "💡 Vérification régulière recommandée pour les images critiques"
        
    } > "$report_file"
    
    echo "📊 Rapport sauvegardé dans : $report_file"
    log_action "Rapport d'images généré : $report_file"
}

# Fonction d'exécution principale
main() {
    local action="${1:-aide}"
    local source="${2:-}"
    local name="${3:-}"
    local output="${4:-$BACKUP_DIR}"
    
    log_action "=== Gestion d'Images Disque MacFleet Démarrée ==="
    
    setup_directories
    
    case "$action" in
        "creer")
            if [[ -n "$source" && -n "$name" ]]; then
                create_enterprise_disk_image "$source" "$name" "$output"
            else
                echo "❌ Utilisation : $0 creer <dossier_source> <nom_image> [repertoire_sortie]"
                echo "Exemple : $0 creer /Users/Shared MonImage /tmp"
            fi
            ;;
        "lot")
            if [[ -n "$source" ]]; then
                batch_create_disk_images "$source" "$output"
            else
                echo "❌ Utilisation : $0 lot <dossier_base> [repertoire_sortie]"
                echo "Exemple : $0 lot /Users/Shared/Projets /tmp/images"
            fi
            ;;
        "verifier")
            if [[ -n "$source" ]]; then
                if [[ -f "$source" ]]; then
                    verify_disk_image "$source"
                elif [[ -d "$source" ]]; then
                    verify_multiple_images "$source"
                else
                    echo "❌ Chemin non trouvé : $source"
                fi
            else
                echo "❌ Utilisation : $0 verifier <fichier_image_ou_repertoire>"
            fi
            ;;
        "rapport")
            generate_image_report "$source"
            ;;
        "info")
            if [[ -n "$source" && -f "$source" ]]; then
                echo "=== Informations de l'Image ==="
                hdiutil imageinfo "$source"
            else
                echo "❌ Utilisation : $0 info <fichier_image>"
            fi
            ;;
        "options")
            show_disk_image_options
            ;;
        "aide"|*)
            echo "Outil de Gestion d'Images Disque MacFleet"
            echo "Utilisation : $0 [action] [options]"
            echo ""
            echo "Actions :"
            echo "  creer <source> <nom> [sortie]    - Créer image disque à partir du dossier"
            echo "  lot <repertoire_base> [sortie]   - Créer images à partir de tous les sous-répertoires"
            echo "  verifier <image_ou_rep>          - Vérifier l'intégrité de l'image"
            echo "  rapport [repertoire_images]      - Générer rapport complet"
            echo "  info <fichier_image>             - Afficher informations détaillées de l'image"
            echo "  options                          - Afficher options de système de fichiers et format disponibles"
            echo "  aide                             - Afficher ce message d'aide"
            echo ""
            echo "Exemples :"
            echo "  $0 creer /Users/Shared MesDonnees  # Créer MesDonnees.dmg à partir de /Users/Shared"
            echo "  $0 lot /Applications /tmp          # Créer images pour toutes les apps"
            echo "  $0 verifier /tmp/MesDonnees.dmg    # Vérifier une seule image"
            echo "  $0 rapport /tmp                    # Générer rapport pour toutes les images dans /tmp"
            echo ""
            echo "Configuration :"
            echo "  Système de fichiers par défaut : $DEFAULT_FILESYSTEM"
            echo "  Format par défaut : $DEFAULT_FORMAT"
            echo "  Chiffrement par défaut : $DEFAULT_ENCRYPTION"
            echo "  Vérification activée : $ENABLE_VERIFICATION"
            ;;
    esac
    
    log_action "=== Gestion d'Images Disque MacFleet Terminée ==="
}

# Exécuter la fonction principale
main "$@"

Comparaison des Formats d'Image

FormatCompressionTailleCompatibilitéCas d'Usage
UDROAucuneGrandeUniverselleTests, images temporaires
UDZOzlib (bonne)MoyennemacOS 10.2+Usage général, bon équilibre
UDBZbzip2 (meilleure)PetitemacOS 10.4+Stockage archive, accès plus lent
ULFOlzfse (rapide)PetitemacOS 10.11+Systèmes modernes, compression rapide
SPARSEAucuneVariablemacOSImages grandissantes, développement

Sécurité et Chiffrement

Création d'Image Chiffrée

# Créer une image disque chiffrée avec politiques d'entreprise
create_secure_image() {
    local source="$1"
    local name="$2"
    local output="$3"
    local encryption_level="${4:-AES-256}"
    
    echo "🔐 Création d'une image disque chiffrée..."
    echo "Chiffrement : $encryption_level"
    
    # Générer un mot de passe sécurisé si non fourni
    if [[ -z "$IMAGE_PASSWORD" ]]; then
        echo "Entrez le mot de passe de chiffrement (ou définissez la variable IMAGE_PASSWORD) :"
        read -s IMAGE_PASSWORD
    fi
    
    echo "$IMAGE_PASSWORD" | hdiutil create \
        -fs HFS+ \
        -format UDBZ \
        -encryption "$encryption_level" \
        -stdinpass \
        -srcfolder "$source" \
        -volname "$name" \
        "$output/$name.dmg"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Image chiffrée créée avec succès"
        echo "🔒 L'image est protégée avec un chiffrement $encryption_level"
    else
        echo "❌ Échec de création de l'image chiffrée"
        return 1
    fi
}

Notes Importantes

  • Espace Disque - Assurez-vous d'avoir suffisamment d'espace pour la création d'image (2x la taille source recommandée)
  • Performance - La compression échange la taille contre la vitesse de création/accès
  • Sécurité - Utilisez le chiffrement AES-256 pour les données sensibles
  • Compatibilité - Choisissez le système de fichiers approprié pour les systèmes cibles
  • Vérification - Vérifiez toujours les images critiques après création
  • Déploiement d'Entreprise - Testez le montage d'image sur les systèmes cibles avant le déploiement en lot

Désactiver les Mises à Jour Automatiques de macOS

Dans les environnements d'entreprise, contrôler quand et comment les mises à jour macOS sont installées est crucial pour maintenir la stabilité du système et assurer la compatibilité avec les applications métier. Ce tutoriel montre comment désactiver les mises à jour automatiques de macOS avec des scripts shell.

Comprendre les Paramètres de Mise à Jour macOS

macOS a deux comportements principaux de mise à jour automatique :

  • Téléchargement Automatique : Télécharge les mises à jour en arrière-plan
  • Vérification Automatique : Vérifie périodiquement les serveurs d'Apple pour de nouvelles mises à jour

Les deux peuvent être contrôlés via le domaine de préférences com.apple.SoftwareUpdate.

Scripts de Base

Désactiver le Téléchargement Automatique

#!/bin/bash
defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -boolean false

Désactiver la Vérification Automatique

#!/bin/bash
defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -boolean false

Script de Déploiement Entreprise

Pour un déploiement à grande échelle dans votre MacFleet :

#!/bin/bash

# Désactiver les Mises à Jour Automatiques macOS - Script Entreprise
# Compatible avec macOS 10.14+

# Fonction pour enregistrer les messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a /var/log/macos_update_config.log
}

# Fonction pour obtenir l'utilisateur actuel
get_current_user() {
    stat -f "%Su" /dev/console
}

# Fonction principale de configuration
configure_updates() {
    local current_user
    current_user=$(get_current_user)
    
    log_message "Début de la configuration des mises à jour macOS pour l'utilisateur : $current_user"
    
    # Désactiver le téléchargement automatique
    if defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -boolean false; then
        log_message "✓ Téléchargement automatique désactivé avec succès"
    else
        log_message "✗ Échec de la désactivation du téléchargement automatique"
        return 1
    fi
    
    # Désactiver la vérification automatique
    if defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -boolean false; then
        log_message "✓ Vérification automatique désactivée avec succès"
    else
        log_message "✗ Échec de la désactivation de la vérification automatique"
        return 1
    fi
    
    # Désactiver l'installation automatique (sécurité supplémentaire)
    if defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -boolean false; then
        log_message "✓ Installation automatique désactivée avec succès"
    else
        log_message "✗ Échec de la désactivation de l'installation automatique"
    fi
    
    # Redémarrer les préférences Software Update pour forcer le rechargement
    killall -HUP cfprefsd 2>/dev/null || true
    
    log_message "Configuration des mises à jour macOS terminée"
    return 0
}

# Fonction de vérification
verify_configuration() {
    local download_status check_status install_status
    
    download_status=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload 2>/dev/null || echo "non défini")
    check_status=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo "non défini")
    install_status=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates 2>/dev/null || echo "non défini")
    
    log_message "Vérification de la configuration :"
    log_message "  Téléchargement Automatique : $download_status"
    log_message "  Vérification Automatique : $check_status"
    log_message "  Installation Automatique : $install_status"
}

# Exécuter la fonction principale
if configure_updates; then
    verify_configuration
    log_message "Script exécuté avec succès"
    exit 0
else
    log_message "Échec de l'exécution du script"
    exit 1
fi

Script de Vérification

Vérifier les paramètres de mise à jour actuels :

#!/bin/bash

echo "=== État des Paramètres de Mise à Jour macOS ==="
echo "Téléchargement Automatique : $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload 2>/dev/null || echo 'Non configuré')"
echo "Vérification Automatique : $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo 'Non configuré')"
echo "Installation Automatique : $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates 2>/dev/null || echo 'Non configuré')"

Réactiver les Mises à Jour

Pour restaurer les mises à jour automatiques :

#!/bin/bash

# Réactiver le téléchargement automatique
defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -boolean true

# Réactiver la vérification automatique
defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -boolean true

# Réactiver l'installation automatique
defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -boolean true

echo "Mises à jour automatiques réactivées"

Dépannage

ProblèmeSolution
Les paramètres reviennent après redémarrageS'assurer que les scripts s'exécutent avec des privilèges admin
Préférences Système affiche les anciennes valeursRedémarrer Préférences Système ou exécuter killall -HUP cfprefsd
Les changements ne s'appliquent pasVérifier /var/log/macos_update_config.log pour les erreurs
Les mises à jour se téléchargent encoreVérifier les permissions du fichier de préférences

Notes Importantes

  • Les utilisateurs avec privilèges admin peuvent changer manuellement ces paramètres
  • L'app Préférences Système/Réglages peut nécessiter un redémarrage pour refléter les changements
  • Considérez l'utilisation de Profils de Configuration pour un contrôle plus strict
  • Testez sur un petit groupe avant le déploiement à l'échelle de l'entreprise

Alternative avec Profil de Configuration

Pour un contrôle plus strict, considérez le déploiement d'un Profil de Configuration :

<key>AutomaticCheckEnabled</key>
<false/>
<key>AutomaticDownload</key>
<false/>
<key>AutomaticallyInstallMacOSUpdates</key>
<false/>

Gestion de Listage de Répertoires et Fichiers sur macOS

Maîtrisez les opérations de listage de fichiers et répertoires sur vos appareils MacFleet en utilisant des outils puissants en ligne de commande. Ce tutoriel couvre le listage de base des fichiers, la découverte de fichiers cachés, l'affichage d'informations détaillées et les techniques de tri avancées pour une gestion efficace du système de fichiers.

Comprendre les Opérations de Répertoires macOS

macOS fournit des outils robustes en ligne de commande pour la gestion des répertoires :

  • ls - Lister le contenu des répertoires avec diverses options
  • find - Rechercher des fichiers et répertoires avec des critères avancés
  • tree - Afficher la structure des répertoires en format arbre
  • stat - Afficher des informations détaillées sur les fichiers/répertoires

Opérations de Base pour Lister les Fichiers

Lister Tous les Fichiers d'un Répertoire

#!/bin/bash

# Listage de répertoire de base
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Fichiers dans $FOLDER_PATH :"
ls "$FOLDER_PATH"

echo "Listage de répertoire terminé avec succès"

Listage Récursif de Répertoire

#!/bin/bash

# Lister tous les fichiers récursivement (y compris les sous-répertoires)
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Listage récursif de $FOLDER_PATH :"
ls -R "$FOLDER_PATH"

echo "Listage récursif de répertoire terminé"

Fichiers et Répertoires Cachés

Afficher le Contenu Caché

#!/bin/bash

# Afficher tous les fichiers y compris les cachés
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Tous les fichiers (y compris cachés) dans $FOLDER_PATH :"
ls -a "$FOLDER_PATH"

echo "Fichiers cachés affichés avec succès"

Analyse des Fichiers Cachés

#!/bin/bash

# Analyse complète des fichiers cachés
analyze_hidden_files() {
    local folder_path="$1"
    
    echo "=== Analyse des Fichiers Cachés pour : $folder_path ==="
    
    # Compter les fichiers cachés
    local hidden_count
    hidden_count=$(ls -la "$folder_path" | grep "^\." | wc -l)
    echo "Fichiers cachés trouvés : $((hidden_count - 2))" # Soustraire . et ..
    
    # Lister les fichiers cachés avec détails
    echo -e "\nFichiers cachés :"
    ls -la "$folder_path" | grep "^\." | grep -v "^total"
    
    # Vérifier les types de fichiers cachés courants
    echo -e "\nTypes de fichiers cachés courants :"
    ls -a "$folder_path" | grep "^\." | grep -E "\.(DS_Store|Spotlight-V100|Trashes|fseventsd)" || echo "Aucun fichier caché système courant trouvé"
}

# Utilisation
analyze_hidden_files "/Users/QA/Desktop/Wallpapers"

Informations Détaillées sur les Fichiers

Listage au Format Long

#!/bin/bash

# Afficher des informations détaillées sur les fichiers
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Informations détaillées sur les fichiers pour $FOLDER_PATH :"
ls -l "$FOLDER_PATH"

echo "Listage détaillé terminé"

Tailles de Fichiers Lisibles par l'Homme

#!/bin/bash

# Afficher les tailles de fichiers dans un format lisible par l'homme
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Fichiers avec tailles lisibles dans $FOLDER_PATH :"
ls -lh "$FOLDER_PATH"

echo "Listage lisible terminé"

Détails Complets des Fichiers

#!/bin/bash

# Affichage avancé d'informations sur les fichiers
show_file_details() {
    local folder_path="$1"
    
    echo "=== Détails Complets des Fichiers : $folder_path ==="
    
    # Listage de base avec permissions, tailles, dates
    echo "Listage détaillé des fichiers :"
    ls -lah "$folder_path"
    
    echo -e "\nRésumé du répertoire :"
    echo "Total d'éléments : $(ls -1 "$folder_path" | wc -l)"
    echo "Taille totale : $(du -sh "$folder_path" | cut -f1)"
    echo "Utilisation disque : $(du -sk "$folder_path" | cut -f1) KB"
    
    # Répartition par type de fichier
    echo -e "\nAnalyse des types de fichiers :"
    find "$folder_path" -maxdepth 1 -type f -exec file {} \; | cut -d: -f2 | sort | uniq -c | sort -nr
}

# Utilisation
show_file_details "/Users/QA/Desktop/Wallpapers"

Options de Tri des Fichiers

Tri par Heure de Modification

#!/bin/bash

# Trier les fichiers par heure de dernière modification (le plus récent en premier)
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Fichiers triés par heure de modification (le plus récent en premier) :"
ls -t "$FOLDER_PATH"

echo "Tri basé sur le temps terminé"

Tri par Taille de Fichier

#!/bin/bash

# Trier les fichiers par taille (le plus grand en premier)
FOLDER_PATH="/Users/QA/Desktop/Wallpapers"

echo "Fichiers triés par taille (le plus grand en premier) :"
ls -lhS "$FOLDER_PATH"

echo "Tri basé sur la taille terminé"

Options de Tri Avancées

#!/bin/bash

# Critères de tri multiples
advanced_sorting() {
    local folder_path="$1"
    
    echo "=== Tri Avancé des Fichiers : $folder_path ==="
    
    echo "1. Par heure de modification (le plus récent en premier) :"
    ls -lt "$folder_path" | head -10
    
    echo -e "\n2. Par heure de modification (le plus ancien en premier) :"
    ls -ltr "$folder_path" | head -10
    
    echo -e "\n3. Par taille (le plus grand en premier) :"
    ls -lhS "$folder_path" | head -10
    
    echo -e "\n4. Par taille (le plus petit en premier) :"
    ls -lhSr "$folder_path" | head -10
    
    echo -e "\n5. Par nom (alphabétique) :"
    ls -l "$folder_path" | sort -k9
    
    echo -e "\n6. Par extension :"
    ls -1 "$folder_path" | grep '\.' | sort -t. -k2
}

# Utilisation
advanced_sorting "/Users/QA/Desktop/Wallpapers"

Système de Gestion de Répertoires d'Entreprise

#!/bin/bash

# Outil de Gestion de Répertoires MacFleet
# Analyse complète des fichiers et répertoires pour les appareils de flotte

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_directory.log"
REPORT_DIR="/etc/macfleet/reports/directory"
CONFIG_DIR="/etc/macfleet/directory"

# Créer les répertoires s'ils n'existent pas
mkdir -p "$REPORT_DIR" "$CONFIG_DIR"

# Catégories de répertoires pour l'analyse
declare -A DIRECTORY_CATEGORIES=(
    ["system"]="/System,/Library,/usr,/bin,/sbin"
    ["user"]="/Users,/home"
    ["applications"]="/Applications,/Applications/Utilities"
    ["documents"]="/Documents,/Desktop,/Downloads"
    ["media"]="/Movies,/Music,/Pictures"
    ["temporary"]="/tmp,/var/tmp,/var/cache"
    ["logs"]="/var/log,/Library/Logs"
    ["configuration"]="/etc,/private/etc,/Library/Preferences"
    ["development"]="/usr/local,/opt,/Developer"
    ["network"]="/Network,/Volumes"
)

# Politiques de répertoires pour différents niveaux de scan
declare -A DIRECTORY_POLICIES=(
    ["quick_scan"]="basic_listing,file_count,size_summary"
    ["standard_scan"]="detailed_listing,hidden_files,type_analysis,permission_check"
    ["comprehensive_scan"]="full_recursive,security_scan,duplicate_detection,metadata_extraction"
    ["security_audit"]="permission_audit,ownership_check,sensitive_file_scan,access_log"
    ["performance_scan"]="large_file_detection,fragmentation_check,cache_analysis"
    ["compliance_scan"]="policy_validation,retention_check,classification_audit"
)

# Fonction de journalisation
log_action() {
    local message="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] $message" | tee -a "$LOG_FILE"
}

# Moteur d'analyse de répertoires
analyze_directory() {
    local target_path="$1"
    local scan_level="${2:-standard_scan}"
    local category="${3:-general}"
    
    log_action "Début de l'analyse de répertoire : $target_path (Niveau : $scan_level, Catégorie : $category)"
    
    if [[ ! -d "$target_path" ]]; then
        log_action "ERREUR : Répertoire non trouvé : $target_path"
        return 1
    fi
    
    local report_file="$REPORT_DIR/directory_analysis_$(echo "$target_path" | tr '/' '_')_$(date +%Y%m%d_%H%M%S).json"
    
    # Initialiser le rapport
    cat > "$report_file" << EOF
{
    "analysis_info": {
        "target_path": "$target_path",
        "scan_level": "$scan_level",
        "category": "$category",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION"
    },
    "directory_metrics": {},
    "file_analysis": {},
    "security_findings": {},
    "recommendations": []
}
EOF
    
    # Métriques de base du répertoire
    local total_items=$(find "$target_path" -maxdepth 1 2>/dev/null | wc -l)
    local total_files=$(find "$target_path" -maxdepth 1 -type f 2>/dev/null | wc -l)
    local total_dirs=$(find "$target_path" -maxdepth 1 -type d 2>/dev/null | wc -l)
    local total_size=$(du -sk "$target_path" 2>/dev/null | cut -f1)
    
    # Mettre à jour le rapport avec les métriques
    jq --argjson total_items "$((total_items - 1))" \
       --argjson total_files "$total_files" \
       --argjson total_dirs "$((total_dirs - 1))" \
       --argjson total_size_kb "$total_size" \
       '.directory_metrics = {
           "total_items": $total_items,
           "total_files": $total_files,
           "total_directories": $total_dirs,
           "total_size_kb": $total_size_kb,
           "average_file_size": (if $total_files > 0 then ($total_size_kb / $total_files) else 0 end)
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    
    # Effectuer l'analyse selon le niveau de scan
    case "$scan_level" in
        "quick_scan")
            perform_quick_scan "$target_path" "$report_file"
            ;;
        "standard_scan")
            perform_standard_scan "$target_path" "$report_file"
            ;;
        "comprehensive_scan")
            perform_comprehensive_scan "$target_path" "$report_file"
            ;;
        "security_audit")
            perform_security_audit "$target_path" "$report_file"
            ;;
        "performance_scan")
            perform_performance_scan "$target_path" "$report_file"
            ;;
        "compliance_scan")
            perform_compliance_scan "$target_path" "$report_file"
            ;;
    esac
    
    log_action "Analyse de répertoire terminée : $report_file"
    echo "$report_file"
}

# Implémentation de scan rapide
perform_quick_scan() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Exécution d'un scan rapide de $target_path..."
    
    # Listage de fichiers de base
    local file_listing=$(ls -la "$target_path" 2>/dev/null | tail -n +2)
    
    # Distribution des types de fichiers
    local file_types=$(find "$target_path" -maxdepth 1 -type f -exec file {} \; 2>/dev/null | cut -d: -f2 | sort | uniq -c | sort -nr)
    
    # Mettre à jour le rapport
    jq --arg file_listing "$file_listing" \
       --arg file_types "$file_types" \
       '.file_analysis.quick_scan = {
           "file_listing": $file_listing,
           "file_type_distribution": $file_types
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Implémentation de scan standard
perform_standard_scan() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Exécution d'un scan standard de $target_path..."
    
    # Analyse détaillée des fichiers
    local detailed_listing=$(ls -lah "$target_path" 2>/dev/null)
    local hidden_files=$(ls -la "$target_path" 2>/dev/null | grep "^\." | wc -l)
    local executable_files=$(find "$target_path" -maxdepth 1 -type f -executable 2>/dev/null | wc -l)
    
    # Analyse de taille des fichiers
    local large_files=$(find "$target_path" -maxdepth 1 -type f -size +10M 2>/dev/null)
    local small_files=$(find "$target_path" -maxdepth 1 -type f -size -1k 2>/dev/null | wc -l)
    
    # Analyse de l'âge des fichiers
    local recent_files=$(find "$target_path" -maxdepth 1 -type f -mtime -7 2>/dev/null | wc -l)
    local old_files=$(find "$target_path" -maxdepth 1 -type f -mtime +365 2>/dev/null | wc -l)
    
    # Mettre à jour le rapport
    jq --arg detailed_listing "$detailed_listing" \
       --argjson hidden_files "$((hidden_files - 2))" \
       --argjson executable_files "$executable_files" \
       --arg large_files "$large_files" \
       --argjson small_files "$small_files" \
       --argjson recent_files "$recent_files" \
       --argjson old_files "$old_files" \
       '.file_analysis.standard_scan = {
           "detailed_listing": $detailed_listing,
           "hidden_files_count": $hidden_files,
           "executable_files_count": $executable_files,
           "large_files": $large_files,
           "small_files_count": $small_files,
           "recent_files_count": $recent_files,
           "old_files_count": $old_files
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Implémentation de scan complet
perform_comprehensive_scan() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Exécution d'un scan complet de $target_path..."
    
    # Analyse récursive
    local total_recursive_items=$(find "$target_path" 2>/dev/null | wc -l)
    local max_depth=$(find "$target_path" -type d 2>/dev/null | awk -F/ '{print NF}' | sort -n | tail -1)
    
    # Analyse des extensions de fichiers
    local extensions=$(find "$target_path" -type f 2>/dev/null | grep '\.' | rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr)
    
    # Détection de fichiers dupliqués
    local duplicates=$(find "$target_path" -type f 2>/dev/null -exec md5 {} \; | sort | uniq -d -w 32)
    
    # Analyse des liens symboliques
    local symlinks=$(find "$target_path" -type l 2>/dev/null)
    
    # Mettre à jour le rapport
    jq --argjson total_recursive "$((total_recursive_items - 1))" \
       --argjson max_depth "$((max_depth - $(echo "$target_path" | tr -cd '/' | wc -c) - 1))" \
       --arg extensions "$extensions" \
       --arg duplicates "$duplicates" \
       --arg symlinks "$symlinks" \
       '.file_analysis.comprehensive_scan = {
           "total_recursive_items": $total_recursive,
           "maximum_depth": $max_depth,
           "file_extensions": $extensions,
           "duplicate_files": $duplicates,
           "symbolic_links": $symlinks
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Fonction d'exécution principale
main() {
    local action="${1:-analyze}"
    local target="${2:-/Users}"
    local scan_level="${3:-standard_scan}"
    
    log_action "=== Gestion de Répertoires MacFleet Démarrée ==="
    log_action "Action : $action, Cible : $target, Niveau de Scan : $scan_level"
    
    case "$action" in
        "analyze")
            analyze_directory "$target" "$scan_level"
            ;;
        "fleet-scan")
            manage_fleet_directories "scan_all" "" "$scan_level"
            ;;
        "category-scan")
            manage_fleet_directories "scan_category" "$target" "$scan_level"
            ;;
        "fleet-report")
            manage_fleet_directories "generate_report"
            ;;
        "help")
            echo "Usage : $0 [action] [cible] [niveau_scan]"
            echo "Actions : analyze, fleet-scan, category-scan, fleet-report, help"
            echo "Niveaux de Scan : quick_scan, standard_scan, comprehensive_scan, security_audit, performance_scan, compliance_scan"
            echo "Catégories : ${!DIRECTORY_CATEGORIES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion de répertoires terminée ==="
}

# Exécuter la fonction principale
main "$@"

Meilleures Pratiques de Listage de Répertoires

Gérer les Espaces dans les Noms de Fichiers

# Gestion sécurisée des noms de fichiers avec espaces
while IFS= read -r -d '' file; do
    echo "Traitement : $file"
    # Votre logique de traitement ici
done < <(find "/chemin/avec espaces" -type f -print0)

Filtrer par Types de Fichiers

# Lister seulement les fichiers images
ls -la /Users/QA/Desktop/Wallpapers/*.{jpg,jpeg,png,gif,bmp} 2>/dev/null

# Lister seulement les fichiers texte
find /chemin/vers/répertoire -name "*.txt" -o -name "*.md" -o -name "*.doc"

Considérations de Performance

# Pour les gros répertoires, utiliser find avec profondeur limitée
find /gros/répertoire -maxdepth 2 -type f | head -100

# Utiliser xargs pour traiter beaucoup de fichiers
find /répertoire -name "*.log" | xargs wc -l

Opérations Courantes de Répertoires

Analyse de Taille de Répertoires

#!/bin/bash

# Analyser les tailles de répertoires
analyze_directory_sizes() {
    local base_path="$1"
    
    echo "Analyse de taille de répertoire pour : $base_path"
    echo "=============================================="
    
    # Top 10 des plus gros sous-répertoires
    du -h "$base_path"/* 2>/dev/null | sort -hr | head -10
    
    echo -e "\nTaille totale du répertoire :"
    du -sh "$base_path"
}

analyze_directory_sizes "/Users"

Comptage de Fichiers par Type

#!/bin/bash

# Compter les fichiers par extension
count_files_by_type() {
    local directory="$1"
    
    echo "Distribution des types de fichiers dans : $directory"
    find "$directory" -type f | grep '\.' | rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr
}

count_files_by_type "/Users/QA/Desktop/Wallpapers"

Notes Importantes

  • Utilisez des guillemets autour des chemins contenant des espaces : ls "/chemin avec espaces"
  • Échappez les caractères spéciaux avec une barre oblique inverse quand vous n'utilisez pas de guillemets
  • Vérifiez les permissions avant d'accéder aux répertoires système
  • Testez les scripts sur des répertoires d'exemple avant utilisation en production
  • Surveillez les performances lors de l'analyse de grandes structures de répertoires
  • Considérez la sécurité lors du listage de répertoires sensibles dans les journaux

Gestion d'Identité et Nomenclature d'Appareils Entreprise sur macOS

Implémentez une gestion d'identité et de nomenclature d'appareils de niveau entreprise sur votre déploiement MacFleet avec des conventions de nomenclature standardisées, un provisioning automatisé et une validation d'identité complète. Ce tutoriel fournit des solutions pour maintenir une identification cohérente des appareils et une présence réseau.

Comprendre l'Identité des Appareils macOS

Les appareils macOS ont trois composants de nomenclature distincts qui affectent l'identification et le comportement réseau :

  • Nom d'Ordinateur - Nom convivial affiché dans les préférences Partage et Finder
  • Nom d'Hôte Local - Identifiant réseau avec suffixe ".local" pour Bonjour/mDNS
  • Nom d'Hôte - Nom d'hôte réseau principal utilisé dans terminal et services réseau
  • Nom NetBIOS - Identifiant de compatibilité réseau Windows

Opérations de Nomenclature d'Appareils de Base

Changer le Nom d'Ordinateur

#!/bin/bash

# Définir le nom d'ordinateur
scutil --set ComputerName "$ComputerName"

echo "Nom d'ordinateur défini à : $ComputerName"

Changer le Nom d'Hôte Local

#!/bin/bash

# Définir le nom d'hôte local pour la découverte Bonjour/mDNS
scutil --set LocalHostName "$LocalHostName"

echo "Nom d'hôte local défini à : $LocalHostName"

Changer le Nom d'Hôte

#!/bin/bash

# Définir le nom d'hôte principal pour les services réseau
# Exemple : Votre-iMac.domaine.com
scutil --set HostName "$HostName"

echo "Nom d'hôte défini à : $HostName"

Vider le Cache DNS

#!/bin/bash

# Vider le cache DNS après les changements de nom
sudo dscacheutil --flushcache

echo "Cache DNS vidé avec succès"

Normes de Nomenclature d'Entreprise

Script de Convention de Nomenclature Standardisée

#!/bin/bash

# Outil de Nomenclature d'Appareils Entreprise MacFleet
# Implémente des conventions de nomenclature standardisées dans la flotte

# Configuration
CONFIG_FILE="/etc/macfleet/naming_policy.conf"
LOG_FILE="/var/log/macfleet_naming.log"
REPORT_DIR="/var/log/macfleet_reports"

# Créer les répertoires
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$REPORT_DIR"

# Politique de nomenclature par défaut
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Politique de Nomenclature d'Appareils MacFleet
# Version : 2.0

# Format de Convention de Nomenclature
# Modèle : {PREFIXE}-{LOCALISATION}-{TYPE}-{SEQUENCE}
# Exemple : MF-PAR-MBP-001

# Paramètres d'Organisation
ORG_PREFIX="MF"
DOMAIN_SUFFIX="macfleet.local"
ENABLE_AUTO_NAMING=true
VALIDATE_NAMES=true

# Codes de Localisation
LOCATION_CODES="PAR,LYO,MRS,LIL,STR,NAN,BOR,TOU"
DEFAULT_LOCATION="PAR"

# Mapping des Types d'Appareils
# Format : IDENTIFIANT_MODELE:CODE_COURT
DEVICE_TYPES=(
    "MacBookPro:MBP"
    "MacBookAir:MBA"
    "iMac:iMac"
    "iMacPro:iMP"
    "MacPro:MP"
    "Macmini:MM"
    "MacStudio:MS"
)

# Paramètres Réseau
ENABLE_NETBIOS=true
SYNC_ALL_NAMES=true
FLUSH_DNS_AFTER_CHANGE=true
EOF

# Charger la configuration
source "$CONFIG_FILE" 2>/dev/null || true

# Fonction de journalisation
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Obtenir les informations du modèle d'appareil
get_device_model() {
    local model_identifier
    model_identifier=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)
    
    # Mapper le modèle au type d'appareil
    for mapping in "${DEVICE_TYPES[@]}"; do
        local model_pattern="${mapping%:*}"
        local type_code="${mapping#*:}"
        
        if [[ "$model_identifier" == *"$model_pattern"* ]]; then
            echo "$type_code"
            return 0
        fi
    done
    
    # Fallback par défaut
    echo "MAC"
}

# Obtenir le code de localisation depuis la saisie utilisateur ou configuration
get_location_code() {
    local location="$1"
    
    if [[ -z "$location" ]]; then
        location="$DEFAULT_LOCATION"
    fi
    
    # Valider le code de localisation
    if [[ ",$LOCATION_CODES," == *",$location,"* ]]; then
        echo "$location"
    else
        echo "$DEFAULT_LOCATION"
        log_action "AVERTISSEMENT : Localisation invalide '$location', utilisation par défaut '$DEFAULT_LOCATION'"
    fi
}

# Générer un numéro de séquence
generate_sequence() {
    local prefix="$1"
    local sequence_file="/var/lib/macfleet/sequences/${prefix}.seq"
    
    mkdir -p "$(dirname "$sequence_file")"
    
    if [[ -f "$sequence_file" ]]; then
        local current_seq
        current_seq=$(cat "$sequence_file")
        ((current_seq++))
    else
        current_seq=1
    fi
    
    printf "%03d" "$current_seq" > "$sequence_file"
    printf "%03d" "$current_seq"
}

# Générer un nom d'appareil standardisé
generate_device_name() {
    local location="$1"
    local custom_suffix="$2"
    
    local device_type
    device_type=$(get_device_model)
    
    local location_code
    location_code=$(get_location_code "$location")
    
    local base_prefix="${ORG_PREFIX}-${location_code}-${device_type}"
    
    if [[ -n "$custom_suffix" ]]; then
        echo "${base_prefix}-${custom_suffix}"
    else
        local sequence
        sequence=$(generate_sequence "$base_prefix")
        echo "${base_prefix}-${sequence}"
    fi
}

# Valider la conformité de nomenclature
validate_device_name() {
    local name="$1"
    local errors=()
    
    # Validation de longueur
    if [[ ${#name} -gt 15 ]]; then
        errors+=("Nom trop long (max 15 caractères pour compatibilité NetBIOS)")
    fi
    
    # Validation de caractères
    if [[ "$name" =~ [^A-Za-z0-9\-] ]]; then
        errors+=("Caractères invalides (seuls alphanumériques et tirets autorisés)")
    fi
    
    # Validation de format
    if [[ ! "$name" =~ ^[A-Z]{2,4}-[A-Z]{2,4}-[A-Z]{2,4}-[0-9]{3}$ ]] && [[ "$VALIDATE_NAMES" == "true" ]]; then
        errors+=("Le nom ne correspond pas au format standard de l'organisation")
    fi
    
    if [[ ${#errors[@]} -eq 0 ]]; then
        return 0
    else
        printf '%s\n' "${errors[@]}"
        return 1
    fi
}

# Appliquer les noms d'appareils avec validation
apply_device_names() {
    local computer_name="$1"
    local hostname="$2"
    local local_hostname="$3"
    
    echo "=== Application des Noms d'Appareils ==="
    
    # Valider tous les noms
    local validation_errors=0
    
    if ! validate_device_name "$computer_name"; then
        echo "❌ Validation du nom d'ordinateur échouée"
        ((validation_errors++))
    fi
    
    if [[ -n "$hostname" ]] && ! validate_device_name "${hostname%%.*}"; then
        echo "❌ Validation du nom d'hôte échouée"
        ((validation_errors++))
    fi
    
    if [[ -n "$local_hostname" ]] && ! validate_device_name "$local_hostname"; then
        echo "❌ Validation du nom d'hôte local échouée"
        ((validation_errors++))
    fi
    
    if [[ $validation_errors -gt 0 ]] && [[ "$VALIDATE_NAMES" == "true" ]]; then
        echo "⚠️  Validation des noms échouée, abandon des changements"
        return 1
    fi
    
    # Appliquer le nom d'ordinateur
    if [[ -n "$computer_name" ]]; then
        scutil --set ComputerName "$computer_name"
        echo "✅ Nom d'ordinateur : $computer_name"
        log_action "Nom d'ordinateur changé en : $computer_name"
    fi
    
    # Appliquer le nom d'hôte
    if [[ -n "$hostname" ]]; then
        scutil --set HostName "$hostname"
        echo "✅ Nom d'hôte : $hostname"
        log_action "Nom d'hôte changé en : $hostname"
    fi
    
    # Appliquer le nom d'hôte local
    if [[ -n "$local_hostname" ]]; then
        scutil --set LocalHostName "$local_hostname"
        echo "✅ Nom d'hôte local : $local_hostname"
        log_action "Nom d'hôte local changé en : $local_hostname"
    fi
    
    # Appliquer le nom NetBIOS si activé
    if [[ "$ENABLE_NETBIOS" == "true" ]] && [[ -n "$computer_name" ]]; then
        defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$computer_name"
        echo "✅ Nom NetBIOS : $computer_name"
        log_action "Nom NetBIOS changé en : $computer_name"
    fi
    
    # Vider le cache DNS
    if [[ "$FLUSH_DNS_AFTER_CHANGE" == "true" ]]; then
        sudo dscacheutil --flushcache
        echo "✅ Cache DNS vidé"
        log_action "Cache DNS vidé après changements de noms"
    fi
    
    return 0
}

# Auto-génération et application des noms
auto_provision_device() {
    local location="$1"
    local custom_suffix="$2"
    
    echo "=== Provisioning Automatique des Noms d'Appareils ==="
    
    if [[ "$ENABLE_AUTO_NAMING" != "true" ]]; then
        echo "❌ Nomenclature automatique désactivée dans la politique"
        return 1
    fi
    
    # Générer le nom de base
    local base_name
    base_name=$(generate_device_name "$location" "$custom_suffix")
    
    # Créer toutes les variantes de nomenclature
    local computer_name="$base_name"
    local local_hostname="$base_name"
    local hostname="${base_name}.${DOMAIN_SUFFIX}"
    
    echo "Noms générés :"
    echo "  Nom d'Ordinateur : $computer_name"
    echo "  Nom d'Hôte Local : $local_hostname"
    echo "  Nom d'Hôte : $hostname"
    echo ""
    
    # Appliquer les noms
    apply_device_names "$computer_name" "$hostname" "$local_hostname"
}

# Obtenir l'identité actuelle de l'appareil
get_current_identity() {
    echo "=== Identité Actuelle de l'Appareil ==="
    
    local computer_name
    computer_name=$(scutil --get ComputerName 2>/dev/null || echo "Non Défini")
    
    local hostname
    hostname=$(scutil --get HostName 2>/dev/null || echo "Non Défini")
    
    local local_hostname
    local_hostname=$(scutil --get LocalHostName 2>/dev/null || echo "Non Défini")
    
    local netbios_name
    netbios_name=$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName 2>/dev/null || echo "Non Défini")
    
    echo "Nom d'Ordinateur : $computer_name"
    echo "Nom d'Hôte : $hostname"
    echo "Nom d'Hôte Local : $local_hostname"
    echo "Nom NetBIOS : $netbios_name"
    echo "Numéro de Série : $(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
    echo "Modèle : $(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)"
}

# Générer un rapport de conformité
generate_naming_report() {
    local report_file="$REPORT_DIR/device_naming_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Génération du Rapport de Conformité de Nomenclature ==="
    
    local computer_name hostname local_hostname netbios_name
    computer_name=$(scutil --get ComputerName 2>/dev/null || echo "")
    hostname=$(scutil --get HostName 2>/dev/null || echo "")
    local_hostname=$(scutil --get LocalHostName 2>/dev/null || echo "")
    netbios_name=$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName 2>/dev/null || echo "")
    
    # Vérifier la conformité
    local computer_compliant="false"
    local hostname_compliant="false"
    local naming_compliant="false"
    
    if validate_device_name "$computer_name" >/dev/null 2>&1; then
        computer_compliant="true"
    fi
    
    if [[ -n "$hostname" ]] && validate_device_name "${hostname%%.*}" >/dev/null 2>&1; then
        hostname_compliant="true"
    fi
    
    if [[ "$computer_compliant" == "true" ]] && [[ "$hostname_compliant" == "true" ]]; then
        naming_compliant="true"
    fi
    
    # Créer le rapport JSON
    cat > "$report_file" << EOF
{
  "type_rapport": "conformite_nomenclature_appareil",
  "horodatage": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "infos_appareil": {
    "nom_hote": "$(hostname)",
    "numero_serie": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "identifiant_modele": "$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)",
    "version_macos": "$(sw_vers -productVersion)"
  },
  "noms_actuels": {
    "nom_ordinateur": "$computer_name",
    "nom_hote": "$hostname",
    "nom_hote_local": "$local_hostname",
    "nom_netbios": "$netbios_name"
  },
  "conformite": {
    "nom_ordinateur_conforme": $computer_compliant,
    "nom_hote_conforme": $hostname_compliant,
    "conformite_globale": $naming_compliant,
    "version_politique": "2.0"
  },
  "parametres_politique": {
    "prefixe_org": "$ORG_PREFIX",
    "suffixe_domaine": "$DOMAIN_SUFFIX",
    "nomenclature_auto_activee": $ENABLE_AUTO_NAMING,
    "validation_activee": $VALIDATE_NAMES
  }
}
EOF
    
    echo "Rapport de nomenclature sauvegardé dans : $report_file"
    log_action "Rapport de nomenclature d'appareil généré : $report_file"
}

# Fonction principale avec gestion d'arguments
main() {
    log_action "=== Outil de Nomenclature d'Appareils MacFleet Démarré ==="
    
    case "${1:-status}" in
        "auto-provision")
            auto_provision_device "$2" "$3"
            ;;
        "set-names")
            apply_device_names "$2" "$3" "$4"
            ;;
        "validate")
            get_current_identity
            echo ""
            if validate_device_name "$2" 2>/dev/null; then
                echo "✅ Le nom '$2' est conforme"
            else
                echo "❌ Validation du nom '$2' échouée :"
                validate_device_name "$2"
            fi
            ;;
        "report")
            generate_naming_report
            ;;
        "status"|*)
            get_current_identity
            ;;
    esac
    
    log_action "=== Opération de nomenclature d'appareil terminée ==="
}

# Exécuter la fonction principale
main "$@"

Gestion d'Identité Avancée

Synchronisation d'Identité Réseau

#!/bin/bash

# Synchroniser tous les composants de nomenclature pour la cohérence
sync_network_identity() {
    echo "=== Synchronisation d'Identité Réseau ==="
    
    # Obtenir le nom d'ordinateur actuel comme source
    local source_name
    source_name=$(scutil --get ComputerName 2>/dev/null)
    
    if [[ -z "$source_name" ]]; then
        echo "❌ Aucun nom d'ordinateur défini, impossible de synchroniser"
        return 1
    fi
    
    # Générer des noms cohérents
    local clean_name
    clean_name=$(echo "$source_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
    
    local local_hostname="$clean_name"
    local hostname="${clean_name}.local"
    
    echo "Synchronisation de l'identité depuis : $source_name"
    echo "Nom d'Hôte Local : $local_hostname"
    echo "Nom d'Hôte : $hostname"
    
    # Appliquer les noms synchronisés
    scutil --set LocalHostName "$local_hostname"
    scutil --set HostName "$hostname"
    
    # Mettre à jour NetBIOS
    defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$source_name"
    
    # Vider le cache DNS
    sudo dscacheutil --flushcache
    
    echo "✅ Identité réseau synchronisée"
}

sync_network_identity

Provisioning d'Appareils en Masse

#!/bin/bash

# Nomenclature d'appareils en masse pour déploiement de flotte
bulk_provision_devices() {
    local csv_file="$1"
    local report_file="/tmp/bulk_naming_$(date +%Y%m%d_%H%M%S).csv"
    
    echo "=== Provisioning d'Appareils en Masse ==="
    echo "Serie,Nom_Ordinateur,Nom_Hote,Statut,Horodatage" > "$report_file"
    
    # Lire le fichier CSV avec les affectations d'appareils
    # Format : Serie,Localisation,SuffixePersonnalise
    while IFS=',' read -r serial location suffix; do
        # Ignorer l'en-tête
        [[ "$serial" == "Serie" ]] && continue
        
        local current_serial
        current_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)
        
        if [[ "$current_serial" == "$serial" ]]; then
            echo "Traitement de l'appareil : $serial"
            
            # Générer les noms pour cet appareil
            local device_name
            device_name=$(generate_device_name "$location" "$suffix")
            
            local computer_name="$device_name"
            local hostname="${device_name}.macfleet.local"
            
            # Appliquer les noms
            if apply_device_names "$computer_name" "$hostname" "$device_name"; then
                echo "$serial,$computer_name,$hostname,SUCCES,$(date)" >> "$report_file"
                echo "✅ Provisionné avec succès : $computer_name"
            else
                echo "$serial,$computer_name,$hostname,ECHEC,$(date)" >> "$report_file"
                echo "❌ Échec du provisioning : $computer_name"
            fi
            
            break
        fi
    done < "$csv_file"
    
    echo "Rapport de provisioning en masse : $report_file"
}

# Exemple d'utilisation :
# bulk_provision_devices "/chemin/vers/affectations_appareils.csv"

Validation d'Identité et Conformité

Script de Validation Complète

#!/bin/bash

# Validation complète de l'identité d'appareil
validate_device_identity() {
    echo "=== Validation de l'Identité d'Appareil ==="
    
    local issues=0
    local warnings=0
    
    # Obtenir tous les noms actuels
    local computer_name hostname local_hostname
    computer_name=$(scutil --get ComputerName 2>/dev/null)
    hostname=$(scutil --get HostName 2>/dev/null)
    local_hostname=$(scutil --get LocalHostName 2>/dev/null)
    
    # Validation du nom d'ordinateur
    if [[ -z "$computer_name" ]]; then
        echo "❌ Nom d'ordinateur non défini"
        ((issues++))
    elif ! validate_device_name "$computer_name" >/dev/null 2>&1; then
        echo "⚠️  Format de nom d'ordinateur non conforme : $computer_name"
        ((warnings++))
    else
        echo "✅ Nom d'ordinateur conforme : $computer_name"
    fi
    
    # Validation du nom d'hôte
    if [[ -z "$hostname" ]]; then
        echo "⚠️  Nom d'hôte non défini"
        ((warnings++))
    elif ! validate_device_name "${hostname%%.*}" >/dev/null 2>&1; then
        echo "⚠️  Format de nom d'hôte non conforme : $hostname"
        ((warnings++))
    else
        echo "✅ Nom d'hôte conforme : $hostname"
    fi
    
    # Validation du nom d'hôte local
    if [[ -z "$local_hostname" ]]; then
        echo "⚠️  Nom d'hôte local non défini"
        ((warnings++))
    elif ! validate_device_name "$local_hostname" >/dev/null 2>&1; then
        echo "⚠️  Format de nom d'hôte local non conforme : $local_hostname"
        ((warnings++))
    else
        echo "✅ Nom d'hôte local conforme : $local_hostname"
    fi
    
    # Vérification de cohérence
    if [[ -n "$computer_name" && -n "$local_hostname" ]]; then
        local expected_local
        expected_local=$(echo "$computer_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
        
        if [[ "$local_hostname" != "$expected_local" ]]; then
            echo "⚠️  Noms non synchronisés (Ordinateur : $computer_name, Local : $local_hostname)"
            ((warnings++))
        fi
    fi
    
    # Validation de connectivité réseau
    echo ""
    echo "=== Test d'Identité Réseau ==="
    
    # Tester la résolution Bonjour
    if ping -c 1 "${local_hostname}.local" >/dev/null 2>&1; then
        echo "✅ Résolution Bonjour fonctionnelle"
    else
        echo "⚠️  Résolution Bonjour échouée"
        ((warnings++))
    fi
    
    # Tester la résolution du nom d'hôte
    if [[ -n "$hostname" ]] && ping -c 1 "$hostname" >/dev/null 2>&1; then
        echo "✅ Résolution de nom d'hôte fonctionnelle"
    elif [[ -n "$hostname" ]]; then
        echo "⚠️  Résolution de nom d'hôte échouée"
        ((warnings++))
    fi
    
    # Résumé
    echo ""
    echo "=== Résumé de Validation ==="
    echo "Problèmes : $issues"
    echo "Avertissements : $warnings"
    
    if [[ $issues -eq 0 && $warnings -eq 0 ]]; then
        echo "✅ Identité d'appareil entièrement conforme"
        return 0
    elif [[ $issues -eq 0 ]]; then
        echo "⚠️  Identité d'appareil a des avertissements mais est fonctionnelle"
        return 1
    else
        echo "❌ Identité d'appareil a des problèmes critiques"
        return 2
    fi
}

validate_device_identity

Intégration des Services Réseau

DNS et Services d'Annuaire

#!/bin/bash

# Mettre à jour les entrées DNS et services d'annuaire
update_network_services() {
    echo "=== Mise à Jour des Services Réseau ==="
    
    # Obtenir les noms actuels
    local computer_name hostname
    computer_name=$(scutil --get ComputerName 2>/dev/null)
    hostname=$(scutil --get HostName 2>/dev/null)
    
    # Mettre à jour mDNSResponder
    echo "Redémarrage de mDNSResponder..."
    sudo launchctl kickstart -k system/com.apple.mDNSResponder
    
    # Mettre à jour l'enregistrement NetBIOS
    if [[ -n "$computer_name" ]]; then
        echo "Mise à jour de l'enregistrement NetBIOS..."
        defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$computer_name"
        sudo launchctl kickstart -k system/com.apple.smbd
    fi
    
    # Vider tous les caches
    echo "Vidage des caches système..."
    sudo dscacheutil --flushcache
    sudo killall -HUP mDNSResponder
    
    # Mettre à jour Open Directory si lié
    if dsconfigldap -v >/dev/null 2>&1; then
        echo "Mise à jour de l'enregistrement Open Directory..."
        sudo dsconfigldap -f
    fi
    
    echo "✅ Services réseau mis à jour"
}

update_network_services

Notes de Configuration Importantes

Utilitaire de Configuration Système (scutil)

La commande scutil gère la configuration système macOS :

  • ComputerName - Nom d'appareil visible par l'utilisateur
  • HostName - Nom d'hôte réseau principal
  • LocalHostName - Identifiant Bonjour/mDNS
  • NetBIOSName - Compatibilité réseau Windows

Bonnes Pratiques pour l'Entreprise

  1. Convention de Nomenclature Standardisée

    • Utiliser un format cohérent : ORG-LOCALISATION-TYPE-SEQUENCE
    • Garder les noms sous 15 caractères pour compatibilité NetBIOS
    • Éviter les caractères spéciaux et espaces
  2. Considérations Réseau

    • Assurer des noms uniques dans les segments réseau
    • Tester la résolution DNS après changements
    • Coordonner avec les administrateurs réseau
  3. Gestion de Flotte

    • Implémenter un provisioning automatisé
    • Maintenir des bases de données de nomenclature
    • Audit de conformité régulier
    • Sauvegarder la configuration avant changements
  4. Implications de Sécurité

    • Les noms d'appareils peuvent révéler la structure organisationnelle
    • Considérer les exigences de confidentialité
    • Implémenter des contrôles d'accès pour les changements de nomenclature

Dépannage des Problèmes Courants

  • Changements de noms non effectifs - Redémarrer les services réseau ou redémarrer
  • Conflits Bonjour - Assurer des valeurs LocalHostName uniques
  • Problèmes de résolution DNS - Vider le cache et redémarrer mDNSResponder
  • Problèmes réseau Windows - Vérifier la configuration du nom NetBIOS

N'oubliez pas de tester les changements de nomenclature de manière approfondie et de coordonner avec les administrateurs réseau avant l'implémentation dans votre déploiement MacFleet.