Guide

Nouvelles mises à jour et améliorations de Macfleet.

Gestion des Préférences Système sur macOS

Gérez et contrôlez l'accès aux Préférences Système sur vos appareils MacFleet avec une gestion complète des panneaux de préférences, des contrôles de restriction utilisateur et des solutions de configuration d'entreprise. Ce tutoriel couvre le masquage, la désactivation et le contrôle des Préférences Système pour une sécurité et conformité renforcées.

Comprendre la Gestion des Préférences Système

Les Préférences Système sur macOS fournissent l'accès aux paramètres de configuration système :

  • Panneaux de Préférences - Modules de configuration individuels (Réseau, Sécurité, Utilisateurs, etc.)
  • Identifiants de Bundle - Identifiants uniques pour chaque panneau de préférences
  • Masqué vs Désactivé - Différents niveaux de restriction d'accès
  • Contrôle d'Entreprise - Gestion centralisée de l'accès utilisateur aux paramètres système

Cas d'Usage d'Entreprise

La gestion des Préférences Système bénéficie aux environnements d'entreprise :

  • Durcissement de Sécurité - Empêcher les modifications de configuration non autorisées
  • Conformité - Assurer que les appareils respectent les exigences réglementaires
  • Expérience Utilisateur - Simplifier les interfaces en masquant les options non pertinentes
  • Contrôle Administratif - Centraliser la gestion de configuration
  • Protection des Données - Restreindre l'accès aux paramètres système sensibles

Contrôle de Base des Préférences Système

Masquer le Panneau Profils

#!/bin/bash

# Masquer le panneau Profils des Préférences Système
hide_profiles_pane() {
    echo "=== Masquage du Panneau Profils ==="
    
    # Vérifier la version macOS (le masquage nécessite macOS 13.0+)
    local macos_version=$(sw_vers -productVersion | cut -d. -f1)
    if [[ $macos_version -lt 13 ]]; then
        echo "Avertissement : Le masquage des panneaux nécessite macOS 13.0 ou ultérieur"
        echo "Version actuelle : $(sw_vers -productVersion)"
        echo "Utilisation de la désactivation au lieu du masquage..."
        disable_profiles_pane
        return
    fi
    
    # Masquer le panneau Profils
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        HiddenPreferencePanes -array "com.apple.preferences.configurationprofiles"
    
    if [[ $? -eq 0 ]]; then
        echo "✓ Panneau Profils masqué avec succès"
        echo "Les utilisateurs ne verront plus le panneau Profils dans les Préférences Système"
    else
        echo "✗ Échec du masquage du panneau Profils"
        return 1
    fi
}

# Désactiver le panneau Profils (alternative pour macOS plus ancien)
disable_profiles_pane() {
    echo "=== Désactivation du Panneau Profils ==="
    
    # Désactiver le panneau Profils (fonctionne sur macOS 10.2+)
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "com.apple.preferences.configurationprofiles"
    
    if [[ $? -eq 0 ]]; then
        echo "✓ Panneau Profils désactivé avec succès"
        echo "Le panneau Profils apparaîtra grisé dans les Préférences Système"
    else
        echo "✗ Échec de la désactivation du panneau Profils"
        return 1
    fi
}

# Usage
hide_profiles_pane

Restaurer/Réactiver le Panneau Profils

#!/bin/bash

# Restaurer l'accès au panneau Profils
restore_profiles_pane() {
    echo "=== Restauration de l'Accès au Panneau Profils ==="
    
    # Supprimer des panneaux masqués
    local hidden_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null)
    if [[ -n "$hidden_panes" ]]; then
        echo "Suppression des panneaux masqués..."
        defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
    fi
    
    # Supprimer des panneaux désactivés
    local disabled_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null)
    if [[ -n "$disabled_panes" ]]; then
        echo "Suppression des panneaux désactivés..."
        defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
    fi
    
    echo "✓ Accès au panneau Profils restauré"
    echo "Les utilisateurs peuvent maintenant accéder au panneau Profils dans les Préférences Système"
}

# Usage
restore_profiles_pane

Gestion de Plusieurs Panneaux de Préférences

#!/bin/bash

# Gérer plusieurs panneaux de préférences simultanément
manage_multiple_panes() {
    local action="${1:-hide}"  # hide, disable, ou restore
    local panes=("${@:2}")    # Tableau d'identifiants de panneaux
    
    if [[ ${#panes[@]} -eq 0 ]]; then
        echo "Usage : manage_multiple_panes [hide|disable|restore] <panneau1> [panneau2] ..."
        echo "Exemple : manage_multiple_panes hide profiles bluetooth network"
        return 1
    fi
    
    echo "=== Gestion de Plusieurs Panneaux de Préférences ==="
    echo "Action : $action"
    echo "Panneaux : ${panes[*]}"
    echo ""
    
    # Convertir les noms conviviaux en identifiants de bundle
    local bundle_ids=()
    for pane in "${panes[@]}"; do
        local bundle_id=$(get_bundle_identifier "$pane")
        if [[ -n "$bundle_id" ]]; then
            bundle_ids+=("$bundle_id")
            echo "✓ $pane -> $bundle_id"
        else
            echo "✗ Panneau inconnu : $pane"
        fi
    done
    
    if [[ ${#bundle_ids[@]} -eq 0 ]]; then
        echo "Aucun panneau valide spécifié"
        return 1
    fi
    
    # Appliquer l'action
    case "$action" in
        "hide")
            defaults write "/Library/Preferences/com.apple.systempreferences" \
                HiddenPreferencePanes -array "${bundle_ids[@]}"
            echo "✓ Panneaux masqués avec succès"
            ;;
        "disable")
            defaults write "/Library/Preferences/com.apple.systempreferences" \
                DisabledPreferencePanes -array "${bundle_ids[@]}"
            echo "✓ Panneaux désactivés avec succès"
            ;;
        "restore")
            defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
            defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
            echo "✓ Tous les panneaux restaurés"
            ;;
        *)
            echo "Action invalide : $action"
            return 1
            ;;
    esac
}

# Convertir les noms conviviaux en identifiants de bundle
get_bundle_identifier() {
    local pane_name="$1"
    
    case "$pane_name" in
        "profiles") echo "com.apple.preferences.configurationprofiles" ;;
        "bluetooth") echo "com.apple.preferences.Bluetooth" ;;
        "network") echo "com.apple.preference.network" ;;
        "security") echo "com.apple.preference.security" ;;
        "users") echo "com.apple.preferences.users" ;;
        "sharing") echo "com.apple.preferences.sharing" ;;
        "timemachine") echo "com.apple.prefs.backup" ;;
        "energy") echo "com.apple.preference.energysaver" ;;
        "displays") echo "com.apple.preference.displays" ;;
        "sound") echo "com.apple.preference.sound" ;;
        "keyboard") echo "com.apple.preference.keyboard" ;;
        "mouse") echo "com.apple.preference.mouse" ;;
        "trackpad") echo "com.apple.preference.trackpad" ;;
        "printers") echo "com.apple.preference.printfax" ;;
        "software_update") echo "com.apple.preferences.softwareupdate" ;;
        "date_time") echo "com.apple.preference.datetime" ;;
        "startup_disk") echo "com.apple.preference.startupdisk" ;;
        "accessibility") echo "com.apple.preference.universalaccess" ;;
        "screen_time") echo "com.apple.preference.screentime" ;;
        "extensions") echo "com.apple.preferences.extensions" ;;
        "spotlight") echo "com.apple.preference.spotlight" ;;
        "language_region") echo "com.apple.Localization" ;;
        "desktop_screensaver") echo "com.apple.preference.desktopscreeneffect" ;;
        "dock") echo "com.apple.preference.dock" ;;
        "mission_control") echo "com.apple.preference.expose" ;;
        "notifications") echo "com.apple.preference.notifications" ;;
        "internet_accounts") echo "com.apple.preferences.internetaccounts" ;;
        "wallet_apple_pay") echo "com.apple.preferences.wallet" ;;
        "siri") echo "com.apple.preference.speech" ;;
        "touch_id") echo "com.apple.preferences.password" ;;
        *) echo "" ;;
    esac
}

# Exemples d'utilisation
# manage_multiple_panes hide profiles bluetooth network
# manage_multiple_panes disable security users sharing
# manage_multiple_panes restore

Gestion Avancée des Préférences Système

Gestion des Préférences Basée sur les Politiques

#!/bin/bash

# Gestion des préférences système basée sur les politiques
apply_preference_policy() {
    local policy_name="${1:-standard_office}"
    local user_role="${2:-standard_user}"
    
    echo "=== Application de Politique de Préférences ==="
    echo "Politique : $policy_name"
    echo "Rôle Utilisateur : $user_role"
    echo ""
    
    # Définir les politiques
    case "$policy_name" in
        "kiosk_mode")
            apply_kiosk_policy "$user_role"
            ;;
        "locked_down")
            apply_locked_down_policy "$user_role"
            ;;
        "standard_office")
            apply_standard_office_policy "$user_role"
            ;;
        "developer_workstation")
            apply_developer_policy "$user_role"
            ;;
        "educational")
            apply_educational_policy "$user_role"
            ;;
        "healthcare")
            apply_healthcare_policy "$user_role"
            ;;
        "financial")
            apply_financial_policy "$user_role"
            ;;
        "public_terminal")
            apply_public_terminal_policy "$user_role"
            ;;
        "executive")
            apply_executive_policy "$user_role"
            ;;
        "contractor")
            apply_contractor_policy "$user_role"
            ;;
        *)
            echo "Politique inconnue : $policy_name"
            return 1
            ;;
    esac
}

# Politique mode kiosque (restrictions maximales)
apply_kiosk_policy() {
    echo "Application de la politique mode kiosque..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
        "com.apple.preferences.softwareupdate"
        "com.apple.preference.datetime"
        "com.apple.preference.startupdisk"
        "com.apple.preferences.extensions"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        HiddenPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique kiosque appliquée - la plupart des préférences masquées"
}

# Politique verrouillée (haute sécurité)
apply_locked_down_policy() {
    echo "Application de la politique verrouillée..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.prefs.backup"
        "com.apple.preferences.softwareupdate"
        "com.apple.preference.startupdisk"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique verrouillée appliquée - panneaux sensibles à la sécurité désactivés"
}

# Politique bureau standard (restrictions modérées)
apply_standard_office_policy() {
    echo "Application de la politique bureau standard..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preferences.sharing"
        "com.apple.preference.startupdisk"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique bureau standard appliquée - restrictions minimales"
}

# Politique poste de développeur (restrictions minimales)
apply_developer_policy() {
    echo "Application de la politique poste de développeur..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique développeur appliquée - seule la gestion de profils restreinte"
}

# Politique éducative (restrictions appropriées aux étudiants)
apply_educational_policy() {
    echo "Application de la politique éducative..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.preferences.softwareupdate"
        "com.apple.preference.startupdisk"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        HiddenPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique éducative appliquée - configuration sécurisée pour étudiants"
}

# Politique santé (axée sur la conformité HIPAA)
apply_healthcare_policy() {
    echo "Application de la politique santé..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique santé appliquée - axée sur la conformité HIPAA"
}

# Politique financière (sécurité renforcée)
apply_financial_policy() {
    echo "Application de la politique financière..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
        "com.apple.preferences.extensions"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique financière appliquée - restrictions de sécurité renforcées"
}

# Politique terminal public (protection maximale)
apply_public_terminal_policy() {
    echo "Application de la politique terminal public..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
        "com.apple.preferences.softwareupdate"
        "com.apple.preference.datetime"
        "com.apple.preference.startupdisk"
        "com.apple.preferences.extensions"
        "com.apple.preference.energysaver"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        HiddenPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique terminal public appliquée - protection maximale"
}

# Politique exécutif (restrictions minimales, accès complet)
apply_executive_policy() {
    echo "Application de la politique exécutif..."
    # Supprimer toutes les restrictions pour les exécutifs
    defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
    defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
    
    echo "✓ Politique exécutif appliquée - accès complet accordé"
}

# Politique contractuel (restrictions d'accès temporaire)
apply_contractor_policy() {
    echo "Application de la politique contractuel..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preferences.sharing"
        "com.apple.prefs.backup"
        "com.apple.preferences.softwareupdate"
        "com.apple.preference.startupdisk"
        "com.apple.preferences.extensions"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Politique contractuel appliquée - restrictions d'accès temporaire"
}

Outil de Gestion des Préférences Système d'Entreprise

#!/bin/bash

# Outil de Gestion des Préférences Système MacFleet
# Contrôle complet des panneaux de préférences et gestion de politiques d'entreprise

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_preferences.log"
REPORT_DIR="/etc/macfleet/reports/preferences"
CONFIG_DIR="/etc/macfleet/preferences"
POLICY_DIR="/etc/macfleet/policies/preferences"
BACKUP_DIR="/etc/macfleet/backups/preferences"

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

# Mapping complet des panneaux de préférences
declare -A PREFERENCE_PANES=(
    ["profiles"]="com.apple.preferences.configurationprofiles"
    ["bluetooth"]="com.apple.preferences.Bluetooth"
    ["network"]="com.apple.preference.network"
    ["security"]="com.apple.preference.security"
    ["users"]="com.apple.preferences.users"
    ["sharing"]="com.apple.preferences.sharing"
    ["timemachine"]="com.apple.prefs.backup"
    ["energy"]="com.apple.preference.energysaver"
    ["displays"]="com.apple.preference.displays"
    ["sound"]="com.apple.preference.sound"
    ["keyboard"]="com.apple.preference.keyboard"
    ["mouse"]="com.apple.preference.mouse"
    ["trackpad"]="com.apple.preference.trackpad"
    ["printers"]="com.apple.preference.printfax"
    ["software_update"]="com.apple.preferences.softwareupdate"
    ["date_time"]="com.apple.preference.datetime"
    ["startup_disk"]="com.apple.preference.startupdisk"
    ["accessibility"]="com.apple.preference.universalaccess"
    ["screen_time"]="com.apple.preference.screentime"
    ["extensions"]="com.apple.preferences.extensions"
    ["spotlight"]="com.apple.preference.spotlight"
    ["language_region"]="com.apple.Localization"
    ["desktop_screensaver"]="com.apple.preference.desktopscreeneffect"
    ["dock"]="com.apple.preference.dock"
    ["mission_control"]="com.apple.preference.expose"
    ["notifications"]="com.apple.preference.notifications"
    ["internet_accounts"]="com.apple.preferences.internetaccounts"
    ["wallet_apple_pay"]="com.apple.preferences.wallet"
    ["siri"]="com.apple.preference.speech"
    ["touch_id"]="com.apple.preferences.password"
)

# Modèles de politiques d'entreprise
declare -A POLICY_TEMPLATES=(
    ["kiosk_mode"]="Restrictions maximales pour kiosques publics et affichages"
    ["locked_down"]="Restrictions de haute sécurité pour environnements sensibles"
    ["standard_office"]="Restrictions modérées pour environnements de bureau typiques"
    ["developer_workstation"]="Restrictions minimales pour environnements de développement"
    ["educational"]="Restrictions appropriées aux étudiants pour institutions éducatives"
    ["healthcare"]="Restrictions conformes HIPAA pour environnements de santé"
    ["financial"]="Sécurité renforcée pour environnements de services financiers"
    ["public_terminal"]="Protection maximale pour terminaux d'accès public"
    ["executive"]="Restrictions minimales à nulles pour utilisateurs exécutifs"
    ["contractor"]="Restrictions d'accès temporaire pour travailleurs contractuels"
)

# Cadres de conformité
declare -A COMPLIANCE_FRAMEWORKS=(
    ["hipaa"]="Health Insurance Portability and Accountability Act"
    ["sox"]="Conformité Sarbanes-Oxley Act"
    ["pci_dss"]="Payment Card Industry Data Security Standard"
    ["ferpa"]="Family Educational Rights and Privacy Act"
    ["gdpr"]="General Data Protection Regulation"
    ["nist"]="National Institute of Standards and Technology"
    ["iso27001"]="International Organization for Standardization 27001"
    ["cis"]="Center for Internet Security controls"
    ["fisma"]="Federal Information Security Management Act"
    ["common_criteria"]="Standard d'évaluation de sécurité Common Criteria"
)

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

# Gestion des préférences système d'entreprise
enterprise_preferences_management() {
    local operation="${1:-status}"
    local policy_name="${2:-standard_office}"
    local target_panes="${3:-}"
    local compliance_framework="${4:-}"
    
    log_action "Démarrage gestion préférences d'entreprise" "INFO"
    log_action "Opération : $operation, Politique : $policy_name" "INFO"
    
    echo "=== Gestion des Préférences Système d'Entreprise ==="
    echo "Opération : $operation"
    echo "Politique : $policy_name"
    echo "Panneaux Cibles : ${target_panes:-tous_définis_par_politique}"
    echo "Cadre de Conformité : ${compliance_framework:-aucun}"
    echo "ID de Gestion : $(uuidgen)"
    echo ""
    
    # Sauvegarder la configuration actuelle
    backup_current_configuration
    
    case "$operation" in
        "apply_policy")
            apply_enterprise_policy "$policy_name" "$compliance_framework"
            ;;
        "hide_panes")
            if [[ -n "$target_panes" ]]; then
                hide_specific_panes "$target_panes"
            else
                echo "Erreur : Aucun panneau cible spécifié pour l'opération de masquage"
                return 1
            fi
            ;;
        "disable_panes")
            if [[ -n "$target_panes" ]]; then
                disable_specific_panes "$target_panes"
            else
                echo "Erreur : Aucun panneau cible spécifié pour l'opération de désactivation"
                return 1
            fi
            ;;
        "restore_all")
            restore_all_preferences
            ;;
        "status")
            show_preferences_status
            ;;
        "audit")
            perform_preferences_audit "$compliance_framework"
            ;;
        "list_policies")
            list_available_policies
            ;;
        "list_panes")
            list_available_panes
            ;;
        *)
            echo "Opération inconnue : $operation"
            return 1
            ;;
    esac
    
    # Générer le rapport de gestion
    generate_preferences_report "$operation" "$policy_name" "$target_panes" "$compliance_framework"
    
    log_action "Gestion des préférences d'entreprise terminée" "INFO"
}

# Sauvegarder la configuration actuelle
backup_current_configuration() {
    local backup_file="$BACKUP_DIR/preferences_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    echo "--- Création de Sauvegarde de Configuration ---"
    
    # Copier la configuration actuelle des préférences système
    if [[ -f "/Library/Preferences/com.apple.systempreferences.plist" ]]; then
        cp "/Library/Preferences/com.apple.systempreferences.plist" "$backup_file"
        echo "✓ Configuration sauvegardée dans : $backup_file"
        log_action "Configuration sauvegardée : $backup_file" "INFO"
    else
        echo "⚠️ Aucun fichier de configuration existant trouvé"
        log_action "Aucun fichier de configuration existant à sauvegarder" "WARNING"
    fi
}

# Appliquer la politique d'entreprise avec considérations de conformité
apply_enterprise_policy() {
    local policy_name="$1"
    local compliance_framework="$2"
    
    echo "--- Application de Politique d'Entreprise ---"
    echo "Politique : $policy_name"
    echo "Conformité : ${compliance_framework:-aucune}"
    
    # Appliquer la politique de base
    case "$policy_name" in
        "kiosk_mode")
            apply_kiosk_mode_policy
            ;;
        "locked_down")
            apply_locked_down_policy
            ;;
        "standard_office")
            apply_standard_office_policy
            ;;
        "developer_workstation")
            apply_developer_workstation_policy
            ;;
        "educational")
            apply_educational_policy
            ;;
        "healthcare")
            apply_healthcare_policy
            ;;
        "financial")
            apply_financial_policy
            ;;
        "public_terminal")
            apply_public_terminal_policy
            ;;
        "executive")
            apply_executive_policy
            ;;
        "contractor")
            apply_contractor_policy
            ;;
        *)
            echo "Politique inconnue : $policy_name"
            return 1
            ;;
    esac
    
    # Appliquer les modifications spécifiques à la conformité
    if [[ -n "$compliance_framework" ]]; then
        apply_compliance_modifications "$compliance_framework"
    fi
    
    echo "✓ Politique d'entreprise appliquée avec succès"
}

# Appliquer les modifications spécifiques à la conformité
apply_compliance_modifications() {
    local framework="$1"
    
    echo "--- Application de Modifications de Conformité ---"
    echo "Cadre : $framework"
    
    case "$framework" in
        "hipaa")
            apply_hipaa_compliance
            ;;
        "sox")
            apply_sox_compliance
            ;;
        "pci_dss")
            apply_pci_dss_compliance
            ;;
        "ferpa")
            apply_ferpa_compliance
            ;;
        "gdpr")
            apply_gdpr_compliance
            ;;
        *)
            echo "Cadre de conformité inconnu : $framework"
            ;;
    esac
}

# Modifications de conformité HIPAA
apply_hipaa_compliance() {
    echo "Application des modifications de conformité HIPAA..."
    
    # Restrictions supplémentaires pour la protection des données de santé
    local hipaa_restricted=(
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
        "com.apple.preferences.internetaccounts"
    )
    
    # Obtenir les panneaux actuellement désactivés
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    
    # Combiner avec les exigences HIPAA
    local combined_disabled=($current_disabled "${hipaa_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ Modifications de conformité HIPAA appliquées"
}

# Modifications de conformité SOX
apply_sox_compliance() {
    echo "Application des modifications de conformité SOX..."
    
    # Exigences d'audit et de contrôle financier
    local sox_restricted=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preference.datetime"
    )
    
    # Modèle similaire pour SOX
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    local combined_disabled=($current_disabled "${sox_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ Modifications de conformité SOX appliquées"
}

# Modifications de conformité PCI DSS
apply_pci_dss_compliance() {
    echo "Application des modifications de conformité PCI DSS..."
    
    # Exigences de l'industrie des cartes de paiement
    local pci_restricted=(
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.preference.security"
        "com.apple.preferences.extensions"
    )
    
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    local combined_disabled=($current_disabled "${pci_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ Modifications de conformité PCI DSS appliquées"
}

# Modifications de conformité FERPA
apply_ferpa_compliance() {
    echo "Application des modifications de conformité FERPA..."
    
    # Exigences de confidentialité éducative
    local ferpa_restricted=(
        "com.apple.preferences.sharing"
        "com.apple.preferences.internetaccounts"
        "com.apple.prefs.backup"
    )
    
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    local combined_disabled=($current_disabled "${ferpa_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ Modifications de conformité FERPA appliquées"
}

# Modifications de conformité GDPR
apply_gdpr_compliance() {
    echo "Application des modifications de conformité GDPR..."
    
    # Exigences de protection des données européennes
    local gdpr_restricted=(
        "com.apple.preferences.sharing"
        "com.apple.prefs.backup"
        "com.apple.preferences.internetaccounts"
        "com.apple.preference.notifications"
    )
    
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    local combined_disabled=($current_disabled "${gdpr_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ Modifications de conformité GDPR appliquées"
}

# Afficher le statut actuel des préférences
show_preferences_status() {
    echo "--- Statut des Préférences Système ---"
    
    # Vérifier les panneaux masqués
    local hidden_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null)
    if [[ -n "$hidden_panes" ]]; then
        echo "Panneaux Masqués :"
        echo "$hidden_panes" | tr -d '(),"' | tr '\n' ' ' | xargs -n1 | while read pane; do
            if [[ -n "$pane" ]]; then
                local friendly_name=$(get_friendly_name "$pane")
                echo "  - $friendly_name ($pane)"
            fi
        done
    else
        echo "Panneaux Masqués : Aucun"
    fi
    
    echo ""
    
    # Vérifier les panneaux désactivés
    local disabled_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null)
    if [[ -n "$disabled_panes" ]]; then
        echo "Panneaux Désactivés :"
        echo "$disabled_panes" | tr -d '(),"' | tr '\n' ' ' | xargs -n1 | while read pane; do
            if [[ -n "$pane" ]]; then
                local friendly_name=$(get_friendly_name "$pane")
                echo "  - $friendly_name ($pane)"
            fi
        done
    else
        echo "Panneaux Désactivés : Aucun"
    fi
}

# Obtenir le nom convivial à partir de l'identifiant de bundle
get_friendly_name() {
    local bundle_id="$1"
    
    for friendly_name in "${!PREFERENCE_PANES[@]}"; do
        if [[ "${PREFERENCE_PANES[$friendly_name]}" == "$bundle_id" ]]; then
            echo "$friendly_name"
            return
        fi
    done
    
    echo "inconnu"
}

# Générer un rapport de préférences complet
generate_preferences_report() {
    local operation="$1"
    local policy_name="$2"
    local target_panes="$3"
    local compliance_framework="$4"
    
    local report_file="$REPORT_DIR/preferences_report_$(date +%Y%m%d_%H%M%S).json"
    
    # Obtenir la configuration actuelle
    local hidden_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    local disabled_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    
    cat > "$report_file" << EOF
{
    "preferences_report": {
        "report_metadata": {
            "report_id": "$(uuidgen)",
            "generated_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
            "hostname": "$(hostname)",
            "script_version": "$SCRIPT_VERSION",
            "macos_version": "$(sw_vers -productVersion)"
        },
        "operation_details": {
            "operation": "$operation",
            "policy_name": "$policy_name",
            "target_panes": "$target_panes",
            "compliance_framework": "$compliance_framework"
        },
        "current_configuration": {
            "hidden_panes": "$hidden_panes",
            "disabled_panes": "$disabled_panes",
            "total_restrictions": $(echo "$hidden_panes $disabled_panes" | wc -w)
        },
        "system_information": {
            "total_preference_panes": ${#PREFERENCE_PANES[@]},
            "available_policies": ${#POLICY_TEMPLATES[@]},
            "compliance_frameworks": ${#COMPLIANCE_FRAMEWORKS[@]}
        }
    }
}
EOF
    
    echo "Rapport de préférences généré : $report_file"
    log_action "Rapport de préférences généré : $report_file" "INFO"
}

# Lister les politiques disponibles
list_available_policies() {
    echo "--- Politiques d'Entreprise Disponibles ---"
    for policy in "${!POLICY_TEMPLATES[@]}"; do
        echo "  $policy : ${POLICY_TEMPLATES[$policy]}"
    done
}

# Lister les panneaux de préférences disponibles
list_available_panes() {
    echo "--- Panneaux de Préférences Disponibles ---"
    for pane in "${!PREFERENCE_PANES[@]}"; do
        echo "  $pane : ${PREFERENCE_PANES[$pane]}"
    done
}

# Fonction d'exécution principale
main() {
    local operation="${1:-help}"
    local policy="${2:-}"
    local panes="${3:-}"
    local compliance="${4:-}"
    
    log_action "=== Gestion des Préférences Système MacFleet Démarrée ===" "INFO"
    log_action "Opération : $operation" "INFO"
    
    case "$operation" in
        "apply")
            if [[ -z "$policy" ]]; then
                echo "Usage : $0 apply <nom_politique> [cadre_conformité]"
                echo "Politiques disponibles : ${!POLICY_TEMPLATES[*]}"
                exit 1
            fi
            enterprise_preferences_management "apply_policy" "$policy" "" "$compliance"
            ;;
        "hide")
            if [[ -z "$panes" ]]; then
                echo "Usage : $0 hide <panneau1,panneau2,...>"
                echo "Panneaux disponibles : ${!PREFERENCE_PANES[*]}"
                exit 1
            fi
            enterprise_preferences_management "hide_panes" "" "$panes"
            ;;
        "disable")
            if [[ -z "$panes" ]]; then
                echo "Usage : $0 disable <panneau1,panneau2,...>"
                echo "Panneaux disponibles : ${!PREFERENCE_PANES[*]}"
                exit 1
            fi
            enterprise_preferences_management "disable_panes" "" "$panes"
            ;;
        "restore")
            enterprise_preferences_management "restore_all"
            ;;
        "status")
            enterprise_preferences_management "status"
            ;;
        "audit")
            enterprise_preferences_management "audit" "" "" "$policy"
            ;;
        "list-policies")
            enterprise_preferences_management "list_policies"
            ;;
        "list-panes")
            enterprise_preferences_management "list_panes"
            ;;
        "help")
            echo "Usage : $0 [opération] [options...]"
            echo "Opérations :"
            echo "  apply <politique> [conformité] - Appliquer une politique d'entreprise"
            echo "  hide <panneaux> - Masquer des panneaux de préférences spécifiques"
            echo "  disable <panneaux> - Désactiver des panneaux de préférences spécifiques"
            echo "  restore - Restaurer tous les panneaux de préférences"
            echo "  status - Afficher le statut actuel des préférences"
            echo "  audit [conformité] - Effectuer un audit de conformité"
            echo "  list-policies - Lister les politiques disponibles"
            echo "  list-panes - Lister les panneaux de préférences disponibles"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Politiques Disponibles : ${!POLICY_TEMPLATES[*]}"
            echo "Cadres de Conformité : ${!COMPLIANCE_FRAMEWORKS[*]}"
            ;;
        *)
            log_action "ERREUR : Opération inconnue : $operation" "ERROR"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion des préférences système terminée ===" "INFO"
}

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

Considérations Importantes

Compatibilité des Versions macOS

  • Masquage des Panneaux : Nécessite macOS 13.0 ou ultérieur (HiddenPreferencePanes)
  • Désactivation des Panneaux : Fonctionne sur macOS 10.2 et ultérieur (DisabledPreferencePanes)
  • Identifiants de Bundle : Peuvent changer entre les versions macOS
  • Protection d'Intégrité Système : Certaines restrictions peuvent ne pas s'appliquer avec SIP activé

Notes de Déploiement d'Entreprise

  • Impact Utilisateur : Les panneaux masqués/désactivés affectent tous les utilisateurs sur l'appareil
  • Accès Administratif : Les modifications nécessitent des privilèges administrateur
  • Test de Politiques : Toujours tester les politiques sur des appareils non-production d'abord
  • Sauvegarde et Récupération : Maintenir des sauvegardes de configuration pour le rollback de politique

Considérations de Sécurité et Conformité

  • Principe du Moindre Privilège : Restreindre l'accès uniquement aux panneaux de préférences nécessaires
  • Journalisation d'Audit : Tous les changements de préférences doivent être journalisés pour la conformité
  • Cadres de Conformité : Différentes industries nécessitent des restrictions spécifiques
  • Formation Utilisateur : Informer les utilisateurs sur les fonctionnalités restreintes et les alternatives

Gestion d'Information Système d'Entreprise sur macOS

Collectez et analysez les informations système complètes de vos appareils MacFleet en utilisant le profilage système avancé, la collecte automatisée de données et l'analytique de niveau entreprise. Ce tutoriel fournit des outils puissants pour implémenter l'inventaire organisationnel des appareils, la surveillance et les rapports de conformité.

Comprendre l'Information Système macOS

macOS fournit plusieurs outils pour la collecte d'informations système :

  • system_profiler - Collecte complète d'informations système
  • uname - Informations de base du système et du noyau
  • sw_vers - Informations de version logicielle
  • hwpref - Données de préférence matérielle
  • ioreg - Informations matérielles du registre I/O
  • Information Système.app - Interface graphique d'information système

Opérations d'Information Système de Base

Information Système Complète

#!/bin/bash

# Obtenir l'information système complète
echo "=== Information Système Complète ==="
system_profiler

echo "Collecte d'information système terminée"

Lister les Types de Données Disponibles

#!/bin/bash

# Lister tous les types de données system_profiler disponibles
echo "=== Types de Données Disponibles ==="
system_profiler --listDataTypes

echo "Listage des types de données terminé"

Information Système Spécifique

#!/bin/bash

# Obtenir une information système spécifique
DATA_TYPE="${1:-SPHardwareDataType}"

echo "=== Information $DATA_TYPE ==="
system_profiler "$DATA_TYPE"

echo "Information système spécifique récupérée"

Sauvegarder le Rapport Système dans un Fichier

#!/bin/bash

# Sauvegarder l'information système dans un fichier
REPORT_FILE="${1:-/tmp/system_report_$(date +%Y%m%d_%H%M%S).txt}"

echo "=== Sauvegarde du Rapport Système ==="
system_profiler > "$REPORT_FILE"

echo "Rapport système sauvegardé dans : $REPORT_FILE"

Système de Gestion d'Information Système d'Entreprise

#!/bin/bash

# Système de Gestion d'Information Système d'Entreprise MacFleet
# Collecte complète de données système, analyse et surveillance

# Configuration
MACFLEET_DIR="/etc/macfleet"
SYSINFO_DIR="$MACFLEET_DIR/system_information"
REPORTS_DIR="$MACFLEET_DIR/reports"
COMPLIANCE_DIR="$MACFLEET_DIR/compliance"
AUDIT_DIR="$MACFLEET_DIR/audit"
LOG_FILE="/var/log/macfleet_system_information.log"
POLICIES_DIR="$MACFLEET_DIR/system_policies"
INVENTORY_DIR="$MACFLEET_DIR/inventory"

# Créer la structure de répertoires
create_directories() {
    local dirs=("$MACFLEET_DIR" "$SYSINFO_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$POLICIES_DIR" "$INVENTORY_DIR")
    for dir in "${dirs[@]}"; do
        [[ ! -d "$dir" ]] && mkdir -p "$dir"
    done
}

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

# Catégories d'Information Système pour la Gestion d'Entreprise
declare -A SYSTEM_CATEGORIES=(
    ["hardware_overview"]="SPHardwareDataType,SPMemoryDataType,SPStorageDataType"
    ["software_inventory"]="SPSoftwareDataType,SPApplicationsDataType,SPExtensionsDataType"
    ["network_configuration"]="SPNetworkDataType,SPBluetoothDataType,SPWWANDataType"
    ["security_configuration"]="SPFirewallDataType,SPManagedClientDataType,SPConfigurationProfileDataType"
    ["peripherals"]="SPUSBDataType,SPThunderboltDataType,SPAudioDataType,SPDisplaysDataType"
    ["system_diagnostics"]="SPPowerDataType,SPLogsDataType,SPDiagnosticsDataType"
    ["enterprise_management"]="SPManagedClientDataType,SPConfigurationProfileDataType,SPCertificatesDataType"
)

# Politiques de Collecte de Données
declare -A COLLECTION_POLICIES=(
    ["comprehensive"]="all_data_types,full_detail,include_sensitive,export_json"
    ["security_focused"]="security_data,certificates,firewall_config,managed_profiles"
    ["hardware_inventory"]="hardware_overview,storage_details,memory_config,peripherals"
    ["software_audit"]="applications,extensions,system_software,preferences"
    ["network_assessment"]="network_interfaces,bluetooth_devices,wireless_config"
    ["compliance_report"]="security_config,certificates,managed_profiles,audit_data"
)

# Seuils de Surveillance de Santé Système
declare -A HEALTH_THRESHOLDS=(
    ["cpu_temperature_warning"]=80
    ["memory_pressure_warning"]=80
    ["storage_usage_warning"]=85
    ["battery_cycle_warning"]=800
    ["uptime_excessive_hours"]=168  # 1 semaine
)

# Collecte complète d'information système
collect_system_information() {
    local collection_policy="$1"
    local output_format="${2:-json}"
    local include_sensitive="${3:-false}"
    local collection_id="sysinfo_$(date +%Y%m%d_%H%M%S)"
    local output_file="$SYSINFO_DIR/${collection_id}.${output_format}"
    
    log_action "Démarrage de la collecte d'information système : $collection_policy"
    
    # Initialiser les métadonnées de collecte
    local hostname=$(hostname)
    local serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    local model_identifier=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk '{print $3}')
    local os_version=$(sw_vers -productVersion)
    local build_version=$(sw_vers -buildVersion)
    local uptime=$(uptime | awk '{print $3,$4}' | sed 's/,//')
    
    # Collecter les données selon la politique
    local collected_data=""
    local data_types=""
    
    case "$collection_policy" in
        "comprehensive")
            data_types=$(system_profiler --listDataTypes | tr '\n' ' ')
            ;;
        "security_focused")
            data_types="SPFirewallDataType SPManagedClientDataType SPConfigurationProfileDataType SPCertificatesDataType"
            ;;
        "hardware_inventory")
            data_types="SPHardwareDataType SPMemoryDataType SPStorageDataType SPUSBDataType SPDisplaysDataType SPAudioDataType"
            ;;
        "software_audit")
            data_types="SPSoftwareDataType SPApplicationsDataType SPExtensionsDataType SPPrefPaneDataType"
            ;;
        "network_assessment")
            data_types="SPNetworkDataType SPBluetoothDataType SPWWANDataType SPAirPortDataType"
            ;;
        "compliance_report")
            data_types="SPManagedClientDataType SPConfigurationProfileDataType SPCertificatesDataType SPFirewallDataType"
            ;;
    esac
    
    # Collecter les données pour chaque type spécifié
    for data_type in $data_types; do
        [[ -z "$data_type" ]] && continue
        
        log_action "Collecte du type de données : $data_type"
        
        if [[ "$output_format" == "json" ]]; then
            local type_data=$(system_profiler -json "$data_type" 2>/dev/null)
            if [[ -n "$type_data" && "$type_data" != "null" ]]; then
                collected_data="$collected_data\"$data_type\":$type_data,"
            fi
        else
            local type_data=$(system_profiler "$data_type" 2>/dev/null)
            if [[ -n "$type_data" ]]; then
                collected_data="$collected_data\n=== $data_type ===\n$type_data\n"
            fi
        fi
    done
    
    # Métriques système supplémentaires
    local additional_metrics=""
    if [[ "$include_sensitive" == "true" || "$collection_policy" == "comprehensive" ]]; then
        local cpu_info=$(sysctl -n machdep.cpu.brand_string)
        local memory_total=$(system_profiler SPHardwareDataType | grep "Memory:" | awk '{print $2,$3}')
        local storage_info=$(df -h / | awk 'NR==2 {print $2,$3,$4,$5}')
        local network_interfaces=$(ifconfig | grep "^[a-z]" | awk '{print $1}' | sed 's/:$//' | tr '\n' ' ')
        local running_processes=$(ps aux | wc -l)
        local logged_in_users=$(who | wc -l)
        
        additional_metrics="{\"cpu_info\":\"$cpu_info\",\"memory_total\":\"$memory_total\",\"storage_info\":\"$storage_info\",\"network_interfaces\":\"$network_interfaces\",\"running_processes\":$running_processes,\"logged_in_users\":$logged_in_users}"
    fi
    
    # Créer une sortie structurée
    if [[ "$output_format" == "json" ]]; then
        # Supprimer la virgule finale des données collectées
        collected_data="${collected_data%,}"
        
        cat > "$output_file" << EOF
{
  "collection_metadata": {
    "collection_id": "$collection_id",
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "policy": "$collection_policy",
    "hostname": "$hostname",
    "serial_number": "$serial_number",
    "model_identifier": "$model_identifier",
    "os_version": "$os_version",
    "build_version": "$build_version",
    "uptime": "$uptime"
  },
  "system_data": {$collected_data},
  "additional_metrics": $additional_metrics,
  "collection_summary": {
    "data_types_collected": $(echo "$data_types" | wc -w),
    "include_sensitive": "$include_sensitive",
    "collection_size_bytes": $(wc -c < "$output_file" 2>/dev/null || echo "0")
  }
}
EOF
    else
        cat > "$output_file" << EOF
=== Rapport d'Information Système MacFleet ===
ID de Collecte : $collection_id
Horodatage : $(date)
Politique : $collection_policy
Nom d'hôte : $hostname
Numéro de Série : $serial_number
Modèle : $model_identifier
Version OS : $os_version ($build_version)
Temps de fonctionnement : $uptime

$collected_data
EOF
    fi
    
    log_action "Collecte d'information système terminée : $output_file"
    echo "$output_file"
}

# Analyse de santé système
analyze_system_health() {
    local analysis_type="$1"
    local health_report="$REPORTS_DIR/system_health_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Démarrage de l'analyse de santé système : $analysis_type"
    
    # Collecter les métriques de santé de base
    local cpu_temp=$(sudo powermetrics -n 1 -s cpu_power | grep "CPU die temperature" | awk '{print $4}' 2>/dev/null || echo "0")
    local memory_pressure=$(vm_stat | grep "Pages compressed" | awk '{print $3}' | sed 's/\.//' | head -1)
    local storage_usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
    local uptime_seconds=$(sysctl -n kern.boottime | awk '{print $4}' | sed 's/,//')
    local current_time=$(date +%s)
    local uptime_hours=$(( (current_time - uptime_seconds) / 3600 ))
    
    # Analyse de charge système
    local load_average=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
    local cpu_cores=$(sysctl -n hw.ncpu)
    local load_per_core=$(echo "scale=2; $load_average / $cpu_cores" | bc -l 2>/dev/null || echo "0")
    
    # Informations de batterie (si disponible)
    local battery_cycle_count=0
    local battery_condition="Inconnu"
    if system_profiler SPPowerDataType | grep -q "Cycle Count"; then
        battery_cycle_count=$(system_profiler SPPowerDataType | grep "Cycle Count" | awk '{print $3}')
        battery_condition=$(system_profiler SPPowerDataType | grep "Condition" | awk '{print $2}')
    fi
    
    # Déterminer l'état de santé
    local health_status="healthy"
    local health_alerts=""
    
    if [[ $(echo "$cpu_temp > ${HEALTH_THRESHOLDS[cpu_temperature_warning]}" | bc -l 2>/dev/null) -eq 1 ]]; then
        health_status="warning"
        health_alerts="$health_alerts\"Température CPU élevée : ${cpu_temp}°C\","
    fi
    
    if [[ $storage_usage -gt ${HEALTH_THRESHOLDS[storage_usage_warning]} ]]; then
        health_status="warning"
        health_alerts="$health_alerts\"Utilisation stockage élevée : ${storage_usage}%\","
    fi
    
    if [[ $battery_cycle_count -gt ${HEALTH_THRESHOLDS[battery_cycle_warning]} ]]; then
        health_status="warning"
        health_alerts="$health_alerts\"Nombre de cycles batterie élevé : $battery_cycle_count\","
    fi
    
    if [[ $uptime_hours -gt ${HEALTH_THRESHOLDS[uptime_excessive_hours]} ]]; then
        health_status="attention"
        health_alerts="$health_alerts\"Temps de fonctionnement excessif : ${uptime_hours} heures\","
    fi
    
    # Supprimer la virgule finale
    health_alerts="${health_alerts%,}"
    
    # Créer le rapport de santé
    cat > "$health_report" << EOF
{
  "system_health_analysis": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "analysis_type": "$analysis_type",
    "health_status": "$health_status",
    "device_info": {
      "hostname": "$(hostname)",
      "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')",
      "model": "$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk '{print $3}')",
      "os_version": "$(sw_vers -productVersion)"
    }
  },
  "health_metrics": {
    "cpu_temperature_celsius": "$cpu_temp",
    "memory_pressure_pages": "$memory_pressure",
    "storage_usage_percent": $storage_usage,
    "uptime_hours": $uptime_hours,
    "load_average": "$load_average",
    "load_per_core": "$load_per_core",
    "cpu_cores": $cpu_cores,
    "battery_cycle_count": $battery_cycle_count,
    "battery_condition": "$battery_condition"
  },
  "health_alerts": [$health_alerts],
  "recommendations": [
    $([ "$health_status" != "healthy" ] && echo "\"Traiter les alertes de santé pour performance optimale\",")
    $([ $uptime_hours -gt 72 ] && echo "\"Considérer redémarrage système pour performance optimale\",")
    $([ $storage_usage -gt 80 ] && echo "\"Réviser utilisation stockage et nettoyer si nécessaire\",")
    "\"Surveillance régulière de santé recommandée\""
  ]
}
EOF
    
    if [[ "$health_status" != "healthy" ]]; then
        log_action "AVERTISSEMENT SANTÉ : Problèmes de santé système détectés - $health_status"
    fi
    
    log_action "Analyse de santé système terminée : $health_report"
    echo "$health_report"
}

# Fonction d'exécution principale
main() {
    create_directories
    
    case "${1:-}" in
        "collect")
            collect_system_information "${2:-comprehensive}" "${3:-json}" "${4:-false}"
            ;;
        "analyze_health")
            analyze_system_health "${2:-standard}"
            ;;
        "help"|*)
            echo "Système de Gestion d'Information Système d'Entreprise MacFleet"
            echo ""
            echo "Utilisation : $0 <commande> [options]"
            echo ""
            echo "Commandes :"
            echo "  collect [politique] [format] [sensible]  - Collecter information système (comprehensive|security_focused|hardware_inventory|software_audit|network_assessment|compliance_report) [json|text] [true|false]"
            echo "  analyze_health [type]                    - Analyser santé système (standard|detailed|continuous)"
            echo ""
            echo "Exemples :"
            echo "  $0 collect comprehensive json false"
            echo "  $0 analyze_health detailed"
            ;;
    esac
}

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

Types de Données d'Information Système

Le système d'entreprise supporte la collecte complète de types de données :

CatégorieTypes de DonnéesCas d'Usage
Aperçu MatérielSPHardwareDataType, SPMemoryDataType, SPStorageDataTypeInventaire d'actifs et planification de capacité
Inventaire LogicielSPSoftwareDataType, SPApplicationsDataType, SPExtensionsDataTypeGestion de licences et audit de sécurité
Configuration RéseauSPNetworkDataType, SPBluetoothDataType, SPWWANDataTypeSécurité réseau et analyse de connectivité
Configuration SécuritéSPFirewallDataType, SPManagedClientDataType, SPConfigurationProfileDataTypeÉvaluation de conformité et posture de sécurité
PériphériquesSPUSBDataType, SPThunderboltDataType, SPAudioDataType, SPDisplaysDataTypeGestion périphériques et validation sécurité

Politiques de Collecte d'Entreprise

Collecte Complète

# Collecter toutes les informations système disponibles
./sysinfo_manager.sh collect comprehensive json false

# Inclure les informations sensibles pour analyse détaillée
./sysinfo_manager.sh collect comprehensive json true

Collecte Axée Sécurité

# Collecter uniquement les informations pertinentes à la sécurité
./sysinfo_manager.sh collect security_focused json false

Inventaire Matériel

# Collecter les données d'inventaire matériel
./sysinfo_manager.sh collect hardware_inventory json false

Surveillance de Santé Système

Analyse de Santé

# Effectuer analyse de santé standard
./sysinfo_manager.sh analyze_health standard

# Analyse de santé détaillée avec métriques complètes
./sysinfo_manager.sh analyze_health detailed

Considérations Importantes de Sécurité

  • Sensibilité des données nécessite manipulation et chiffrement appropriés
  • Contrôles d'accès doivent être implémentés pour informations système sensibles
  • Journalisation d'audit doit suivre tous les accès et collectes d'information système
  • Sécurité réseau doit protéger transmission de données entre appareils
  • Exigences de conformité varient selon l'industrie et la localisation géographique

Performance et Évolutivité

Le système d'entreprise est conçu pour :

  • Déploiement à grande échelle sur des milliers d'appareils
  • Collecte efficace de données avec impact système minimal
  • Stockage évolutif pour données historiques et analyse de tendances
  • Haute disponibilité avec redondance et capacités de basculement
  • Optimisation de performance pour diverses configurations matérielles

Ce système complet transforme la récupération d'information système de base en une plateforme de gestion et surveillance d'appareils de niveau entreprise avec analytique avancée, rapports de conformité et capacités de gestion de flotte.

Gestion de Stockage d'Entreprise sur macOS

Surveillez et optimisez le stockage de vos appareils MacFleet en utilisant l'analyse avancée d'utilisation du disque, les politiques de nettoyage automatisées et la gestion complète de stockage. Ce tutoriel fournit des outils de niveau entreprise pour implémenter les politiques de stockage organisationnelles et l'optimisation de stockage à l'échelle de la flotte.

Comprendre la Gestion de Stockage macOS

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

  • du - Analyse d'utilisation de répertoires et consommation d'espace
  • df - Espace disque libre et informations du système de fichiers
  • diskutil - Utilitaire de disque pour opérations avancées de disque
  • tmutil - Utilitaire Time Machine pour stockage de sauvegarde
  • Gestion de Stockage - Interface d'optimisation de stockage graphique

Opérations de Stockage de Base

Vérifier l'Utilisation de Stockage des Utilisateurs

#!/bin/bash

# Vérifier l'utilisation du disque pour tous les utilisateurs
echo "=== Utilisation de Stockage des Utilisateurs ==="
sudo du -hxd1 /Users

echo "Vérification d'utilisation de stockage terminée"

Vérifier l'Utilisation du Système de Fichiers

#!/bin/bash

# Vérifier l'utilisation globale du système de fichiers
echo "=== Utilisation du Système de Fichiers ==="
df -h

# Vérifier un système de fichiers spécifique
# df -h /dev/disk1s1

echo "Vérification d'utilisation du système de fichiers terminée"

Vérifier l'Utilisation du Répertoire Actuel

#!/bin/bash

# Vérifier l'utilisation du répertoire actuel
echo "=== Utilisation du Répertoire Actuel ==="
du -sh *

echo "Vérification d'utilisation du répertoire terminée"

Système de Gestion de Stockage d'Entreprise

#!/bin/bash

# Système de Gestion de Stockage d'Entreprise MacFleet
# Surveillance complète de stockage, optimisation et gestion de politiques

# Configuration
MACFLEET_DIR="/etc/macfleet"
STORAGE_DIR="$MACFLEET_DIR/storage_management"
REPORTS_DIR="$MACFLEET_DIR/reports"
COMPLIANCE_DIR="$MACFLEET_DIR/compliance"
AUDIT_DIR="$MACFLEET_DIR/audit"
LOG_FILE="/var/log/macfleet_storage_management.log"
POLICIES_DIR="$MACFLEET_DIR/storage_policies"
CLEANUP_DIR="$MACFLEET_DIR/cleanup_logs"

# Créer la structure de répertoires
create_directories() {
    local dirs=("$MACFLEET_DIR" "$STORAGE_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$POLICIES_DIR" "$CLEANUP_DIR")
    for dir in "${dirs[@]}"; do
        [[ ! -d "$dir" ]] && mkdir -p "$dir"
    done
}

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

# Catégories de Stockage pour la Gestion d'Entreprise
declare -A STORAGE_CATEGORIES=(
    ["system_critical"]="macOS,system_apps,kernel_extensions,system_logs"
    ["user_data"]="documents,downloads,desktop,pictures,movies"
    ["application_data"]="app_support,caches,preferences,saved_states"
    ["development"]="xcode,simulators,build_artifacts,source_code"
    ["media_content"]="photos,videos,music,podcasts"
    ["temporary_files"]="caches,logs,trash,temp_downloads"
    ["backup_data"]="time_machine,local_snapshots,manual_backups"
)

# Politiques de Stockage pour Différents Environnements
declare -A STORAGE_POLICIES=(
    ["aggressive_cleanup"]="clear_caches,remove_logs_7days,empty_trash,remove_downloads_30days"
    ["conservative_cleanup"]="clear_caches,remove_logs_30days,archive_old_files"
    ["development_optimized"]="preserve_builds,clear_simulator_data,optimize_xcode_cache"
    ["media_optimized"]="compress_videos,optimize_photos,remove_duplicates"
    ["security_focused"]="secure_delete,encrypt_backups,audit_sensitive_files"
    ["compliance_strict"]="retain_all,encrypt_storage,detailed_logging,no_auto_delete"
)

# Seuils d'Espace Disque pour Différents Niveaux d'Alerte
declare -A ALERT_THRESHOLDS=(
    ["critical"]=5     # Moins de 5GB libres
    ["warning"]=10     # Moins de 10GB libres
    ["low"]=20         # Moins de 20GB libres
    ["optimal"]=50     # Moins de 50GB libres
)

# Analyse complète de stockage
analyze_storage_comprehensive() {
    local analysis_level="$1"
    local output_file="$STORAGE_DIR/storage_analysis_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Démarrage de l'analyse complète de stockage : $analysis_level"
    
    # Obtenir les informations de base du système de fichiers
    local total_space=$(df -h / | awk 'NR==2 {print $2}')
    local used_space=$(df -h / | awk 'NR==2 {print $3}')
    local available_space=$(df -h / | awk 'NR==2 {print $4}')
    local usage_percentage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
    
    # Convertir en octets pour les calculs
    local available_gb=$(df -g / | awk 'NR==2 {print $4}')
    
    # Déterminer le niveau d'alerte
    local alert_level="optimal"
    if [[ $available_gb -lt ${ALERT_THRESHOLDS["critical"]} ]]; then
        alert_level="critical"
    elif [[ $available_gb -lt ${ALERT_THRESHOLDS["warning"]} ]]; then
        alert_level="warning"
    elif [[ $available_gb -lt ${ALERT_THRESHOLDS["low"]} ]]; then
        alert_level="low"
    fi
    
    # Analyser les répertoires utilisateurs
    local user_data=""
    while IFS= read -r user_dir; do
        if [[ -d "$user_dir" && ! "$user_dir" =~ (Shared|.localized)$ ]]; then
            local user_name=$(basename "$user_dir")
            local user_size=$(du -sg "$user_dir" 2>/dev/null | awk '{print $1}' || echo "0")
            user_data="$user_data{\"user\":\"$user_name\",\"size_gb\":$user_size},"
        fi
    done <<< "$(find /Users -maxdepth 1 -type d)"
    
    # Supprimer la virgule finale
    user_data="${user_data%,}"
    
    # Analyser les grands répertoires
    local large_dirs=""
    if [[ "$analysis_level" == "detailed" || "$analysis_level" == "full" ]]; then
        while IFS= read -r dir_info; do
            local size=$(echo "$dir_info" | awk '{print $1}')
            local path=$(echo "$dir_info" | awk '{$1=""; print substr($0,2)}')
            [[ $size -gt 1 ]] && large_dirs="$large_dirs{\"path\":\"$path\",\"size_gb\":$size},"
        done <<< "$(sudo du -sg /Applications /Library /System /Users 2>/dev/null | sort -nr)"
        large_dirs="${large_dirs%,}"
    fi
    
    # Analyser les caches système et fichiers temporaires
    local temp_data=""
    local cache_size=$(du -sg ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
    local log_size=$(du -sg /var/log 2>/dev/null | awk '{print $1}' || echo "0")
    local trash_size=$(du -sg ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
    
    temp_data="{\"caches_gb\":$cache_size,\"logs_gb\":$log_size,\"trash_gb\":$trash_size}"
    
    # Créer un rapport complet
    cat > "$output_file" << EOF
{
  "storage_analysis": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "analysis_level": "$analysis_level",
    "alert_level": "$alert_level",
    "filesystem_info": {
      "total_space": "$total_space",
      "used_space": "$used_space",
      "available_space": "$available_space",
      "usage_percentage": $usage_percentage,
      "available_gb": $available_gb
    },
    "user_breakdown": [$user_data],
    "large_directories": [$large_dirs],
    "temporary_files": $temp_data
  },
  "recommendations": [
    $([ $alert_level == "critical" ] && echo "\"Nettoyage immédiat requis - niveau de stockage critique\",")
    $([ $alert_level == "warning" ] && echo "\"Nettoyage de stockage recommandé\",")
    $([ $cache_size -gt 5 ] && echo "\"Vider les caches d'application ($cache_size GB)\",")
    $([ $trash_size -gt 1 ] && echo "\"Vider la corbeille ($trash_size GB)\",")
    $([ $log_size -gt 2 ] && echo "\"Archiver les anciens fichiers de log ($log_size GB)\",")
    "\"Surveillance régulière du stockage recommandée\""
  ]
}
EOF
    
    log_action "Analyse de stockage terminée. Rapport : $output_file"
    
    # Alerte si critique
    if [[ "$alert_level" == "critical" ]]; then
        log_action "ALERTE CRITIQUE : Espace de stockage critique ($available_gb GB restants)"
        # Envoyer notification d'alerte
        osascript -e "display notification \"Espace de stockage critique : $available_gb GB restants\" with title \"Alerte Stockage MacFleet\""
    fi
    
    echo "$output_file"
}

# Nettoyage avancé de stockage avec politiques
perform_storage_cleanup() {
    local cleanup_policy="$1"
    local dry_run="${2:-false}"
    local cleanup_report="$CLEANUP_DIR/cleanup_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Démarrage du nettoyage de stockage avec politique : $cleanup_policy (dry_run: $dry_run)"
    
    local total_freed=0
    local operations=""
    
    case "$cleanup_policy" in
        "aggressive_cleanup")
            # Vider les caches d'application
            if [[ "$dry_run" == "false" ]]; then
                local cache_size_before=$(du -sg ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
                find ~/Library/Caches -type f -mtime +1 -delete 2>/dev/null
                local cache_size_after=$(du -sg ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
                local cache_freed=$((cache_size_before - cache_size_after))
                total_freed=$((total_freed + cache_freed))
                operations="$operations{\"operation\":\"clear_caches\",\"freed_gb\":$cache_freed},"
            fi
            
            # Supprimer les anciens logs (7 jours)
            if [[ "$dry_run" == "false" ]]; then
                local log_size_before=$(du -sg ~/Library/Logs 2>/dev/null | awk '{print $1}' || echo "0")
                find ~/Library/Logs -type f -mtime +7 -delete 2>/dev/null
                local log_size_after=$(du -sg ~/Library/Logs 2>/dev/null | awk '{print $1}' || echo "0")
                local log_freed=$((log_size_before - log_size_after))
                total_freed=$((total_freed + log_freed))
                operations="$operations{\"operation\":\"remove_old_logs\",\"freed_gb\":$log_freed},"
            fi
            
            # Vider la corbeille
            if [[ "$dry_run" == "false" ]]; then
                local trash_size=$(du -sg ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
                rm -rf ~/.Trash/*
                total_freed=$((total_freed + trash_size))
                operations="$operations{\"operation\":\"empty_trash\",\"freed_gb\":$trash_size},"
            fi
            ;;
            
        "development_optimized")
            # Vider les données dérivées Xcode
            if [[ -d ~/Library/Developer/Xcode/DerivedData && "$dry_run" == "false" ]]; then
                local derived_size=$(du -sg ~/Library/Developer/Xcode/DerivedData 2>/dev/null | awk '{print $1}' || echo "0")
                rm -rf ~/Library/Developer/Xcode/DerivedData/*
                total_freed=$((total_freed + derived_size))
                operations="$operations{\"operation\":\"clear_xcode_derived_data\",\"freed_gb\":$derived_size},"
            fi
            
            # Vider les données du simulateur iOS
            if [[ -d ~/Library/Developer/CoreSimulator && "$dry_run" == "false" ]]; then
                local sim_size_before=$(du -sg ~/Library/Developer/CoreSimulator 2>/dev/null | awk '{print $1}' || echo "0")
                xcrun simctl delete unavailable
                local sim_size_after=$(du -sg ~/Library/Developer/CoreSimulator 2>/dev/null | awk '{print $1}' || echo "0")
                local sim_freed=$((sim_size_before - sim_size_after))
                total_freed=$((total_freed + sim_freed))
                operations="$operations{\"operation\":\"cleanup_simulator_data\",\"freed_gb\":$sim_freed},"
            fi
            ;;
    esac
    
    # Supprimer la virgule finale
    operations="${operations%,}"
    
    # Créer un rapport de nettoyage
    cat > "$cleanup_report" << EOF
{
  "cleanup_report": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "policy": "$cleanup_policy",
    "dry_run": "$dry_run",
    "total_freed_gb": $total_freed,
    "operations": [$operations]
  },
  "storage_after_cleanup": {
    "available_space": "$(df -h / | awk 'NR==2 {print $4}')",
    "usage_percentage": "$(df -h / | awk 'NR==2 {print $5}')"
  }
}
EOF
    
    if [[ "$dry_run" == "false" ]]; then
        log_action "Nettoyage terminé. Espace total libéré : ${total_freed}GB"
    else
        log_action "Test à blanc terminé. Libérerait approximativement : ${total_freed}GB"
    fi
    
    echo "$cleanup_report"
}

# Surveillance et alerte de stockage
monitor_storage_continuously() {
    local monitoring_interval="${1:-300}"  # 5 minutes par défaut
    local alert_threshold="${2:-10}"       # 10GB par défaut
    
    log_action "Démarrage de la surveillance continue de stockage (intervalle : ${monitoring_interval}s, seuil : ${alert_threshold}GB)"
    
    while true; do
        local available_gb=$(df -g / | awk 'NR==2 {print $4}')
        local usage_percent=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
        
        if [[ $available_gb -lt $alert_threshold ]]; then
            log_action "ALERTE STOCKAGE : Seulement ${available_gb}GB restants (${usage_percent}% utilisés)"
            
            # Envoyer notification système
            osascript -e "display notification \"Stockage faible : ${available_gb}GB restants\" with title \"Moniteur Stockage MacFleet\""
            
            # Optionnellement déclencher le nettoyage automatique
            if [[ $available_gb -lt 5 ]]; then
                log_action "Déclenchement du nettoyage d'urgence..."
                perform_storage_cleanup "aggressive_cleanup" "false"
            fi
        fi
        
        # Enregistrer le statut actuel
        log_action "Statut stockage : ${available_gb}GB disponible (${usage_percent}% utilisé)"
        
        sleep "$monitoring_interval"
    done
}

# Fonction d'exécution principale
main() {
    create_directories
    
    case "${1:-}" in
        "analyze")
            analyze_storage_comprehensive "${2:-standard}"
            ;;
        "cleanup")
            perform_storage_cleanup "${2:-conservative_cleanup}" "${3:-false}"
            ;;
        "monitor")
            monitor_storage_continuously "${2:-300}" "${3:-10}"
            ;;
        "help"|*)
            echo "Système de Gestion de Stockage d'Entreprise MacFleet"
            echo ""
            echo "Utilisation : $0 <commande> [options]"
            echo ""
            echo "Commandes :"
            echo "  analyze [niveau]                     - Analyser le stockage (basic|standard|detailed|full)"
            echo "  cleanup <politique> [dry_run]       - Effectuer nettoyage (aggressive_cleanup|conservative_cleanup|development_optimized|media_optimized) [true|false]"
            echo "  monitor [intervalle] [seuil]         - Surveillance continue (intervalle en secondes, seuil en GB)"
            echo ""
            echo "Exemples :"
            echo "  $0 analyze detailed"
            echo "  $0 cleanup aggressive_cleanup false"
            echo "  $0 monitor 600 15"
            ;;
    esac
}

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

## Analyse et Surveillance de Stockage

Le système d'entreprise fournit une analyse complète de stockage :

| **Niveau d'Analyse** | **Portée** | **Détails** | **Cas d'Usage** |
|---|---|---|---|
| **Basic** | Utilisation globale du disque | Vérification rapide d'espace | Surveillance quotidienne |
| **Standard** | Répartition utilisateur et système | Modèles d'utilisation détaillés | Révisions hebdomadaires |
| **Detailed** | Analyse des grands répertoires | Inventaire complet | Audits mensuels |
| **Full** | Analyse complète du système | Rapports d'entreprise | Évaluations trimestrielles |

## Politiques de Nettoyage de Stockage

### Politique de Nettoyage Agressive

```bash
# Effectuer nettoyage agressif pour récupérer un maximum d'espace
./storage_manager.sh cleanup aggressive_cleanup false

# Test à blanc pour voir ce qui serait nettoyé
./storage_manager.sh cleanup aggressive_cleanup true

Nettoyage Optimisé pour le Développement

# Nettoyer les caches et données de build spécifiques au développement
./storage_manager.sh cleanup development_optimized false

Surveillance de Stockage d'Entreprise

Surveillance Continue

# Surveiller le stockage toutes les 5 minutes avec seuil de 10GB
./storage_manager.sh monitor 300 10

# Surveiller le stockage chaque heure avec seuil de 20GB
./storage_manager.sh monitor 3600 20

Alertes Automatisées

Le système fournit des alertes intelligentes :

  • Alerte Critique - Moins de 5GB restants
  • Alerte d'Avertissement - Moins de 10GB restants
  • Stockage Faible - Moins de 20GB restants
  • Optimal - Plus de 50GB restants

Considérations Importantes de Stockage

  • Chiffrement FileVault doit être activé pour la sécurité d'entreprise
  • Sauvegardes Time Machine nécessitent un stockage externe adéquat
  • Instantanés APFS consomment du stockage et doivent être surveillés
  • Caches d'application peuvent grossir et nécessitent un nettoyage régulier
  • Éducation des utilisateurs aide à maintenir une utilisation optimale du stockage

Conformité et Gouvernance

Le système d'entreprise supporte diverses frameworks de conformité :

  • Conformité GDPR - Rétention de données et suppression sécurisée
  • Exigences HIPAA - Sécurité de stockage de données de santé
  • Conformité SOX - Contrôles de stockage de données financières
  • ISO 27001 - Gestion de sécurité de stockage d'information

Ce système complet transforme les commandes de base d'utilisation du disque en une plateforme de gestion de stockage de niveau entreprise avec surveillance avancée, optimisation automatisée et capacités de gestion de flotte.

Configurer Stage Manager sur les appareils macOS

Stage Manager est une fonctionnalité puissante de gestion des fenêtres introduite dans macOS Ventura qui aide les utilisateurs à organiser et se concentrer sur leur travail en regroupant les fenêtres et en masquant les applications inactives. Ce tutoriel vous montre comment gérer les paramètres de Stage Manager dans votre flotte Mac à l'aide de scripts shell.

Qu'est-ce que Stage Manager ?

Stage Manager est un système de gestion de fenêtres qui :

  • Organise les fenêtres en groupes focalisés sur le bureau
  • Réduit l'encombrement visuel en masquant les applications inactives
  • Améliore la productivité en permettant aux utilisateurs de basculer entre différents contextes de travail
  • Prend en charge les écrans externes avec des contrôles Stage Manager indépendants
  • S'intègre avec Mission Control pour une gestion améliorée des fenêtres

Prérequis et compatibilité

Configuration système requise

  • macOS 13.0 (Ventura) ou ultérieur - Stage Manager n'est pas disponible sur les versions antérieures
  • Appareils pris en charge : Ordinateurs Mac avec Apple Silicon (M1, M2, M3, M4) ou processeurs Intel
  • Privilèges administrateur pour l'exécution de scripts

Compatibilité matérielle

Stage Manager fonctionne mieux sur :

  • MacBook Pro et MacBook Air (2018 ou ultérieur)
  • iMac (2019 ou ultérieur)
  • Mac Studio (tous les modèles)
  • Mac Pro (2019 ou ultérieur)
  • Mac mini (2018 ou ultérieur)

Gestion de base de Stage Manager

Activer Stage Manager

#!/bin/bash

# Script pour activer Stage Manager sur macOS
CurrentUser=$(ls -l /dev/console | awk '/ / { print $3 }')
CurrentUserUID=$(id -u "$CurrentUser")

echo "Activation de Stage Manager MacFleet"
echo "Utilisateur actuel : $CurrentUser"
echo "UID de l'utilisateur actuel : $CurrentUserUID"

# Activer Stage Manager globalement
launchctl asuser $CurrentUserUID sudo -iu "$CurrentUser" defaults write com.apple.WindowManager GloballyEnabled -bool true

echo "✅ Stage Manager a été activé pour l'utilisateur $CurrentUser"
echo "Les changements prendront effet après la prochaine connexion ou le redémarrage du gestionnaire de fenêtres"

Désactiver Stage Manager

#!/bin/bash

# Script pour désactiver Stage Manager sur macOS
CurrentUser=$(ls -l /dev/console | awk '/ / { print $3 }')
CurrentUserUID=$(id -u "$CurrentUser")

echo "Désactivation de Stage Manager MacFleet"
echo "Utilisateur actuel : $CurrentUser"
echo "UID de l'utilisateur actuel : $CurrentUserUID"

# Désactiver Stage Manager globalement
launchctl asuser $CurrentUserUID sudo -iu "$CurrentUser" defaults write com.apple.WindowManager GloballyEnabled -bool false

echo "❌ Stage Manager a été désactivé pour l'utilisateur $CurrentUser"
echo "Les changements prendront effet après la prochaine connexion ou le redémarrage du gestionnaire de fenêtres"

Configuration avancée de Stage Manager

Script de gestion complet de Stage Manager

#!/bin/bash

# Gestion avancée de Stage Manager pour flotte Mac
DEVICE_NAME=$(scutil --get ComputerName)
CURRENT_USER=$(ls -l /dev/console | awk '/ / { print $3 }')
CURRENT_USER_UID=$(id -u "$CURRENT_USER")
MACOS_VERSION=$(sw_vers -productVersion)
LOG_FILE="/var/log/macfleet_stage_manager.log"

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

# Fonction pour vérifier la compatibilité de la version macOS
check_compatibility() {
    local major_version=$(echo "$MACOS_VERSION" | cut -d. -f1)
    local minor_version=$(echo "$MACOS_VERSION" | cut -d. -f2)
    
    if [ "$major_version" -ge 13 ]; then
        echo "✅ macOS $MACOS_VERSION est compatible avec Stage Manager"
        return 0
    else
        echo "❌ macOS $MACOS_VERSION n'est pas compatible avec Stage Manager (nécessite 13.0+)"
        return 1
    fi
}

# Fonction pour obtenir le statut actuel de Stage Manager
get_stage_manager_status() {
    local status=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults read com.apple.WindowManager GloballyEnabled 2>/dev/null)
    case "$status" in
        1) echo "activé" ;;
        0) echo "désactivé" ;;
        *) echo "indéfini" ;;
    esac
}

# Fonction pour activer Stage Manager
enable_stage_manager() {
    launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool true
    log_message "Stage Manager activé sur $DEVICE_NAME pour l'utilisateur $CURRENT_USER"
}

# Fonction pour désactiver Stage Manager
disable_stage_manager() {
    launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool false
    log_message "Stage Manager désactivé sur $DEVICE_NAME pour l'utilisateur $CURRENT_USER"
}

# Fonction pour configurer la visibilité des applications récentes
configure_recent_apps() {
    local show_recent="$1"
    
    if [ "$show_recent" = "true" ]; then
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool false
        log_message "Visibilité des applications récentes activée"
        echo "✅ Les applications récentes seront visibles sur le côté gauche"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool true
        log_message "Visibilité des applications récentes désactivée"
        echo "❌ Les applications récentes seront masquées"
    fi
}

# Fonction pour configurer le comportement de regroupement des fenêtres
configure_window_grouping() {
    local grouping_mode="$1"
    
    case "$grouping_mode" in
        "all_at_once")
            launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool false
            log_message "Regroupement de fenêtres défini sur 'Toutes à la fois'"
            echo "✅ Regroupement de fenêtres : Toutes à la fois"
            ;;
        "one_at_time")
            launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
            log_message "Regroupement de fenêtres défini sur 'Une à la fois'"
            echo "✅ Regroupement de fenêtres : Une à la fois"
            ;;
        *)
            echo "❌ Mode de regroupement invalide. Utilisez 'all_at_once' ou 'one_at_time'"
            return 1
            ;;
    esac
}

# Fonction pour redémarrer le gestionnaire de fenêtres
restart_window_manager() {
    launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" killall WindowManager 2>/dev/null
    sleep 2
    log_message "Gestionnaire de fenêtres redémarré pour l'utilisateur $CURRENT_USER"
}

# Fonction pour valider la configuration de Stage Manager
validate_configuration() {
    local expected_state="$1"
    local current_state=$(get_stage_manager_status)
    
    if [ "$current_state" = "$expected_state" ]; then
        echo "✅ Validation de la configuration réussie : Stage Manager est $expected_state"
        return 0
    else
        echo "❌ Échec de la validation de la configuration : Attendu $expected_state, obtenu $current_state"
        return 1
    fi
}

# Exécution principale
echo "Configuration de Stage Manager MacFleet"
echo "======================================"
echo "Appareil : $DEVICE_NAME"
echo "Utilisateur : $CURRENT_USER"
echo "Version macOS : $MACOS_VERSION"
echo ""

log_message "Début de la configuration de Stage Manager sur $DEVICE_NAME"

# Vérifier la compatibilité
if ! check_compatibility; then
    log_message "Configuration de Stage Manager abandonnée en raison de problèmes de compatibilité"
    exit 1
fi

# Afficher le statut actuel
echo "Statut actuel de Stage Manager : $(get_stage_manager_status)"
echo ""

# Options de configuration (décommentez selon les besoins)
# enable_stage_manager
# disable_stage_manager
# configure_recent_apps "true"
# configure_window_grouping "all_at_once"
# restart_window_manager

log_message "Configuration de Stage Manager terminée"

Configuration interactive de Stage Manager

#!/bin/bash

# Outil de configuration interactive de Stage Manager
CURRENT_USER=$(ls -l /dev/console | awk '/ / { print $3 }')
CURRENT_USER_UID=$(id -u "$CURRENT_USER")
MACOS_VERSION=$(sw_vers -productVersion)

# Fonction pour obtenir le statut actuel de Stage Manager
get_stage_manager_status() {
    local status=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults read com.apple.WindowManager GloballyEnabled 2>/dev/null)
    case "$status" in
        1) echo "activé" ;;
        0) echo "désactivé" ;;
        *) echo "non configuré" ;;
    esac
}

# Fonction pour obtenir le paramètre des applications récentes
get_recent_apps_status() {
    local status=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults read com.apple.WindowManager AutoHide 2>/dev/null)
    case "$status" in
        1) echo "masquées" ;;
        0) echo "visibles" ;;
        *) echo "non configuré" ;;
    esac
}

# Fonction pour obtenir le paramètre de regroupement des fenêtres
get_window_grouping_status() {
    local status=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults read com.apple.WindowManager AppWindowGroupingBehavior 2>/dev/null)
    case "$status" in
        1) echo "une à la fois" ;;
        0) echo "toutes à la fois" ;;
        *) echo "non configuré" ;;
    esac
}

# Fonction pour afficher la configuration actuelle
display_current_config() {
    echo "Configuration actuelle de Stage Manager :"
    echo "========================================"
    echo "Stage Manager : $(get_stage_manager_status)"
    echo "Applications récentes : $(get_recent_apps_status)"
    echo "Regroupement de fenêtres : $(get_window_grouping_status)"
    echo ""
}

# Menu interactif principal
echo "Configuration interactive de Stage Manager MacFleet"
echo "==================================================="
echo "Appareil : $(scutil --get ComputerName)"
echo "Utilisateur : $CURRENT_USER"
echo "Version macOS : $MACOS_VERSION"
echo ""

# Vérifier la compatibilité
major_version=$(echo "$MACOS_VERSION" | cut -d. -f1)
if [ "$major_version" -lt 13 ]; then
    echo "❌ Stage Manager nécessite macOS 13.0 ou ultérieur"
    echo "Version actuelle : $MACOS_VERSION"
    exit 1
fi

display_current_config

echo "Options de configuration :"
echo "1. Activer Stage Manager"
echo "2. Désactiver Stage Manager"
echo "3. Afficher les applications récentes"
echo "4. Masquer les applications récentes"
echo "5. Définir le regroupement de fenêtres sur 'Toutes à la fois'"
echo "6. Définir le regroupement de fenêtres sur 'Une à la fois'"
echo "7. Appliquer les paramètres recommandés"
echo "8. Réinitialiser aux valeurs par défaut"
echo "9. Afficher la configuration actuelle"
echo "0. Quitter"
echo ""

read -p "Entrez votre choix (0-9) : " choice

case $choice in
    1)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool true
        echo "✅ Stage Manager activé"
        ;;
    2)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool false
        echo "❌ Stage Manager désactivé"
        ;;
    3)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool false
        echo "✅ Les applications récentes seront visibles"
        ;;
    4)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool true
        echo "❌ Les applications récentes seront masquées"
        ;;
    5)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool false
        echo "✅ Regroupement de fenêtres défini sur 'Toutes à la fois'"
        ;;
    6)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
        echo "✅ Regroupement de fenêtres défini sur 'Une à la fois'"
        ;;
    7)
        # Appliquer les paramètres d'entreprise recommandés
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool true
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool false
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool false
        echo "✅ Paramètres d'entreprise recommandés appliqués"
        ;;
    8)
        # Réinitialiser aux valeurs par défaut du système
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults delete com.apple.WindowManager GloballyEnabled 2>/dev/null
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults delete com.apple.WindowManager AutoHide 2>/dev/null
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults delete com.apple.WindowManager AppWindowGroupingBehavior 2>/dev/null
        echo "✅ Réinitialisé aux valeurs par défaut du système"
        ;;
    9)
        display_current_config
        ;;
    0)
        echo "Sortie..."
        exit 0
        ;;
    *)
        echo "Choix invalide. Veuillez réessayer."
        ;;
esac

echo ""
echo "Configuration mise à jour. Les changements peuvent nécessiter une déconnexion/reconnexion pour prendre pleinement effet."
echo "Vous pouvez vérifier les changements dans Réglages Système > Bureau et Dock > Stage Manager."

Scripts de déploiement d'entreprise

Configuration en lot de Stage Manager

#!/bin/bash

# Script de déploiement d'entreprise de Stage Manager
COMPANY_NAME="MacFleet"
DEPLOYMENT_DATE=$(date +"%Y-%m-%d")
LOG_FILE="/var/log/macfleet_stage_manager_deployment.log"
REPORT_FILE="/tmp/stage_manager_deployment_report_$(date +%Y%m%d_%H%M%S).txt"

# Paramètres de configuration
STAGE_MANAGER_ENABLED=true
RECENT_APPS_VISIBLE=true
WINDOW_GROUPING_MODE="all_at_once"  # Options : "all_at_once" ou "one_at_time"
RESTART_WINDOW_MANAGER=true

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

# Fonction pour vérifier la compatibilité macOS
check_macos_compatibility() {
    local macos_version=$(sw_vers -productVersion)
    local major_version=$(echo "$macos_version" | cut -d. -f1)
    
    if [ "$major_version" -ge 13 ]; then
        log_message "macOS $macos_version est compatible avec Stage Manager"
        return 0
    else
        log_message "macOS $macos_version n'est pas compatible avec Stage Manager"
        return 1
    fi
}

# Fonction pour obtenir les informations de l'appareil
get_device_info() {
    local device_name=$(scutil --get ComputerName)
    local device_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    local macos_version=$(sw_vers -productVersion)
    local current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local hardware_model=$(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)
    
    echo "Appareil : $device_name"
    echo "Série : $device_serial"
    echo "Matériel : $hardware_model"
    echo "macOS : $macos_version"
    echo "Utilisateur : $current_user"
}

# Fonction pour déployer la configuration de Stage Manager
deploy_stage_manager_config() {
    local current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local current_user_uid=$(id -u "$current_user")
    
    # Activer/désactiver Stage Manager
    if [ "$STAGE_MANAGER_ENABLED" = true ]; then
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager GloballyEnabled -bool true
        log_message "Stage Manager activé pour l'utilisateur $current_user"
        echo "✅ Stage Manager activé"
    else
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager GloballyEnabled -bool false
        log_message "Stage Manager désactivé pour l'utilisateur $current_user"
        echo "❌ Stage Manager désactivé"
    fi
    
    # Configurer la visibilité des applications récentes
    if [ "$RECENT_APPS_VISIBLE" = true ]; then
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AutoHide -bool false
        log_message "Visibilité des applications récentes activée"
        echo "✅ Les applications récentes seront visibles"
    else
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AutoHide -bool true
        log_message "Visibilité des applications récentes désactivée"
        echo "❌ Les applications récentes seront masquées"
    fi
    
    # Configurer le comportement de regroupement des fenêtres
    case "$WINDOW_GROUPING_MODE" in
        "all_at_once")
            launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool false
            log_message "Regroupement de fenêtres défini sur 'Toutes à la fois'"
            echo "✅ Regroupement de fenêtres : Toutes à la fois"
            ;;
        "one_at_time")
            launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
            log_message "Regroupement de fenêtres défini sur 'Une à la fois'"
            echo "✅ Regroupement de fenêtres : Une à la fois"
            ;;
    esac
    
    # Redémarrer le gestionnaire de fenêtres si demandé
    if [ "$RESTART_WINDOW_MANAGER" = true ]; then
        launchctl asuser $current_user_uid sudo -iu "$current_user" killall WindowManager 2>/dev/null
        sleep 2
        log_message "Gestionnaire de fenêtres redémarré"
        echo "🔄 Gestionnaire de fenêtres redémarré"
    fi
}

# Fonction pour valider le déploiement
validate_deployment() {
    local current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local current_user_uid=$(id -u "$current_user")
    
    local stage_manager_status=$(launchctl asuser $current_user_uid sudo -iu "$current_user" defaults read com.apple.WindowManager GloballyEnabled 2>/dev/null)
    local recent_apps_status=$(launchctl asuser $current_user_uid sudo -iu "$current_user" defaults read com.apple.WindowManager AutoHide 2>/dev/null)
    local window_grouping_status=$(launchctl asuser $current_user_uid sudo -iu "$current_user" defaults read com.apple.WindowManager AppWindowGroupingBehavior 2>/dev/null)
    
    local validation_success=true
    
    # Valider le statut de Stage Manager
    if [ "$STAGE_MANAGER_ENABLED" = true ] && [ "$stage_manager_status" = "1" ]; then
        echo "✅ Validation de Stage Manager : RÉUSSIE"
    elif [ "$STAGE_MANAGER_ENABLED" = false ] && [ "$stage_manager_status" = "0" ]; then
        echo "✅ Validation de Stage Manager : RÉUSSIE"
    else
        echo "❌ Validation de Stage Manager : ÉCHOUÉE"
        validation_success=false
    fi
    
    # Valider le paramètre des applications récentes
    if [ "$RECENT_APPS_VISIBLE" = true ] && [ "$recent_apps_status" = "0" ]; then
        echo "✅ Validation des applications récentes : RÉUSSIE"
    elif [ "$RECENT_APPS_VISIBLE" = false ] && [ "$recent_apps_status" = "1" ]; then
        echo "✅ Validation des applications récentes : RÉUSSIE"
    else
        echo "❌ Validation des applications récentes : ÉCHOUÉE"
        validation_success=false
    fi
    
    if [ "$validation_success" = true ]; then
        log_message "Validation du déploiement réussie"
        return 0
    else
        log_message "Validation du déploiement échouée"
        return 1
    fi
}

# Processus principal de déploiement
echo "Déploiement de Stage Manager $COMPANY_NAME" > "$REPORT_FILE"
echo "===========================================" >> "$REPORT_FILE"
echo "Date : $DEPLOYMENT_DATE" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

get_device_info >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

log_message "Début du déploiement de Stage Manager"
echo "Début du déploiement..." >> "$REPORT_FILE"

# Vérifier la compatibilité macOS
if ! check_macos_compatibility; then
    echo "Statut : ÉCHEC - Version macOS incompatible" >> "$REPORT_FILE"
    log_message "Déploiement abandonné en raison de la compatibilité macOS"
    exit 1
fi

# Déployer la configuration
deploy_stage_manager_config

# Valider le déploiement
if validate_deployment; then
    echo "Statut : SUCCÈS" >> "$REPORT_FILE"
else
    echo "Statut : ÉCHEC" >> "$REPORT_FILE"
fi

log_message "Déploiement terminé"
echo "Déploiement terminé. Rapport sauvegardé dans : $REPORT_FILE"
cat "$REPORT_FILE"

Meilleures pratiques pour la gestion de Stage Manager

1. Formation et adoption des utilisateurs

  • Fournir une formation complète sur les fonctionnalités de Stage Manager
  • Créer des guides utilisateur et de la documentation
  • Démontrer les avantages de productivité
  • Offrir des configurations personnalisées basées sur les rôles des utilisateurs

2. Standards de configuration

  • Définir des standards organisationnels pour les paramètres de Stage Manager
  • Créer différents profils pour différents types d'utilisateurs
  • Documenter les configurations approuvées
  • Implémenter des processus de gestion des changements

3. Considérations de performance

  • Surveiller l'impact sur les performances du système
  • Considérer les capacités matérielles lors de l'activation de Stage Manager
  • Tester les configurations sur différents types d'appareils
  • Fournir des options de retour en arrière

4. Intégration avec d'autres outils

  • Coordonner avec les outils de gestion de fenêtres existants
  • Considérer l'impact sur le partage d'écran et l'accès à distance
  • Tester avec les applications métier
  • Assurer la compatibilité avec les fonctionnalités d'accessibilité

Résolution des problèmes courants

Problème : Stage Manager non disponible

# Vérifier la version macOS
macos_version=$(sw_vers -productVersion)
echo "Version macOS : $macos_version"

# Vérifier si l'exécution se fait sur du matériel compatible
hardware_model=$(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)
echo "Modèle matériel : $hardware_model"

# Vérifier les exigences système
if [[ "$macos_version" < "13.0" ]]; then
    echo "❌ Stage Manager nécessite macOS 13.0 ou ultérieur"
fi

Problème : Les changements ne prennent pas effet

# Redémarrer le gestionnaire de fenêtres
current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
current_user_uid=$(id -u "$current_user")

launchctl asuser $current_user_uid sudo -iu "$current_user" killall WindowManager
sleep 3

# Vérifier le redémarrage du processus
if pgrep -x "WindowManager" > /dev/null; then
    echo "✅ Gestionnaire de fenêtres redémarré avec succès"
else
    echo "❌ Échec du redémarrage du gestionnaire de fenêtres"
fi

Problème : Permission refusée

# Vérifier les permissions utilisateur
current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
echo "Utilisateur actuel : $current_user"

# Vérifier le contexte utilisateur
id "$current_user"

# Vérifier si l'utilisateur a les permissions nécessaires
if groups "$current_user" | grep -q "admin"; then
    echo "✅ L'utilisateur a des privilèges administrateur"
else
    echo "❌ L'utilisateur n'a pas de privilèges administrateur"
fi

Problème : Les paramètres ne persistent pas

# Vérifier le fichier de préférences
current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
plist_file="/Users/$current_user/Library/Preferences/com.apple.WindowManager.plist"

if [ -f "$plist_file" ]; then
    echo "✅ Le fichier de préférences existe"
    ls -la "$plist_file"
else
    echo "❌ Fichier de préférences non trouvé"
fi

# Forcer la synchronisation des préférences
defaults synchronize

Analyse approfondie des fonctionnalités de Stage Manager

Comprendre les composants de Stage Manager

Stage Manager se compose de plusieurs composants clés :

  1. Groupes de fenêtres : Collections de fenêtres liées qui apparaissent ensemble
  2. Scène : Zone de travail principale où les groupes de fenêtres actifs sont affichés
  3. Applications récentes : Barre latérale montrant les applications récemment utilisées
  4. Support d'écran externe : Fonctionnement indépendant de Stage Manager sur les écrans externes

Options de configuration avancées

#!/bin/bash

# Options de configuration avancées de Stage Manager
CURRENT_USER=$(ls -l /dev/console | awk '/ / { print $3 }')
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configurer Stage Manager pour les écrans externes
configure_external_display_stage_manager() {
    local enable_external="$1"
    
    if [ "$enable_external" = "true" ]; then
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager StandardStageStripShowsFullDesktop -bool true
        echo "✅ Stage Manager pour écran externe activé"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager StandardStageStripShowsFullDesktop -bool false
        echo "❌ Stage Manager pour écran externe désactivé"
    fi
}

# Configurer la vitesse d'animation de Stage Manager
configure_animation_speed() {
    local speed="$1"  # Valeurs : 0.1 à 1.0
    
    if [[ "$speed" =~ ^[0-9]+\.?[0-9]*$ ]] && (( $(echo "$speed >= 0.1" | bc -l) )) && (( $(echo "$speed <= 1.0" | bc -l) )); then
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager StageManagerAnimationSpeed -float "$speed"
        echo "✅ Vitesse d'animation définie à $speed"
    else
        echo "❌ Vitesse d'animation invalide. Utilisez des valeurs entre 0.1 et 1.0"
    fi
}

# Configurer les raccourcis clavier de Stage Manager
configure_hotkeys() {
    local enable_hotkeys="$1"
    
    if [ "$enable_hotkeys" = "true" ]; then
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager EnableHotKeys -bool true
        echo "✅ Raccourcis clavier de Stage Manager activés"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager EnableHotKeys -bool false
        echo "❌ Raccourcis clavier de Stage Manager désactivés"
    fi
}

# Exemples d'utilisation
# configure_external_display_stage_manager "true"
# configure_animation_speed "0.5"
# configure_hotkeys "true"

Conclusion

Stage Manager est une fonctionnalité de productivité puissante qui peut considérablement améliorer les flux de travail de gestion des fenêtres lorsqu'elle est correctement configurée. Ce guide complet fournit :

  • Fonctionnalité d'activation/désactivation de base pour un déploiement rapide
  • Options de configuration avancées pour des expériences utilisateur personnalisées
  • Scripts de déploiement d'entreprise pour une gestion à grande échelle
  • Outils de surveillance et de reporting pour une gestion continue
  • Guides de dépannage pour les problèmes courants

L'implémentation régulière des pratiques de gestion de Stage Manager aidera à s'assurer que votre flotte Mac fournit une expérience utilisateur optimale tout en maintenant les standards organisationnels et les objectifs de productivité.

Pour une efficacité maximale, envisagez d'intégrer la configuration de Stage Manager avec vos outils existants de gestion de flotte Mac et vos programmes de formation utilisateur.

Gestion de l'indexation Spotlight sur les appareils macOS

Spotlight est la puissante fonctionnalité de recherche système de macOS qui aide les utilisateurs à localiser rapidement fichiers, documents, applications, emails et plus encore à travers leur système. Bien que Spotlight offre d'excellentes capacités de recherche, son indexation continue en arrière-plan peut parfois impacter les performances système, particulièrement sur du matériel plus ancien ou dans des environnements avec des ressources limitées. Ce guide complet fournit des méthodes pour gérer efficacement l'indexation Spotlight.

Comprendre Spotlight et son impact

Spotlight utilise un système d'indexation sophistiqué qui scanne et catalogue continuellement le contenu de votre Mac pour fournir des résultats de recherche instantanés. Ce processus d'indexation implique :

  • Analyse du contenu des fichiers : Lecture et indexation du texte dans les documents
  • Extraction de métadonnées : Catalogage des propriétés de fichiers, dates de création et étiquettes
  • Indexation des applications : Suivi des applications installées et de leurs données
  • Indexation email et messages : Indexation de Mail, Messages et autres apps de communication
  • Mises à jour en temps réel : Surveillance des changements du système de fichiers pour maintenir l'index à jour

Pourquoi gérer l'indexation Spotlight ?

Il y a plusieurs scénarios où la gestion de l'indexation Spotlight devient nécessaire :

  • Optimisation des performances : Réduction de l'utilisation CPU et disque sur les systèmes à ressources limitées
  • Préoccupations de confidentialité : Prévention de l'indexation de fichiers et répertoires sensibles
  • Gestion du stockage : Économie d'espace disque utilisé par les fichiers d'index
  • Dépannage : Résolution de problèmes de recherche ou d'index corrompus
  • Déploiement d'entreprise : Standardisation du comportement de recherche sur les appareils gérés
  • Environnements de développement : Prévention de l'indexation de répertoires de build et fichiers temporaires

Prérequis

Avant de gérer l'indexation Spotlight, assurez-vous d'avoir :

  • Privilèges administrateur sur le Mac
  • Accès Terminal ou SSH
  • Compréhension de l'impact sur la fonctionnalité de recherche
  • Sauvegarde des données importantes (recommandé)

Commandes de base de gestion Spotlight

Comprendre mdutil

La commande mdutil est l'outil principal pour gérer l'indexation Spotlight :

# Vérifier le statut d'indexation
mdutil -s /

# Activer l'indexation pour un volume
mdutil -i on /

# Désactiver l'indexation pour un volume
mdutil -i off /

# Effacer et reconstruire l'index
mdutil -E /

# Obtenir de l'aide
mdutil -h

Vérifier le statut d'indexation actuel

Avant de faire des changements, vérifiez le statut d'indexation actuel :

#!/bin/bash

# Vérifier le statut d'indexation Spotlight pour tous les volumes
echo "Rapport de statut d'indexation Spotlight"
echo "========================================"
echo "Date: $(date)"
echo ""

# Obtenir tous les volumes montés
volumes=$(df -h | grep "^/dev" | awk '{print $9}')

echo "Statut d'indexation des volumes:"
echo "--------------------------------"

for volume in $volumes; do
    if [ -d "$volume" ]; then
        status=$(mdutil -s "$volume" 2>/dev/null | grep "Indexing enabled")
        echo "$volume: $status"
    fi
done

echo ""
echo "Processus d'indexation actifs:"
ps aux | grep -i mds | grep -v grep

Désactiver l'indexation Spotlight

Script de base pour désactiver

Script simple pour désactiver l'indexation Spotlight sur le volume principal :

#!/bin/bash

# Désactiver l'indexation Spotlight sur le volume racine
echo "Désactivation de l'indexation Spotlight..."

if sudo mdutil -i off /; then
    echo "✓ Indexation Spotlight désactivée avec succès"
    
    # Vérifier le changement
    status=$(mdutil -s / | grep "Indexing enabled")
    echo "Statut actuel: $status"
else
    echo "✗ Échec de la désactivation de l'indexation Spotlight"
    exit 1
fi

echo "Note: La fonctionnalité de recherche sera limitée jusqu'à ce que l'indexation soit réactivée"

Script avancé de désactivation avec journalisation

Script plus complet avec journalisation et vérification :

#!/bin/bash

# Script avancé de désactivation Spotlight avec journalisation
LOG_FILE="/var/log/spotlight_management.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Fonction pour enregistrer les messages
log_message() {
    echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
}

# Fonction pour désactiver l'indexation d'un volume
disable_indexing() {
    local volume=$1
    
    log_message "Tentative de désactivation de l'indexation pour le volume: $volume"
    
    # Vérifier si le volume existe
    if [ ! -d "$volume" ]; then
        log_message "ERREUR: Le volume $volume n'existe pas"
        return 1
    fi
    
    # Vérifier le statut actuel
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    log_message "Statut actuel pour $volume: $current_status"
    
    # Désactiver l'indexation
    if sudo mdutil -i off "$volume"; then
        log_message "SUCCÈS: Indexation désactivée pour $volume"
        
        # Vérifier le changement
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        log_message "Nouveau statut pour $volume: $new_status"
        
        return 0
    else
        log_message "ERREUR: Échec de la désactivation de l'indexation pour $volume"
        return 1
    fi
}

# Exécution principale
log_message "Début du processus de désactivation de l'indexation Spotlight"

# Désactiver pour le volume racine
if disable_indexing "/"; then
    log_message "Indexation du volume racine désactivée avec succès"
else
    log_message "Échec de la désactivation de l'indexation du volume racine"
    exit 1
fi

log_message "Processus de désactivation de l'indexation Spotlight terminé"
echo "Processus terminé. Vérifiez le journal à: $LOG_FILE"

Désactivation par lot pour plusieurs volumes

Script pour désactiver l'indexation sur plusieurs volumes :

#!/bin/bash

# Désactivation par lot de l'indexation Spotlight pour plusieurs volumes
VOLUMES=(
    "/"
    "/Users"
    "/Applications"
    # Ajouter plus de volumes si nécessaire
)

echo "Désactivation par lot de l'indexation Spotlight"
echo "==============================================="
echo "Date: $(date)"
echo ""

successful=0
failed=0

for volume in "${VOLUMES[@]}"; do
    echo "Traitement du volume: $volume"
    
    if [ -d "$volume" ]; then
        if sudo mdutil -i off "$volume" 2>/dev/null; then
            echo "  ✓ Indexation désactivée avec succès pour $volume"
            ((successful++))
        else
            echo "  ✗ Échec de la désactivation de l'indexation pour $volume"
            ((failed++))
        fi
    else
        echo "  ⚠ Le volume $volume n'existe pas, ignoré"
    fi
done

echo ""
echo "Résumé:"
echo "-------"
echo "Désactivés avec succès: $successful volumes"
echo "Échecs: $failed volumes"

if [ $failed -gt 0 ]; then
    echo "Certaines opérations ont échoué. Vérifiez le statut de chaque volume manuellement."
    exit 1
fi

Suppression des fichiers d'index Spotlight

Script de nettoyage de base

Après avoir désactivé l'indexation, supprimez les fichiers d'index existants pour libérer de l'espace :

#!/bin/bash

# Supprimer les fichiers d'index Spotlight
echo "Suppression des fichiers d'index Spotlight..."

# Supprimer les répertoires .Spotlight-V100 (macOS moderne)
if sudo rm -rf /.Spotlight-V100; then
    echo "✓ Répertoire .Spotlight-V100 supprimé"
else
    echo "⚠ Aucun répertoire .Spotlight-V100 trouvé ou suppression échouée"
fi

# Supprimer les répertoires .Spotlight anciens
if sudo rm -rf /.Spotlight*; then
    echo "✓ Répertoires Spotlight anciens supprimés"
else
    echo "⚠ Aucun répertoire Spotlight ancien trouvé"
fi

# Calculer l'espace libéré
echo "Nettoyage de l'index Spotlight terminé"

Nettoyage avancé avec calcul de taille

Script de nettoyage plus détaillé qui montre les économies d'espace :

#!/bin/bash

# Nettoyage avancé d'index Spotlight avec rapport de taille
echo "Utilitaire de nettoyage d'index Spotlight"
echo "========================================="
echo "Date: $(date)"
echo ""

# Fonction pour obtenir la taille d'un répertoire
get_size() {
    local dir=$1
    if [ -d "$dir" ]; then
        du -sh "$dir" 2>/dev/null | cut -f1
    else
        echo "0B"
    fi
}

# Fonction pour supprimer les répertoires spotlight
cleanup_spotlight_dirs() {
    local base_path=$1
    local total_size=0
    
    echo "Nettoyage des répertoires Spotlight dans: $base_path"
    
    # Trouver tous les répertoires Spotlight
    spotlight_dirs=$(find "$base_path" -name ".Spotlight*" -type d 2>/dev/null)
    
    if [ -z "$spotlight_dirs" ]; then
        echo "  Aucun répertoire Spotlight trouvé"
        return 0
    fi
    
    for dir in $spotlight_dirs; do
        size=$(get_size "$dir")
        echo "  Trouvé: $dir ($size)"
        
        if sudo rm -rf "$dir"; then
            echo "    ✓ Supprimé avec succès"
        else
            echo "    ✗ Échec de la suppression"
        fi
    done
}

# Nettoyer les emplacements communs
cleanup_spotlight_dirs "/"
cleanup_spotlight_dirs "/Users"

# Nettoyer sur les volumes externes s'il y en a
for volume in /Volumes/*; do
    if [ -d "$volume" ]; then
        echo ""
        cleanup_spotlight_dirs "$volume"
    fi
done

echo ""
echo "Nettoyage de l'index Spotlight terminé"
echo "Exécutez 'df -h' pour voir l'utilisation de disque mise à jour"

Activer l'indexation Spotlight

Script d'activation de base

Script simple pour réactiver l'indexation Spotlight :

#!/bin/bash

# Activer l'indexation Spotlight sur le volume racine
echo "Activation de l'indexation Spotlight..."

if sudo mdutil -i on /; then
    echo "✓ Indexation Spotlight activée avec succès"
    
    # Vérifier le changement
    status=$(mdutil -s / | grep "Indexing enabled")
    echo "Statut actuel: $status"
    
    echo ""
    echo "Note: L'indexation commencera automatiquement et peut prendre du temps à se terminer"
    echo "Vous pouvez surveiller le progrès en utilisant la recherche Spotlight"
else
    echo "✗ Échec de l'activation de l'indexation Spotlight"
    exit 1
fi

Activation avancée avec surveillance du progrès

Script qui active l'indexation et fournit une surveillance du progrès :

#!/bin/bash

# Script avancé d'activation Spotlight avec surveillance du progrès
LOG_FILE="/var/log/spotlight_management.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Fonction pour enregistrer les messages
log_message() {
    echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
}

# Fonction pour surveiller le progrès de l'indexation
monitor_indexing() {
    local volume=$1
    local timeout=60  # Surveiller pendant 60 secondes
    local elapsed=0
    
    echo "Surveillance du progrès d'indexation pour $volume..."
    
    while [ $elapsed -lt $timeout ]; do
        # Vérifier si l'indexation est en cours
        if ps aux | grep -v grep | grep -q "mds_stores\|mdworker"; then
            echo "  Indexation en cours... (${elapsed}s écoulées)"
        else
            echo "  L'indexation peut être terminée ou en pause"
            break
        fi
        
        sleep 5
        elapsed=$((elapsed + 5))
    done
    
    if [ $elapsed -ge $timeout ]; then
        echo "  Délai de surveillance atteint. L'indexation peut encore être en cours."
    fi
}

# Fonction pour activer l'indexation d'un volume
enable_indexing() {
    local volume=$1
    
    log_message "Tentative d'activation de l'indexation pour le volume: $volume"
    
    # Vérifier si le volume existe
    if [ ! -d "$volume" ]; then
        log_message "ERREUR: Le volume $volume n'existe pas"
        return 1
    fi
    
    # Vérifier le statut actuel
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    log_message "Statut actuel pour $volume: $current_status"
    
    # Activer l'indexation
    if sudo mdutil -i on "$volume"; then
        log_message "SUCCÈS: Indexation activée pour $volume"
        
        # Vérifier le changement
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        log_message "Nouveau statut pour $volume: $new_status"
        
        # Surveiller le progrès initial
        monitor_indexing "$volume"
        
        return 0
    else
        log_message "ERREUR: Échec de l'activation de l'indexation pour $volume"
        return 1
    fi
}

# Exécution principale
log_message "Début du processus d'activation de l'indexation Spotlight"

# Activer pour le volume racine
if enable_indexing "/"; then
    log_message "Indexation du volume racine activée avec succès"
else
    log_message "Échec de l'activation de l'indexation du volume racine"
    exit 1
fi

log_message "Processus d'activation de l'indexation Spotlight terminé"
echo "Processus terminé. Vérifiez le journal à: $LOG_FILE"

Reconstruire l'index Spotlight

Script de reconstruction de base

Script pour reconstruire complètement l'index Spotlight :

#!/bin/bash

# Reconstruire l'index Spotlight
echo "Reconstruction de l'index Spotlight..."
echo "Attention: Ceci va effacer l'index actuel et le reconstruire depuis zéro"
echo ""

read -p "Continuer? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
    echo "Opération annulée"
    exit 0
fi

echo "Début de la reconstruction de l'index..."

if sudo mdutil -E /; then
    echo "✓ Reconstruction de l'index initiée avec succès"
    
    # Afficher le statut
    status=$(mdutil -s /)
    echo "Statut actuel: $status"
    
    echo ""
    echo "Le processus de reconstruction de l'index a commencé et continuera en arrière-plan"
    echo "Cela peut prendre plusieurs heures selon la quantité de données"
    echo "Vous pouvez surveiller le progrès en utilisant le Moniteur d'activité (cherchez les processus mds_stores et mdworker)"
else
    echo "✗ Échec de l'initiation de la reconstruction de l'index"
    exit 1
fi

Reconstruction avancée avec volumes sélectifs

Script pour reconstruire les index de volumes spécifiques :

#!/bin/bash

# Script avancé de reconstruction d'index Spotlight
VOLUMES=(
    "/"
    "/Users"
    # Ajouter des volumes spécifiques ou utiliser la découverte
)

AUTO_DISCOVER=${1:-false}

echo "Utilitaire de reconstruction d'index Spotlight"
echo "=============================================="
echo "Date: $(date)"
echo ""

# Fonction pour découvrir les volumes montés
discover_volumes() {
    echo "Découverte des volumes montés..."
    
    # Obtenir tous les volumes HFS+/APFS montés
    local discovered_volumes=()
    while IFS= read -r line; do
        volume=$(echo "$line" | awk '{print $9}')
        if [ -d "$volume" ] && [ "$volume" != "/dev" ]; then
            discovered_volumes+=("$volume")
        fi
    done < <(df -h | grep "^/dev")
    
    echo "Volumes découverts:"
    for vol in "${discovered_volumes[@]}"; do
        echo "  - $vol"
    done
    
    VOLUMES=("${discovered_volumes[@]}")
}

# Fonction pour reconstruire l'index d'un volume
rebuild_index() {
    local volume=$1
    
    echo "Reconstruction de l'index pour: $volume"
    
    # Vérifier si le volume existe et est monté
    if [ ! -d "$volume" ]; then
        echo "  ✗ Le volume $volume n'existe pas ou n'est pas monté"
        return 1
    fi
    
    # Afficher le statut actuel
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    echo "  Statut actuel: $current_status"
    
    # Reconstruire l'index
    if sudo mdutil -E "$volume"; then
        echo "  ✓ Reconstruction de l'index initiée pour $volume"
        
        # Afficher le nouveau statut
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        echo "  Nouveau statut: $new_status"
        
        return 0
    else
        echo "  ✗ Échec de la reconstruction de l'index pour $volume"
        return 1
    fi
}

# Auto-découverte des volumes si demandé
if [ "$AUTO_DISCOVER" = "true" ]; then
    discover_volumes
fi

echo "Volumes à reconstruire:"
for volume in "${VOLUMES[@]}"; do
    echo "  - $volume"
done

echo ""
read -p "Procéder à la reconstruction des index? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
    echo "Opération annulée"
    exit 0
fi

echo ""
echo "Début du processus de reconstruction d'index..."
echo ""

successful=0
failed=0

for volume in "${VOLUMES[@]}"; do
    if rebuild_index "$volume"; then
        ((successful++))
    else
        ((failed++))
    fi
    echo ""
done

echo "Résumé de reconstruction:"
echo "------------------------"
echo "Initiés avec succès: $successful volumes"
echo "Échecs: $failed volumes"
echo ""
echo "Note: La reconstruction d'index continuera en arrière-plan"
echo "Surveillez le progrès avec: ps aux | grep mds"

Gestion avancée de Spotlight

Exclusion sélective de répertoires

Script pour exclure des répertoires spécifiques de l'indexation :

#!/bin/bash

# Exclure des répertoires spécifiques de l'indexation Spotlight
EXCLUDE_DIRS=(
    "/tmp"
    "/var/tmp"
    "/private/tmp"
    "/Users/Shared/Build"
    # Ajouter plus de répertoires si nécessaire
)

echo "Gestionnaire d'exclusion de répertoires Spotlight"
echo "================================================="
echo ""

# Fonction pour ajouter un répertoire à la liste d'exclusion
exclude_directory() {
    local dir_path=$1
    
    echo "Exclusion du répertoire: $dir_path"
    
    # Vérifier si le répertoire existe
    if [ ! -d "$dir_path" ]; then
        echo "  ⚠ Le répertoire n'existe pas: $dir_path"
        return 1
    fi
    
    # Ajouter à la liste de confidentialité Spotlight en utilisant defaults
    if sudo defaults write /System/Library/CoreServices/Search.bundle/Contents/Resources/SpotlightExclusions.plist Exclusions -array-add "$dir_path"; then
        echo "  ✓ Ajouté à la liste d'exclusion"
        return 0
    else
        echo "  ✗ Échec de l'ajout à la liste d'exclusion"
        return 1
    fi
}

# Fonction pour afficher les exclusions actuelles
show_exclusions() {
    echo "Exclusions Spotlight actuelles:"
    echo "-------------------------------"
    
    # Lire depuis les préférences système
    if defaults read /System/Library/CoreServices/Search.bundle/Contents/Resources/SpotlightExclusions.plist Exclusions 2>/dev/null; then
        echo ""
    else
        echo "Aucune exclusion trouvée ou impossible de lire la liste d'exclusions"
    fi
}

# Afficher les exclusions actuelles
show_exclusions

echo ""
echo "Ajout de nouvelles exclusions..."

for dir in "${EXCLUDE_DIRS[@]}"; do
    exclude_directory "$dir"
done

echo ""
echo "Processus d'exclusion terminé"
echo "Redémarrez Spotlight pour que les changements prennent effet:"
echo "sudo killall mds && sudo mdutil -E /"

Script de surveillance des performances

Script pour surveiller l'impact de Spotlight sur les performances système :

#!/bin/bash

# Moniteur de performance Spotlight
DURATION=${1:-60}  # Surveiller pendant 60 secondes par défaut
INTERVAL=5

echo "Moniteur de performance Spotlight"
echo "================================="
echo "Durée de surveillance: ${DURATION} secondes"
echo "Intervalle d'échantillonnage: ${INTERVAL} secondes"
echo ""

# Fonction pour obtenir les statistiques des processus Spotlight
get_spotlight_stats() {
    local timestamp=$(date '+%H:%M:%S')
    
    # Obtenir les processus mds
    mds_stats=$(ps aux | grep -E "mds|mdworker" | grep -v grep | awk '{
        cpu += $3; 
        mem += $4; 
        count++
    } END {
        printf "Processus: %d, CPU: %.1f%%, Mémoire: %.1f%%", count, cpu, mem
    }')
    
    # Obtenir l'activité disque (si disponible)
    disk_activity=$(iostat -c 1 2>/dev/null | tail -1 | awk '{print "Disque: " $4 "% utilisation"}' || echo "Disque: N/A")
    
    echo "[$timestamp] $mds_stats, $disk_activity"
}

# En-tête
echo "Heure    | Statistiques Spotlight"
echo "---------|------------------------------------------------"

# Boucle de surveillance
elapsed=0
while [ $elapsed -lt $DURATION ]; do
    get_spotlight_stats
    sleep $INTERVAL
    elapsed=$((elapsed + INTERVAL))
done

echo ""
echo "Surveillance terminée"

# Afficher le résumé
echo ""
echo "Résumé final des processus:"
echo "--------------------------"
ps aux | grep -E "mds|mdworker" | grep -v grep | head -10

Automatisation et planification

Script de maintenance automatisée

Script pour la maintenance planifiée de Spotlight :

#!/bin/bash

# Script de maintenance automatisée Spotlight
# Peut être exécuté via cron ou launchd

CONFIG_FILE="/etc/spotlight_maintenance.conf"
LOG_FILE="/var/log/spotlight_maintenance.log"

# Configuration par défaut
REBUILD_INTERVAL=30  # jours
CLEANUP_TEMP=true
MONITOR_PERFORMANCE=true

# Fonction pour journaliser avec horodatage
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Charger la configuration si elle existe
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
    log_message "Configuration chargée depuis $CONFIG_FILE"
fi

# Fonction pour vérifier si une reconstruction est nécessaire
needs_rebuild() {
    local index_age_file="/var/db/.spotlight_last_rebuild"
    
    if [ ! -f "$index_age_file" ]; then
        return 0  # Aucun enregistrement, supposer qu'une reconstruction est nécessaire
    fi
    
    local last_rebuild=$(cat "$index_age_file")
    local current_time=$(date +%s)
    local age_days=$(( (current_time - last_rebuild) / 86400 ))
    
    if [ $age_days -gt $REBUILD_INTERVAL ]; then
        log_message "Âge de l'index: $age_days jours, reconstruction nécessaire"
        return 0
    else
        log_message "Âge de l'index: $age_days jours, reconstruction non nécessaire"
        return 1
    fi
}

# Fonction pour effectuer la reconstruction
perform_rebuild() {
    log_message "Début de la reconstruction d'index planifiée"
    
    if sudo mdutil -E /; then
        log_message "Reconstruction d'index initiée avec succès"
        echo "$(date +%s)" | sudo tee /var/db/.spotlight_last_rebuild > /dev/null
        return 0
    else
        log_message "Échec de la reconstruction d'index"
        return 1
    fi
}

# Fonction pour nettoyer les fichiers temporaires
cleanup_temp_files() {
    if [ "$CLEANUP_TEMP" = true ]; then
        log_message "Nettoyage des fichiers temporaires Spotlight"
        
        # Supprimer les fichiers d'index temporaires
        sudo find /tmp -name ".Spotlight*" -exec rm -rf {} \; 2>/dev/null
        sudo find /var/tmp -name ".Spotlight*" -exec rm -rf {} \; 2>/dev/null
        
        log_message "Nettoyage des fichiers temporaires terminé"
    fi
}

# Fonction pour vérifier les performances
check_performance() {
    if [ "$MONITOR_PERFORMANCE" = true ]; then
        local mds_cpu=$(ps aux | grep mds | grep -v grep | awk '{sum += $3} END {print sum}')
        
        if [ -n "$mds_cpu" ] && [ "$mds_cpu" -gt 50 ]; then
            log_message "AVERTISSEMENT: Utilisation CPU Spotlight élevée détectée: ${mds_cpu}%"
        else
            log_message "Performance Spotlight normale: ${mds_cpu:-0}% CPU"
        fi
    fi
}

# Routine de maintenance principale
log_message "Début de la maintenance automatisée Spotlight"

check_performance
cleanup_temp_files

if needs_rebuild; then
    perform_rebuild
fi

log_message "Maintenance automatisée Spotlight terminée"

Conclusion

La gestion efficace de Spotlight est cruciale pour maintenir des performances macOS optimales tout en préservant la fonctionnalité de recherche là où elle est nécessaire. Les scripts et techniques fournis dans ce guide offrent des solutions complètes pour divers scénarios de gestion Spotlight.

Points clés à retenir :

  • Comprendre l'impact de l'indexation sur les performances système
  • Utiliser les scripts appropriés pour votre cas d'usage spécifique
  • Implémenter des procédures de surveillance et maintenance appropriées
  • Toujours tester les changements dans un environnement contrôlé
  • Documenter toutes les modifications pour référence future

N'oubliez pas que désactiver l'indexation Spotlight impactera significativement la fonctionnalité de recherche, donc considérez soigneusement les compromis avant d'implémenter ces changements sur votre flotte Mac.