Guide

Nouvelles mises à jour et améliorations de Roundfleet.

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 Roundfleet 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 Roundfleet
# 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/roundfleet_preferences.log"
REPORT_DIR="/etc/roundfleet/reports/preferences"
CONFIG_DIR="/etc/roundfleet/preferences"
POLICY_DIR="/etc/roundfleet/policies/preferences"
BACKUP_DIR="/etc/roundfleet/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 Roundfleet 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 Roundfleet 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 Roundfleet
# Collecte complète de données système, analyse et surveillance

# Configuration
ROUNDFLEET_DIR="/etc/roundfleet"
SYSINFO_DIR="$ROUNDFLEET_DIR/system_information"
REPORTS_DIR="$ROUNDFLEET_DIR/reports"
COMPLIANCE_DIR="$ROUNDFLEET_DIR/compliance"
AUDIT_DIR="$ROUNDFLEET_DIR/audit"
LOG_FILE="/var/log/roundfleet_system_information.log"
POLICIES_DIR="$ROUNDFLEET_DIR/system_policies"
INVENTORY_DIR="$ROUNDFLEET_DIR/inventory"

# Créer la structure de répertoires
create_directories() {
    local dirs=("$ROUNDFLEET_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 Roundfleet ===
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 Roundfleet"
            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 Roundfleet 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 Roundfleet
# Surveillance complète de stockage, optimisation et gestion de politiques

# Configuration
ROUNDFLEET_DIR="/etc/roundfleet"
STORAGE_DIR="$ROUNDFLEET_DIR/storage_management"
REPORTS_DIR="$ROUNDFLEET_DIR/reports"
COMPLIANCE_DIR="$ROUNDFLEET_DIR/compliance"
AUDIT_DIR="$ROUNDFLEET_DIR/audit"
LOG_FILE="/var/log/roundfleet_storage_management.log"
POLICIES_DIR="$ROUNDFLEET_DIR/storage_policies"
CLEANUP_DIR="$ROUNDFLEET_DIR/cleanup_logs"

# Créer la structure de répertoires
create_directories() {
    local dirs=("$ROUNDFLEET_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 Roundfleet\""
    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 Roundfleet\""
            
            # 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 Roundfleet"
            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 Roundfleet"
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 Roundfleet"
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/roundfleet_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 Roundfleet"
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 Roundfleet"
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="Roundfleet"
DEPLOYMENT_DATE=$(date +"%Y-%m-%d")
LOG_FILE="/var/log/roundfleet_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.

Gestion Entreprise du Sommeil et de l'Alimentation pour macOS

Implémentez une gestion de sommeil et d'alimentation de niveau entreprise sur votre déploiement Roundfleet avec des politiques d'alimentation automatisées, l'optimisation énergétique, la surveillance de conformité et une gestion complète de la flotte. Ce tutoriel fournit des solutions pour maintenir une efficacité énergétique optimale tout en respectant les exigences de sécurité et opérationnelles.

Comprendre la Gestion de l'Alimentation macOS

macOS fournit plusieurs outils et mécanismes de gestion de l'alimentation :

  • pmset - Outil principal de paramètres de gestion d'alimentation
  • caffeinate - Empêcher le sommeil du système pour des opérations spécifiques
  • systemsetup - Configuration d'alimentation à l'échelle du système
  • Économiseur d'énergie - Interface de gestion d'alimentation via GUI
  • Assertions d'alimentation - Prévention du sommeil au niveau application

Opérations de Gestion d'Alimentation de Base

Configurer le Minuteur de Sommeil Système

#!/bin/bash

# Définir le minuteur de sommeil système à 15 minutes
sudo pmset sleep 15

Configurer le Minuteur de Sommeil d'Écran

#!/bin/bash

# Définir le minuteur de sommeil d'écran à 15 minutes
sudo pmset displaysleep 15

Programmer les Événements de Réveil

#!/bin/bash

# Programmer le réveil tous les jours à 9h00
sudo pmset repeat wakeorpoweron MTWRFSU 9:00:00

Empêcher le Sommeil pour une Période Spécifique

#!/bin/bash

# Empêcher le sommeil du système pendant 300 secondes
caffeinate -u -t 300

Vérifier les Paramètres de Sommeil Système

#!/bin/bash

# Vérifier le temps d'inactivité de sommeil actuel
sudo systemsetup -getcomputersleep

Désactiver le Sommeil Système

#!/bin/bash

# Désactiver le sommeil système
sudo systemsetup -setcomputersleep Never

Activer le Redémarrage en Cas de Blocage

#!/bin/bash

# Redémarrer automatiquement en cas de blocage système
systemsetup -setrestartfreeze on

Système de Gestion d'Alimentation Entreprise

Outil de Gestion d'Alimentation Complet

#!/bin/bash

# Outil de Gestion du Sommeil et de l'Alimentation Entreprise Roundfleet
# Politiques d'alimentation avancées et optimisation énergétique

# Configuration
CONFIG_FILE="/etc/roundfleet/power_policy.conf"
LOG_FILE="/var/log/roundfleet_power.log"
POLICIES_DIR="/Library/Roundfleet/PowerPolicies"
AUDIT_LOG="/var/log/roundfleet_power_audit.log"

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

# Politique de gestion d'alimentation par défaut
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Politique de Gestion d'Alimentation Entreprise Roundfleet
# Version : 2.0

# Application des Politiques d'Alimentation
ENFORCE_POWER_POLICIES=true
AUTO_APPLY_POLICIES=true
POWER_PROFILE="corporate_standard"
ENERGY_OPTIMIZATION=true
COMPLIANCE_MONITORING=true

# Paramètres de Sommeil (minutes)
SYSTEM_SLEEP_AC=30
SYSTEM_SLEEP_BATTERY=15
DISPLAY_SLEEP_AC=15
DISPLAY_SLEEP_BATTERY=5
DISK_SLEEP_AC=10
DISK_SLEEP_BATTERY=5

# Événements de Réveil et d'Alimentation
WAKE_ON_LAN=true
WAKE_ON_ADMINISTRATIVE_ACCESS=true
AUTOMATIC_RESTART_ON_POWER_LOSS=true
AUTOMATIC_RESTART_ON_FREEZE=true
SCHEDULED_WAKE_ENABLED=true
SCHEDULED_SLEEP_ENABLED=true

# Configuration des Heures de Bureau
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
BUSINESS_DAYS="MTWRF"
WEEKEND_POWER_PROFILE="energy_saver"
AFTER_HOURS_POWER_PROFILE="security_focused"
EOF

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

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

# Fonction de journalisation d'audit
audit_log() {
    local action="$1"
    local result="$2"
    local details="$3"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ACTION:$action RESULT:$result DETAILS:$details USER:$(whoami)" >> "$AUDIT_LOG"
}

# Obtenir l'état actuel de l'alimentation
get_power_status() {
    echo "=== État Actuel de la Gestion d'Alimentation ==="
    
    # Paramètres d'alimentation à l'échelle du système
    echo "Paramètres d'Alimentation Système :"
    pmset -g 2>/dev/null || echo "  Paramètres d'alimentation indisponibles"
    
    echo -e "\nSource d'Alimentation Actuelle :"
    pmset -g ps 2>/dev/null | head -1
    
    echo -e "\nMinuteurs de Sommeil :"
    echo "  Sommeil Système (AC) : $(pmset -g | grep -E '^\s*sleep\s' | awk '{print $2}') minutes"
    echo "  Sommeil Écran (AC) : $(pmset -g | grep -E '^\s*displaysleep\s' | awk '{print $2}') minutes"
    echo "  Sommeil Disque (AC) : $(pmset -g | grep -E '^\s*disksleep\s' | awk '{print $2}') minutes"
    
    echo -e "\nAssertions d'Alimentation :"
    pmset -g assertions 2>/dev/null | grep -E "(PreventUserIdleSystemSleep|PreventUserIdleDisplaySleep)" | head -5
    
    echo -e "\nÉtat Thermique :"
    pmset -g thermstate 2>/dev/null | head -3
    
    return 0
}

# Appliquer un profil d'alimentation entreprise
apply_power_profile() {
    local profile="${1:-$POWER_PROFILE}"
    
    echo "=== Application du Profil d'Alimentation Entreprise : $profile ==="
    
    case "$profile" in
        "corporate_standard")
            apply_corporate_standard_profile
            ;;
        "energy_saver")
            apply_energy_saver_profile
            ;;
        "high_performance")
            apply_high_performance_profile
            ;;
        "security_focused")
            apply_security_focused_profile
            ;;
        "presentation_mode")
            apply_presentation_mode_profile
            ;;
        "kiosk_mode")
            apply_kiosk_mode_profile
            ;;
        *)
            echo "Profil d'alimentation inconnu : $profile"
            echo "Utilisation du profil corporate_standard par défaut"
            apply_corporate_standard_profile
            ;;
    esac
    
    # Appliquer les paramètres de sécurité communs
    apply_security_settings
    
    # Configurer les événements programmés
    configure_scheduled_events
    
    echo "✅ Profil d'alimentation '$profile' appliqué avec succès"
    log_action "Profil d'alimentation appliqué : $profile"
    audit_log "POWER_PROFILE" "APPLIED" "Profil : $profile"
    
    return 0
}

# Profil d'alimentation standard entreprise
apply_corporate_standard_profile() {
    echo "=== Configuration du Profil Standard Entreprise ==="
    
    # Paramètres alimentation secteur
    sudo pmset -c sleep "$SYSTEM_SLEEP_AC" 2>/dev/null
    sudo pmset -c displaysleep "$DISPLAY_SLEEP_AC" 2>/dev/null
    sudo pmset -c disksleep "$DISK_SLEEP_AC" 2>/dev/null
    
    # Paramètres batterie (si applicable)
    sudo pmset -b sleep "$SYSTEM_SLEEP_BATTERY" 2>/dev/null
    sudo pmset -b displaysleep "$DISPLAY_SLEEP_BATTERY" 2>/dev/null
    sudo pmset -b disksleep "$DISK_SLEEP_BATTERY" 2>/dev/null
    
    # Paramètres de réveil
    if [[ "$WAKE_ON_LAN" == "true" ]]; then
        sudo pmset -a womp 1 2>/dev/null
    fi
    
    if [[ "$WAKE_ON_ADMINISTRATIVE_ACCESS" == "true" ]]; then
        sudo pmset -a acwake 1 2>/dev/null
    fi
    
    echo "Profil standard entreprise configuré"
    log_action "Profil d'alimentation standard entreprise appliqué"
}

# Profil économiseur d'énergie
apply_energy_saver_profile() {
    echo "=== Configuration du Profil Économiseur d'Énergie ==="
    
    # Économie d'énergie agressive
    sudo pmset -c sleep 10 2>/dev/null
    sudo pmset -c displaysleep 5 2>/dev/null
    sudo pmset -c disksleep 5 2>/dev/null
    
    sudo pmset -b sleep 5 2>/dev/null
    sudo pmset -b displaysleep 2 2>/dev/null
    sudo pmset -b disksleep 3 2>/dev/null
    
    # Activer les fonctionnalités d'économie d'énergie
    sudo pmset -a reducebright 1 2>/dev/null
    sudo pmset -a lessbright 1 2>/dev/null
    
    echo "Profil économiseur d'énergie configuré"
    log_action "Profil d'alimentation économiseur d'énergie appliqué"
}

# Profil haute performance
apply_high_performance_profile() {
    echo "=== Configuration du Profil Haute Performance ==="
    
    # Paramètres de sommeil minimaux
    sudo pmset -c sleep 60 2>/dev/null
    sudo pmset -c displaysleep 30 2>/dev/null
    sudo pmset -c disksleep 30 2>/dev/null
    
    sudo pmset -b sleep 30 2>/dev/null
    sudo pmset -b displaysleep 15 2>/dev/null
    sudo pmset -b disksleep 15 2>/dev/null
    
    # Désactiver les fonctionnalités d'économie d'énergie
    sudo pmset -a reducebright 0 2>/dev/null
    sudo pmset -a lessbright 0 2>/dev/null
    
    echo "Profil haute performance configuré"
    log_action "Profil d'alimentation haute performance appliqué"
}

# Profil axé sécurité
apply_security_focused_profile() {
    echo "=== Configuration du Profil Axé Sécurité ==="
    
    # Minuteurs de sommeil courts pour la sécurité
    sudo pmset -c sleep 5 2>/dev/null
    sudo pmset -c displaysleep 3 2>/dev/null
    sudo pmset -c disksleep 5 2>/dev/null
    
    sudo pmset -b sleep 3 2>/dev/null
    sudo pmset -b displaysleep 1 2>/dev/null
    sudo pmset -b disksleep 3 2>/dev/null
    
    echo "Profil axé sécurité configuré"
    log_action "Profil d'alimentation axé sécurité appliqué"
}

# Profil mode présentation
apply_presentation_mode_profile() {
    echo "=== Configuration du Profil Mode Présentation ==="
    
    # Empêcher le sommeil pendant les présentations
    sudo pmset -c sleep 0 2>/dev/null
    sudo pmset -c displaysleep 0 2>/dev/null
    
    # Maintenir le système actif
    sudo pmset -a lidwake 1 2>/dev/null
    sudo pmset -a acwake 1 2>/dev/null
    
    echo "Profil mode présentation configuré"
    log_action "Profil d'alimentation mode présentation appliqué"
}

# Profil mode kiosque
apply_kiosk_mode_profile() {
    echo "=== Configuration du Profil Mode Kiosque ==="
    
    # Paramètres jamais en sommeil pour les appareils kiosque
    sudo pmset -c sleep 0 2>/dev/null
    sudo pmset -c displaysleep 0 2>/dev/null
    sudo pmset -c disksleep 0 2>/dev/null
    
    # Assurer que le système reste actif
    sudo pmset -a womp 1 2>/dev/null
    sudo pmset -a autorestart 1 2>/dev/null
    
    echo "Profil mode kiosque configuré"
    log_action "Profil d'alimentation mode kiosque appliqué"
}

# Appliquer les paramètres de sécurité
apply_security_settings() {
    echo "=== Application des Paramètres de Sécurité d'Alimentation ==="
    
    # Mode d'hibernation sécurisé
    sudo pmset -a hibernatemode 3 2>/dev/null
    echo "✅ Mode d'hibernation défini à 3"
    
    # Redémarrage automatique
    if [[ "$AUTOMATIC_RESTART_ON_POWER_LOSS" == "true" ]]; then
        sudo pmset -a autorestart 1 2>/dev/null
        echo "✅ Redémarrage automatique en cas de perte d'alimentation activé"
    fi
    
    if [[ "$AUTOMATIC_RESTART_ON_FREEZE" == "true" ]]; then
        sudo systemsetup -setrestartfreeze on 2>/dev/null
        echo "✅ Redémarrage automatique en cas de blocage activé"
    fi
    
    log_action "Paramètres de sécurité d'alimentation appliqués"
}

# Configurer les événements programmés
configure_scheduled_events() {
    echo "=== Configuration des Événements d'Alimentation Programmés ==="
    
    # Effacer les événements programmés existants
    sudo pmset repeat cancel 2>/dev/null
    
    if [[ "$SCHEDULED_WAKE_ENABLED" == "true" ]]; then
        # Programmer le réveil pour les heures de bureau
        sudo pmset repeat wakeorpoweron "$BUSINESS_DAYS" "$BUSINESS_HOURS_START:00" 2>/dev/null
        echo "✅ Réveil programmé configuré pour les heures de bureau"
        log_action "Réveil programmé configuré : $BUSINESS_DAYS à $BUSINESS_HOURS_START"
    fi
    
    if [[ "$SCHEDULED_SLEEP_ENABLED" == "true" ]]; then
        # Programmer le sommeil après les heures de bureau
        local sleep_time="${BUSINESS_HOURS_END}:30:00"
        sudo pmset repeat sleep "$BUSINESS_DAYS" "$sleep_time" 2>/dev/null
        echo "✅ Sommeil programmé configuré pour après les heures"
        log_action "Sommeil programmé configuré : $BUSINESS_DAYS à $sleep_time"
    fi
}

# Vérifier la conformité de la gestion d'alimentation
check_power_compliance() {
    echo "=== Vérification de Conformité de la Gestion d'Alimentation ==="
    
    local compliance_issues=()
    local compliance_score=100
    
    # Vérifier si la gestion d'alimentation est correctement configurée
    local current_settings
    current_settings=$(pmset -g 2>/dev/null)
    
    if [[ -z "$current_settings" ]]; then
        compliance_issues+=("Impossible de lire les paramètres de gestion d'alimentation")
        compliance_score=$((compliance_score - 50))
    fi
    
    # Vérifier les minuteurs de sommeil
    local system_sleep
    system_sleep=$(echo "$current_settings" | grep -E '^\s*sleep\s' | awk '{print $2}')
    
    if [[ "$system_sleep" == "0" ]] && [[ "$POWER_PROFILE" != "kiosk_mode" ]] && [[ "$POWER_PROFILE" != "presentation_mode" ]]; then
        compliance_issues+=("Sommeil système désactivé (risque de sécurité)")
        compliance_score=$((compliance_score - 20))
    fi
    
    # Vérifier le sommeil d'écran
    local display_sleep
    display_sleep=$(echo "$current_settings" | grep -E '^\s*displaysleep\s' | awk '{print $2}')
    
    if [[ "$display_sleep" == "0" ]] && [[ "$POWER_PROFILE" != "kiosk_mode" ]] && [[ "$POWER_PROFILE" != "presentation_mode" ]]; then
        compliance_issues+=("Sommeil d'écran désactivé (gaspillage d'énergie)")
        compliance_score=$((compliance_score - 15))
    fi
    
    # Rapporter l'état de conformité
    echo "Score de Conformité : $compliance_score/100"
    
    if [[ ${#compliance_issues[@]} -eq 0 ]]; then
        echo "✅ La configuration de gestion d'alimentation est conforme"
        audit_log "COMPLIANCE_CHECK" "PASSED" "Score : $compliance_score/100"
        return 0
    else
        echo "❌ Problèmes de conformité trouvés :"
        printf '  - %s\n' "${compliance_issues[@]}"
        audit_log "COMPLIANCE_CHECK" "FAILED" "Problèmes : ${#compliance_issues[@]} Score : $compliance_score/100"
        
        # Auto-remédiation si activée
        if [[ "$AUTO_APPLY_POLICIES" == "true" ]]; then
            echo "🔧 Auto-remédiation activée, application du profil d'alimentation correct..."
            apply_power_profile "$POWER_PROFILE"
        fi
        
        return 1
    fi
}

# Empêcher le sommeil système pour des opérations critiques
prevent_sleep_for_operation() {
    local operation_name="$1"
    local duration_seconds="$2"
    local prevent_display="${3:-false}"
    
    echo "=== Empêcher le Sommeil pour l'Opération : $operation_name ==="
    
    local caffeinate_options="-i"
    
    if [[ "$prevent_display" == "true" ]]; then
        caffeinate_options="$caffeinate_options -d"
    fi
    
    if [[ -n "$duration_seconds" ]]; then
        caffeinate_options="$caffeinate_options -t $duration_seconds"
    fi
    
    echo "Empêchement du sommeil système pour $operation_name..."
    log_action "Prévention de sommeil démarrée pour l'opération : $operation_name (durée : ${duration_seconds:-indéfinie}s)"
    
    # Exécuter caffeinate en arrière-plan et retourner le PID
    caffeinate $caffeinate_options &
    local caffeinate_pid=$!
    
    echo "Prévention de sommeil active (PID : $caffeinate_pid)"
    echo "$caffeinate_pid" > "/tmp/roundfleet_caffeinate_$operation_name.pid"
    
    audit_log "SLEEP_PREVENTION" "STARTED" "Opération : $operation_name PID : $caffeinate_pid"
    
    return 0
}

# Arrêter la prévention de sommeil pour une opération
stop_sleep_prevention() {
    local operation_name="$1"
    local pid_file="/tmp/roundfleet_caffeinate_$operation_name.pid"
    
    if [[ -f "$pid_file" ]]; then
        local caffeinate_pid
        caffeinate_pid=$(cat "$pid_file")
        
        if kill -0 "$caffeinate_pid" 2>/dev/null; then
            kill "$caffeinate_pid"
            echo "Prévention de sommeil arrêtée pour $operation_name (PID : $caffeinate_pid)"
            log_action "Prévention de sommeil arrêtée pour l'opération : $operation_name"
            audit_log "SLEEP_PREVENTION" "STOPPED" "Opération : $operation_name PID : $caffeinate_pid"
        else
            echo "Processus de prévention de sommeil non trouvé pour $operation_name"
        fi
        
        rm -f "$pid_file"
    else
        echo "Aucune prévention de sommeil active trouvée pour $operation_name"
    fi
}

# Fonction principale avec gestion d'arguments
main() {
    log_action "=== Outil de Gestion d'Alimentation Roundfleet Démarré ==="
    
    case "${1:-status}" in
        "status")
            get_power_status
            ;;
        "profile")
            apply_power_profile "$2"
            ;;
        "compliance")
            check_power_compliance
            ;;
        "prevent-sleep")
            prevent_sleep_for_operation "$2" "$3" "$4"
            ;;
        "allow-sleep")
            stop_sleep_prevention "$2"
            ;;
        "schedule")
            configure_scheduled_events
            ;;
        *)
            echo "Outil de Gestion d'Alimentation Entreprise Roundfleet"
            echo "Usage : $0 [commande] [options]"
            echo ""
            echo "Commandes :"
            echo "  status                        - Afficher l'état actuel de la gestion d'alimentation"
            echo "  profile [nom]                 - Appliquer un profil d'alimentation spécifique"
            echo "  compliance                    - Vérifier la conformité de la gestion d'alimentation"
            echo "  prevent-sleep [nom] [durée] [écran] - Empêcher le sommeil pour une opération"
            echo "  allow-sleep [nom]             - Arrêter la prévention de sommeil pour une opération"
            echo "  schedule                      - Configurer les événements d'alimentation programmés"
            echo ""
            echo "Profils d'Alimentation :"
            echo "  corporate_standard            - Gestion d'alimentation d'entreprise standard (défaut)"
            echo "  energy_saver                  - Efficacité énergétique maximale"
            echo "  high_performance              - Paramètres axés performance"
            echo "  security_focused              - Gestion d'alimentation optimisée sécurité"
            echo "  presentation_mode             - Empêcher le sommeil pendant les présentations"
            echo "  kiosk_mode                    - Toujours actif pour les appareils kiosque"
            ;;
    esac
    
    log_action "=== Opération de gestion d'alimentation terminée ==="
}

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

Notes de Configuration Importantes

Architecture de Gestion d'Alimentation macOS

  • Unité de Gestion d'Alimentation (PMU) - Contrôle d'alimentation au niveau matériel
  • IOPMrootDomain - Gestion d'alimentation du noyau
  • PowerManagement.framework - APIs d'alimentation espace utilisateur
  • pmset - Outil de gestion d'alimentation en ligne de commande
  • Économiseur d'Énergie - Interface d'alimentation Préférences Système

Points d'Intégration Entreprise

  • Profils de Configuration MDM - Déployer les politiques d'alimentation de manière centralisée
  • Systèmes de Surveillance Énergétique - Intégration avec la gestion des installations
  • Suivi d'Empreinte Carbone - Rapports de conformité environnementale
  • Intelligence d'Affaires - Analytiques et optimisation de l'utilisation d'énergie

Bonnes Pratiques pour la Gestion d'Alimentation Entreprise

  1. Stratégie d'Efficacité Énergétique

    • Implémenter des profils d'alimentation échelonnés basés sur les modèles d'utilisation
    • Surveiller et optimiser la consommation d'énergie à travers la flotte
    • S'aligner avec les initiatives de développement durable d'entreprise
    • Suivre les économies de coûts des politiques de gestion d'alimentation
  2. Considérations de Sécurité

    • Activer la destruction des clés FileVault en veille pour les données sensibles
    • Configurer des modes d'hibernation appropriés pour la sécurité
    • Implémenter des modes de sommeil sécurisés pour les appareils non surveillés
    • Équilibrer les exigences de sécurité avec les besoins opérationnels
  3. Optimisation des Performances

    • Utiliser des profils haute performance pour les tâches intensives en ressources
    • Implémenter des modes présentation pour les scénarios de réunion
    • Configurer la gestion thermique pour les charges de travail soutenues
    • Surveiller la santé de la batterie et optimiser les modèles de charge
  4. Conformité et Rapports

    • Générer des rapports d'utilisation d'énergie pour la conformité réglementaire
    • Suivre l'adhérence aux politiques de gestion d'alimentation
    • Documenter les initiatives d'optimisation d'alimentation
    • Surveiller les métriques d'impact environnemental

N'oubliez pas de tester minutieusement les configurations de gestion d'alimentation dans votre environnement avant le déploiement à l'échelle de la flotte pour vous assurer qu'elles répondent aux exigences opérationnelles, de sécurité et d'efficacité énergétique de votre organisation.

Gestion Entreprise de l'Arrêt et du Redémarrage pour macOS

Implémentez une gestion d'arrêt et de redémarrage de niveau entreprise sur votre déploiement Roundfleet avec la planification automatisée de maintenance, les procédures d'arrêt en douceur, la validation de sécurité et la gestion complète de l'alimentation de la flotte. Ce tutoriel fournit des solutions pour maintenir la continuité opérationnelle tout en assurant des opérations d'alimentation système sécurisées et efficaces.

Comprendre la Gestion d'Arrêt et de Redémarrage macOS

macOS fournit plusieurs mécanismes et outils de contrôle d'alimentation :

  • shutdown - Outil principal en ligne de commande pour le contrôle d'alimentation système
  • reboot - Commande alternative de redémarrage
  • halt - Arrêt du système sans extinction
  • Menu Apple - Interface d'arrêt via GUI
  • Bouton d'alimentation - Contrôle d'alimentation au niveau matériel

Opérations d'Arrêt de Base

Arrêt Instantané

#!/bin/bash

# Arrêter le Mac instantanément
sudo shutdown -h now

Redémarrage Programmé

#!/bin/bash

# Redémarrer le Mac dans 5 minutes
sudo shutdown -r +5

Arrêt à une Heure Spécifique

#!/bin/bash

# Arrêt à une heure spécifique : 18 octobre, 16:11:00 2022
sudo shutdown -h 2210181611

Redémarrage avec Message d'Avertissement

#!/bin/bash

# Redémarrer avec message d'avertissement
sudo shutdown -r +2 "le système redémarrera dans 2 minutes"

Veille d'Écran et Verrouillage

#!/bin/bash

# Verrouiller l'appareil et éteindre l'écran
sudo shutdown -s

Système de Gestion d'Arrêt et de Redémarrage Entreprise

Outil de Gestion d'Alimentation Complet

#!/bin/bash

# Outil de Gestion d'Arrêt et de Redémarrage Entreprise Roundfleet
# Contrôle d'alimentation avancé et planification de maintenance

# Configuration
CONFIG_FILE="/etc/roundfleet/shutdown_policy.conf"
LOG_FILE="/var/log/roundfleet_shutdown.log"
SCHEDULES_DIR="/Library/Roundfleet/ShutdownSchedules"
AUDIT_LOG="/var/log/roundfleet_shutdown_audit.log"

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

# Politique de gestion d'arrêt par défaut
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Politique de Gestion d'Arrêt et de Redémarrage Entreprise Roundfleet
# Version : 2.0

# Application des Politiques d'Arrêt
ENFORCE_SHUTDOWN_POLICIES=true
GRACEFUL_SHUTDOWN_ENABLED=true
SAVE_WORK_BEFORE_SHUTDOWN=true
FORCE_SHUTDOWN_TIMEOUT=300
WARNING_NOTIFICATION_TIME=300

# Sécurité et Sûreté
REQUIRE_ADMIN_APPROVAL=false
VALIDATE_USER_SESSIONS=true
CHECK_RUNNING_PROCESSES=true
BACKUP_BEFORE_SHUTDOWN=false
ENCRYPTION_KEY_PROTECTION=true

# Fenêtres de Maintenance
MAINTENANCE_WINDOW_ENABLED=true
MAINTENANCE_START_TIME="02:00"
MAINTENANCE_END_TIME="06:00"
MAINTENANCE_DAYS="MTWRF"
WEEKEND_MAINTENANCE_ENABLED=true
HOLIDAY_MAINTENANCE_DISABLED=true

# Protection des Heures de Bureau
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
PREVENT_SHUTDOWN_BUSINESS_HOURS=true
EMERGENCY_SHUTDOWN_OVERRIDE=true
CRITICAL_SYSTEM_PROTECTION=true

# Notification et Communication
USER_NOTIFICATION_ENABLED=true
ADMIN_NOTIFICATION_ENABLED=true
SLACK_WEBHOOK_URL=""
EMAIL_NOTIFICATION_ENABLED=false
NOTIFICATION_LEAD_TIME=600

# Planification Automatique
AUTO_REBOOT_ENABLED=true
AUTO_REBOOT_FREQUENCY="weekly"
AUTO_REBOOT_DAY="sunday"
AUTO_REBOOT_TIME="03:00"
PATCH_REBOOT_REQUIRED=true
EOF

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

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

# Fonction de journalisation d'audit
audit_log() {
    local action="$1"
    local result="$2"
    local details="$3"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ACTION:$action RESULT:$result DETAILS:$details USER:$(whoami)" >> "$AUDIT_LOG"
}

# Vérifier si l'arrêt est autorisé
check_shutdown_allowed() {
    local operation="$1"
    local force="${2:-false}"
    
    echo "=== Validation de l'Autorisation d'Arrêt ==="
    
    # Vérifier la protection des heures de bureau
    if [[ "$PREVENT_SHUTDOWN_BUSINESS_HOURS" == "true" && "$force" != "true" ]]; then
        local current_hour
        current_hour=$(date +%H)
        local start_hour
        start_hour=$(echo "$BUSINESS_HOURS_START" | cut -d':' -f1)
        local end_hour
        end_hour=$(echo "$BUSINESS_HOURS_END" | cut -d':' -f1)
        
        if [[ $current_hour -ge $start_hour && $current_hour -lt $end_hour ]]; then
            echo "❌ Arrêt bloqué : Actuellement en heures de bureau ($BUSINESS_HOURS_START - $BUSINESS_HOURS_END)"
            log_action "ARRÊT BLOQUÉ : Protection des heures de bureau active"
            audit_log "SHUTDOWN_BLOCKED" "BUSINESS_HOURS" "Opération : $operation Heure : $(date '+%H:%M')"
            return 1
        fi
    fi
    
    # Vérifier les sessions utilisateur actives
    if [[ "$VALIDATE_USER_SESSIONS" == "true" ]]; then
        local active_users
        active_users=$(who | wc -l)
        
        if [[ $active_users -gt 0 && "$force" != "true" ]]; then
            echo "⚠️  Avertissement : $active_users session(s) utilisateur active(s) détectée(s)"
            log_action "AVERTISSEMENT : Sessions utilisateur actives pendant $operation"
            
            if [[ "$GRACEFUL_SHUTDOWN_ENABLED" != "true" ]]; then
                echo "❌ Arrêt bloqué : Utilisateurs actifs et arrêt en douceur désactivé"
                audit_log "SHUTDOWN_BLOCKED" "ACTIVE_USERS" "Utilisateurs : $active_users Opération : $operation"
                return 1
            fi
        fi
    fi
    
    # Vérifier les processus critiques en cours
    if [[ "$CHECK_RUNNING_PROCESSES" == "true" ]]; then
        local critical_processes=(
            "backupd"
            "softwareupdate"
            "installer"
            "diskutil"
            "fsck"
        )
        
        for process in "${critical_processes[@]}"; do
            if pgrep -f "$process" >/dev/null 2>&1; then
                echo "⚠️  Processus critique en cours : $process"
                
                if [[ "$force" != "true" ]]; then
                    echo "❌ Arrêt bloqué : Le processus critique $process est en cours"
                    log_action "ARRÊT BLOQUÉ : Processus critique $process en cours"
                    audit_log "SHUTDOWN_BLOCKED" "CRITICAL_PROCESS" "Processus : $process Opération : $operation"
                    return 1
                else
                    echo "🚨 Arrêt forcé : Terminera le processus critique $process"
                    log_action "ARRÊT FORCÉ : Termination du processus critique $process"
                fi
            fi
        done
    fi
    
    echo "✅ Autorisation d'arrêt validée"
    audit_log "SHUTDOWN_AUTHORIZED" "APPROVED" "Opération : $operation"
    return 0
}

# Envoyer une notification avant l'arrêt
send_shutdown_notification() {
    local operation="$1"
    local delay_minutes="$2"
    local message="$3"
    
    echo "=== Envoi des Notifications d'Arrêt ==="
    
    local notification_title="Notification $operation Système Roundfleet"
    local notification_message="${message:-$operation système programmé dans $delay_minutes minutes}"
    
    # Notification utilisateur
    if [[ "$USER_NOTIFICATION_ENABLED" == "true" ]]; then
        # Afficher la notification à tous les utilisateurs connectés
        local logged_users
        logged_users=$(who | awk '{print $1}' | sort -u)
        
        for user in $logged_users; do
            if [[ -n "$user" ]]; then
                sudo -u "$user" osascript -e "display notification \"$notification_message\" with title \"$notification_title\"" 2>/dev/null || true
                echo "📱 Notification envoyée à l'utilisateur : $user"
            fi
        done
        
        # Notification terminal
        wall "$notification_title : $notification_message" 2>/dev/null || true
    fi
    
    log_action "Notifications d'arrêt envoyées pour $operation (délai : $delay_minutes minutes)"
}

# Arrêt en douceur avec gestion des sessions utilisateur
graceful_shutdown() {
    local operation="$1"
    local delay_minutes="$2"
    local message="$3"
    
    echo "=== Initiation de l'$operation en Douceur ==="
    
    # Envoyer la notification initiale
    send_shutdown_notification "$operation" "$delay_minutes" "$message"
    
    # Sauvegarder le travail utilisateur si activé
    if [[ "$SAVE_WORK_BEFORE_SHUTDOWN" == "true" ]]; then
        echo "💾 Tentative de sauvegarde du travail utilisateur..."
        
        # Essayer de sauvegarder le travail dans les applications courantes
        local save_commands=(
            "osascript -e 'tell application \"System Events\" to keystroke \"s\" using command down'"
            "pkill -USR1 TextEdit"  # Signal TextEdit pour sauvegarder
        )
        
        for cmd in "${save_commands[@]}"; do
            eval "$cmd" 2>/dev/null || true
        done
        
        log_action "Tentative de sauvegarde du travail utilisateur avant $operation"
    fi
    
    # Protection des clés FileVault
    if [[ "$ENCRYPTION_KEY_PROTECTION" == "true" ]]; then
        echo "🔐 Assurance de la sécurité des clés FileVault..."
        sudo pmset -a destroyfvkeyonstandby 1 2>/dev/null || true
        log_action "Protection des clés FileVault activée avant $operation"
    fi
    
    # Attendre la période de délai avec compte à rebours
    if [[ $delay_minutes -gt 0 ]]; then
        echo "⏱️  Attente de $delay_minutes minutes avant $operation..."
        
        local remaining_seconds=$((delay_minutes * 60))
        local notification_intervals=(300 120 60 30 10)  # 5min, 2min, 1min, 30s, 10s
        
        while [[ $remaining_seconds -gt 0 ]]; do
            # Envoyer des rappels de notification à des intervalles spécifiques
            for interval in "${notification_intervals[@]}"; do
                if [[ $remaining_seconds -eq $interval ]]; then
                    local remaining_minutes=$((remaining_seconds / 60))
                    if [[ $remaining_minutes -gt 0 ]]; then
                        send_shutdown_notification "$operation" "$remaining_minutes" "Avertissement final : $operation système dans $remaining_minutes minute(s)"
                    else
                        send_shutdown_notification "$operation" "0" "Avertissement final : $operation système dans $remaining_seconds secondes"
                    fi
                    break
                fi
            done
            
            sleep 1
            remaining_seconds=$((remaining_seconds - 1))
        done
    fi
    
    echo "✅ Préparation de l'$operation en douceur terminée"
    log_action "Préparation de l'$operation en douceur terminée"
}

# Arrêt entreprise avec validation complète
enterprise_shutdown() {
    local delay="${1:-now}"
    local message="$2"
    local force="${3:-false}"
    
    echo "=== Arrêt Entreprise Initié ==="
    
    # Valider l'autorisation d'arrêt
    if ! check_shutdown_allowed "arrêt" "$force"; then
        return 1
    fi
    
    # Analyser le délai
    local delay_minutes=0
    if [[ "$delay" != "now" ]]; then
        if [[ "$delay" =~ ^\+([0-9]+)$ ]]; then
            delay_minutes="${BASH_REMATCH[1]}"
        else
            echo "❌ Format de délai invalide. Utilisez 'now' ou '+minutes'"
            return 1
        fi
    fi
    
    # Arrêt en douceur si activé
    if [[ "$GRACEFUL_SHUTDOWN_ENABLED" == "true" ]]; then
        graceful_shutdown "arrêt" "$delay_minutes" "$message"
    fi
    
    # Journaliser l'action d'arrêt
    log_action "ARRÊT ENTREPRISE : Exécution de l'arrêt avec délai : $delay"
    audit_log "SHUTDOWN" "INITIATED" "Délai : $delay Message : ${message:-Aucun} Force : $force"
    
    # Exécuter l'arrêt
    if [[ "$delay" == "now" ]]; then
        echo "🔌 Exécution de l'arrêt immédiat..."
        sudo shutdown -h now "$message"
    else
        echo "🔌 Programmation de l'arrêt dans $delay_minutes minutes..."
        sudo shutdown -h +"$delay_minutes" "$message"
    fi
    
    audit_log "SHUTDOWN" "EXECUTED" "Commande terminée avec succès"
    return 0
}

# Redémarrage entreprise avec validation complète
enterprise_reboot() {
    local delay="${1:-now}"
    local message="$2"
    local force="${3:-false}"
    
    echo "=== Redémarrage Entreprise Initié ==="
    
    # Valider l'autorisation de redémarrage
    if ! check_shutdown_allowed "redémarrage" "$force"; then
        return 1
    fi
    
    # Analyser le délai
    local delay_minutes=0
    if [[ "$delay" != "now" ]]; then
        if [[ "$delay" =~ ^\+([0-9]+)$ ]]; then
            delay_minutes="${BASH_REMATCH[1]}"
        else
            echo "❌ Format de délai invalide. Utilisez 'now' ou '+minutes'"
            return 1
        fi
    fi
    
    # Redémarrage en douceur si activé
    if [[ "$GRACEFUL_SHUTDOWN_ENABLED" == "true" ]]; then
        graceful_shutdown "redémarrage" "$delay_minutes" "$message"
    fi
    
    # Journaliser l'action de redémarrage
    log_action "REDÉMARRAGE ENTREPRISE : Exécution du redémarrage avec délai : $delay"
    audit_log "REBOOT" "INITIATED" "Délai : $delay Message : ${message:-Aucun} Force : $force"
    
    # Exécuter le redémarrage
    if [[ "$delay" == "now" ]]; then
        echo "🔄 Exécution du redémarrage immédiat..."
        sudo shutdown -r now "$message"
    else
        echo "🔄 Programmation du redémarrage dans $delay_minutes minutes..."
        sudo shutdown -r +"$delay_minutes" "$message"
    fi
    
    audit_log "REBOOT" "EXECUTED" "Commande terminée avec succès"
    return 0
}

# Programmer un redémarrage de maintenance
schedule_maintenance_reboot() {
    local schedule_time="$1"
    local reason="$2"
    
    echo "=== Programmation d'un Redémarrage de Maintenance ==="
    
    if [[ -z "$schedule_time" ]]; then
        echo "❌ Heure de programmation requise (format : AAMMJJHHMM)"
        return 1
    fi
    
    # Valider le format de l'heure de programmation
    if [[ ! "$schedule_time" =~ ^[0-9]{10}$ ]]; then
        echo "❌ Format d'heure de programmation invalide. Utilisez AAMMJJHHMM"
        return 1
    fi
    
    # Vérifier si l'heure programmée est dans la fenêtre de maintenance
    if [[ "$MAINTENANCE_WINDOW_ENABLED" == "true" ]]; then
        local schedule_hour
        schedule_hour=$(echo "$schedule_time" | cut -c 7-8)
        local maintenance_start_hour
        maintenance_start_hour=$(echo "$MAINTENANCE_START_TIME" | cut -d':' -f1)
        local maintenance_end_hour
        maintenance_end_hour=$(echo "$MAINTENANCE_END_TIME" | cut -d':' -f1)
        
        if [[ $schedule_hour -lt $maintenance_start_hour || $schedule_hour -ge $maintenance_end_hour ]]; then
            echo "⚠️  Avertissement : Heure programmée en dehors de la fenêtre de maintenance ($MAINTENANCE_START_TIME - $MAINTENANCE_END_TIME)"
        fi
    fi
    
    # Programmer le redémarrage
    local message="Redémarrage de maintenance programmé : ${reason:-Maintenance système}"
    
    log_action "REDÉMARRAGE DE MAINTENANCE PROGRAMMÉ : Heure : $schedule_time Raison : ${reason:-Maintenance système}"
    audit_log "MAINTENANCE_SCHEDULED" "CREATED" "Heure : $schedule_time Raison : ${reason:-Maintenance système}"
    
    echo "🗓️  Programmation du redémarrage de maintenance..."
    sudo shutdown -r "$schedule_time" "$message"
    
    echo "✅ Redémarrage de maintenance programmé pour $(date -j -f "%Y%m%d%H%M" "20$schedule_time" "+%Y-%m-%d %H:%M")"
    
    return 0
}

# Annuler les opérations programmées
cancel_scheduled_operation() {
    echo "=== Annulation des Opérations Programmées ==="
    
    # Obtenir la liste des opérations programmées
    local scheduled_ops
    scheduled_ops=$(ps aux | grep "shutdown" | grep -v grep | wc -l)
    
    if [[ $scheduled_ops -eq 0 ]]; then
        echo "ℹ️  Aucune opération d'arrêt/redémarrage programmée trouvée"
        return 0
    fi
    
    # Annuler les opérations d'arrêt
    if sudo pkill -f "shutdown"; then
        echo "✅ Opérations d'arrêt/redémarrage programmées annulées"
        log_action "Opérations d'arrêt/redémarrage programmées annulées"
        audit_log "SCHEDULE_CANCELLED" "SUCCESS" "Opérations annulées par $(whoami)"
        
        # Notifier les utilisateurs de l'annulation
        send_shutdown_notification "annulation" "0" "L'opération système programmée a été annulée"
    else
        echo "❌ Échec de l'annulation des opérations programmées"
        log_action "ÉCHEC : Impossible d'annuler les opérations programmées"
        audit_log "SCHEDULE_CANCELLED" "FAILED" "Tentative d'annulation par $(whoami)"
        return 1
    fi
    
    return 0
}

# Arrêt d'urgence (contourne toutes les vérifications)
emergency_shutdown() {
    local reason="$1"
    
    echo "🚨 ARRÊT D'URGENCE INITIÉ 🚨"
    
    if [[ -z "$reason" ]]; then
        echo "❌ Raison d'urgence requise"
        return 1
    fi
    
    log_action "ARRÊT D'URGENCE : Raison : $reason"
    audit_log "EMERGENCY_SHUTDOWN" "INITIATED" "Raison : $reason Utilisateur : $(whoami)"
    
    # Envoyer une notification d'urgence
    send_shutdown_notification "ARRÊT D'URGENCE" "0" "URGENCE : Arrêt système initié - $reason"
    
    # Exécuter l'arrêt immédiat forcé
    echo "🔌 Exécution de l'arrêt d'urgence (forcé)..."
    sudo shutdown -h now "ARRÊT D'URGENCE : $reason"
    
    audit_log "EMERGENCY_SHUTDOWN" "EXECUTED" "Arrêt immédiat terminé"
}

# Vérifier l'état du système pour la préparation à l'arrêt
check_system_status() {
    echo "=== Vérification de l'État du Système ==="
    
    local status_issues=()
    local status_warnings=()
    
    # Vérifier le temps de fonctionnement
    local uptime_seconds
    uptime_seconds=$(uptime | awk '{print $3}' | cut -d',' -f1)
    echo "Temps de Fonctionnement Système : $uptime_seconds"
    
    # Vérifier la charge moyenne
    local load_average
    load_average=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
    if (( $(echo "$load_average > 5.0" | bc -l) )); then
        status_warnings+=("Charge système élevée : $load_average")
    fi
    
    # Vérifier l'espace disque
    local disk_usage
    disk_usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
    if [[ $disk_usage -gt 90 ]]; then
        status_warnings+=("Espace disque faible : ${disk_usage}% utilisé")
    fi
    
    # Vérifier les mises à jour en attente
    if softwareupdate -l 2>/dev/null | grep -q "Software Update found"; then
        status_warnings+=("Mises à jour logicielles en attente disponibles")
    fi
    
    # Rapporter l'état
    if [[ ${#status_issues[@]} -eq 0 && ${#status_warnings[@]} -eq 0 ]]; then
        echo "✅ État du système : Prêt pour arrêt/redémarrage"
        return 0
    else
        if [[ ${#status_issues[@]} -gt 0 ]]; then
            echo "❌ Problèmes d'état du système :"
            printf '  - %s\n' "${status_issues[@]}"
        fi
        
        if [[ ${#status_warnings[@]} -gt 0 ]]; then
            echo "⚠️  Avertissements d'état du système :"
            printf '  - %s\n' "${status_warnings[@]}"
        fi
        
        return 1
    fi
}

# Fonction principale avec gestion d'arguments
main() {
    log_action "=== Outil de Gestion d'Arrêt Roundfleet Démarré ==="
    
    case "${1:-status}" in
        "shutdown")
            enterprise_shutdown "$2" "$3" "$4"
            ;;
        "reboot")
            enterprise_reboot "$2" "$3" "$4"
            ;;
        "schedule")
            schedule_maintenance_reboot "$2" "$3"
            ;;
        "cancel")
            cancel_scheduled_operation
            ;;
        "emergency")
            emergency_shutdown "$2"
            ;;
        "status")
            check_system_status
            ;;
        *)
            echo "Outil de Gestion d'Arrêt et de Redémarrage Entreprise Roundfleet"
            echo "Usage : $0 [commande] [options]"
            echo ""
            echo "Commandes :"
            echo "  shutdown [délai] [message] [force]  - Arrêter le système avec délai optionnel"
            echo "  reboot [délai] [message] [force]    - Redémarrer le système avec délai optionnel"
            echo "  schedule [heure] [raison]           - Programmer un redémarrage de maintenance (AAMMJJHHMM)"
            echo "  cancel                              - Annuler les opérations programmées"
            echo "  emergency [raison]                  - Arrêt d'urgence (contourne les vérifications)"
            echo "  status                              - Vérifier l'état du système pour préparation à l'arrêt"
            echo ""
            echo "Formats de Délai :"
            echo "  now                                 - Opération immédiate"
            echo "  +minutes                            - Délai en minutes (ex : +5)"
            echo ""
            echo "Exemples :"
            echo "  $0 shutdown now                     - Arrêt immédiat"
            echo "  $0 reboot +10 \"Maintenance système\" - Redémarrer dans 10 minutes avec message"
            echo "  $0 schedule 2501020300 \"Patch Tuesday\" - Programmer redémarrage 2 jan, 3h00"
            echo "  $0 emergency \"Incident de sécurité\" - Arrêt d'urgence"
            ;;
    esac
    
    log_action "=== Opération de gestion d'arrêt terminée ==="
}

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

Notes de Configuration Importantes

Options de Commande d'Arrêt macOS

  • -h - Arrêter le système (shutdown)
  • -r - Redémarrer le système (reboot)
  • -s - Mettre le système en veille (écran éteint + verrouillage)
  • Formats d'heure - now, +minutes, AAMMJJHHMM
  • Messages d'avertissement - Texte supplémentaire affiché aux utilisateurs

Points d'Intégration Entreprise

  • Systèmes de Gestion des Changements - Intégration avec les plateformes ITSM
  • Systèmes de Surveillance - Suivi en temps réel des événements d'arrêt
  • Solutions de Sauvegarde - Automatisation de sauvegarde pré-arrêt
  • Cadres de Sécurité - Conformité avec les politiques d'arrêt

Bonnes Pratiques pour la Gestion d'Arrêt Entreprise

  1. Continuité Opérationnelle

    • Implémenter des procédures d'arrêt en douceur avec notifications utilisateur
    • Valider la préparation du système avant les opérations d'arrêt
    • Maintenir des capacités de contournement d'urgence pour les situations critiques
    • Programmer les opérations de maintenance pendant les fenêtres désignées
  2. Sécurité et Conformité

    • Activer la journalisation d'audit complète pour toutes les opérations d'alimentation
    • Implémenter la protection des clés FileVault pendant l'arrêt
    • Valider les sessions utilisateur et les processus en cours avant l'arrêt
    • Maintenir la conformité avec les exigences réglementaires d'arrêt
  3. Gestion des Changements

    • Exiger l'approbation pour les opérations d'arrêt non programmées
    • Documenter tous les arrêts liés à la maintenance
    • Intégrer avec les plateformes ITSM pour le suivi des changements
    • Maintenir les informations de contact d'urgence pour les situations critiques
  4. Expérience Utilisateur

    • Fournir un avertissement adéquat avant les opérations d'arrêt
    • Tenter de sauvegarder le travail utilisateur avant l'arrêt système
    • Envoyer des notifications via plusieurs canaux (GUI, email, Slack)
    • Permettre l'annulation des opérations programmées le cas échéant

Dépannage des Problèmes Courants

  • Erreurs de permissions - S'assurer des privilèges administrateur pour les commandes d'arrêt
  • Conflits d'opérations programmées - Vérifier les arrêts programmés existants
  • Échecs de notification réseau - Vérifier les URLs webhook et la connectivité réseau
  • Échecs de sauvegarde - Vérifier l'espace disque et la disponibilité de destination de sauvegarde
  • Violations de fenêtre de maintenance - Examiner les heures de bureau et les horaires de maintenance

N'oubliez pas de tester minutieusement les procédures d'arrêt dans un environnement contrôlé avant l'implémentation sur l'ensemble de votre Roundfleet pour assurer la continuité des activités et la protection des données.

Gestion d'Entreprise des Utilisateurs de Partage sur macOS

Gérez les comptes utilisateurs de partage uniquement sur vos appareils Roundfleet en utilisant des commandes dscl avancées. Ce tutoriel couvre la création d'utilisateurs, les politiques de sécurité, le déploiement en masse et la gestion du cycle de vie des utilisateurs en entreprise.

Comprendre la Gestion d'Utilisateurs macOS

macOS utilise l'utilitaire de ligne de commande Directory Service (dscl) pour la gestion des utilisateurs :

  • dscl - Utilitaire de ligne de commande Directory Service
  • Répertoire Local - /var/db/dslocal/nodes/Default
  • Enregistrements Utilisateur - Stockés dans le chemin /Users/
  • Utilisateurs de Partage Uniquement - Comptes d'accès limité pour le partage de fichiers

Création d'Utilisateur de Partage de Base

Utilisateur de Partage Simple

#!/bin/bash

# Créer un compte utilisateur de partage uniquement de base
USERNAME="UtilisateurPartage"
DISPLAY_NAME="Compte de Partage"
PASSWORD="MotDePasseSecurise123"
USER_ID="550"

# Créer l'utilisateur
sudo dscl . create /Users/"$USERNAME"

# Définir le nom d'affichage
sudo dscl . create /Users/"$USERNAME" RealName "$DISPLAY_NAME"

# Définir le mot de passe
sudo dscl . passwd /Users/"$USERNAME" "$PASSWORD"

# Définir l'ID unique
sudo dscl . create /Users/"$USERNAME" UniqueID "$USER_ID"

# Définir l'ID de groupe (groupe staff)
sudo dscl . create /Users/"$USERNAME" PrimaryGroupID 20

# Refuser l'accès shell
sudo dscl . create /Users/"$USERNAME" UserShell /usr/bin/false

# Aucun répertoire home
sudo dscl . create /Users/"$USERNAME" NFSHomeDirectory /dev/null

echo "Utilisateur de partage '$USERNAME' créé avec succès"

Utilisateur de Partage Amélioré avec Options

#!/bin/bash

# Création d'utilisateur de partage améliorée avec options supplémentaires
create_sharing_user() {
    local username="$1"
    local display_name="$2"
    local password="$3"
    local hint="$4"
    local picture_path="$5"
    local user_id="$6"
    
    echo "Création de l'utilisateur de partage : $username"
    
    # Créer l'utilisateur
    sudo dscl . create /Users/"$username"
    
    # Définir le nom d'affichage
    sudo dscl . create /Users/"$username" RealName "$display_name"
    
    # Définir le mot de passe
    sudo dscl . passwd /Users/"$username" "$password"
    
    # Définir l'indice de mot de passe (optionnel)
    if [[ -n "$hint" ]]; then
        sudo dscl . create /Users/"$username" hint "$hint"
    fi
    
    # Définir l'image de profil (optionnel)
    if [[ -n "$picture_path" && -f "$picture_path" ]]; then
        sudo dscl . create /Users/"$username" picture "$picture_path"
    fi
    
    # Définir l'ID unique
    sudo dscl . create /Users/"$username" UniqueID "$user_id"
    
    # Définir l'ID de groupe
    sudo dscl . create /Users/"$username" PrimaryGroupID 20
    
    # Refuser l'accès shell
    sudo dscl . create /Users/"$username" UserShell /usr/bin/false
    
    # Aucun répertoire home
    sudo dscl . create /Users/"$username" NFSHomeDirectory /dev/null
    
    echo "✅ Utilisateur de partage '$username' créé avec succès"
    return 0
}

# Exemples d'utilisation
create_sharing_user "PartagerFichiers" "Compte de Partage de Fichiers" "FichierPass123" "Accès fichiers uniquement" "" "551"
create_sharing_user "AccesInvite" "Utilisateur Invité" "InvitePass456" "Accès temporaire" "/System/Library/User Pictures/Animals/Butterfly.tif" "552"

Catégories d'Utilisateurs d'Entreprise

Classifications de Types d'Utilisateurs

#!/bin/bash

# Catégories d'utilisateurs d'entreprise avec configurations spécifiques
declare -A USER_CATEGORIES=(
    ["partage_standard"]="Accès de partage de fichiers standard"
    ["partage_securise"]="Partage haute sécurité avec restrictions"
    ["invite_temporaire"]="Accès invité temporaire avec expiration"
    ["compte_service"]="Comptes de service pour applications"
    ["partage_departemental"]="Comptes partagés spécifiques au département"
    ["partenaire_externe"]="Accès limité partenaire externe"
    ["kiosque_public"]="Comptes d'accès kiosque public"
)

# Politiques de sécurité pour chaque catégorie
declare -A SECURITY_POLICIES=(
    ["partage_standard"]="politique_mot_de_passe:standard,niveau_audit:basique,delai_session:8h"
    ["partage_securise"]="politique_mot_de_passe:fort,niveau_audit:complet,delai_session:2h,mfa_requis:true"
    ["invite_temporaire"]="politique_mot_de_passe:basique,niveau_audit:complet,delai_session:1h,expiration_auto:24h"
    ["compte_service"]="politique_mot_de_passe:service,niveau_audit:systeme,non_interactif:true"
    ["partage_departemental"]="politique_mot_de_passe:departement,niveau_audit:departement,restrictions_groupe:true"
    ["partenaire_externe"]="politique_mot_de_passe:externe,niveau_audit:complet,restrictions_reseau:true"
    ["kiosque_public"]="politique_mot_de_passe:public,niveau_audit:minimal,delai_session:30m,reinitialisation_deconnexion:true"
)

# Définitions de contrôle d'accès
declare -A ACCESS_CONTROLS=(
    ["partage_standard"]="partage_fichiers:lecture_ecriture,acces_impression:oui,acces_reseau:local"
    ["partage_securise"]="partage_fichiers:lecture_seule,acces_impression:restreint,acces_reseau:vpn_seulement"
    ["invite_temporaire"]="partage_fichiers:dossier_invite,acces_impression:non,acces_reseau:wifi_invite"
    ["compte_service"]="partage_fichiers:repertoires_service,acces_impression:non,acces_reseau:ports_service"
    ["partage_departemental"]="partage_fichiers:repertoires_departement,acces_impression:departement,acces_reseau:vlan_departement"
    ["partenaire_externe"]="partage_fichiers:repertoires_partenaire,acces_impression:non,acces_reseau:dmz_partenaire"
    ["kiosque_public"]="partage_fichiers:documents_publics,acces_impression:public,acces_reseau:wifi_public"
)

print_user_categories() {
    echo "=== Catégories d'Utilisateurs Disponibles ==="
    for category in "${!USER_CATEGORIES[@]}"; do
        echo "Catégorie : $category"
        echo "  Description : ${USER_CATEGORIES[$category]}"
        echo "  Sécurité : ${SECURITY_POLICIES[$category]}"
        echo "  Accès : ${ACCESS_CONTROLS[$category]}"
        echo ""
    done
}

# Afficher les catégories disponibles
print_user_categories

Politiques de Gestion d'Utilisateurs

Moteur de Politique de Mot de Passe

#!/bin/bash

# Définitions de politiques de mot de passe pour différents types d'utilisateurs
generate_password_policy() {
    local policy_type="$1"
    
    case "$policy_type" in
        "standard")
            echo "longueur_min:8,complexite:moyenne,expiration:90j,historique:5"
            ;;
        "fort")
            echo "longueur_min:12,complexite:haute,expiration:60j,historique:10,caracteres_speciaux:requis"
            ;;
        "basique")
            echo "longueur_min:6,complexite:faible,expiration:jamais,historique:3"
            ;;
        "service")
            echo "longueur_min:16,complexite:haute,expiration:180j,historique:20,genere_machine:true"
            ;;
        "departement")
            echo "longueur_min:10,complexite:moyenne,expiration:120j,historique:8,prefixe_departement:requis"
            ;;
        "externe")
            echo "longueur_min:14,complexite:haute,expiration:30j,historique:15,validation_externe:requise"
            ;;
        "public")
            echo "longueur_min:4,complexite:aucune,expiration:quotidienne,historique:1,reinitialisation_auto:true"
            ;;
        *)
            echo "longueur_min:8,complexite:moyenne,expiration:90j,historique:5"
            ;;
    esac
}

# Générer un mot de passe sécurisé basé sur la politique
generate_secure_password() {
    local policy="$1"
    local length
    local complexity
    
    # Analyser la politique
    length=$(echo "$policy" | grep -o 'longueur_min:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexite:[a-z]*' | cut -d: -f2)
    
    case "$complexity" in
        "haute")
            # Haute complexité : majuscules, minuscules, chiffres, caractères spéciaux
            openssl rand -base64 $((length * 2)) | tr -d "=+/" | cut -c1-"$length" | sed 's/./&@1A/4'
            ;;
        "moyenne")
            # Complexité moyenne : majuscules, minuscules, chiffres
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
        "faible")
            # Faible complexité : alphanumérique
            openssl rand -hex "$((length/2))" | cut -c1-"$length"
            ;;
        *)
            # Complexité moyenne par défaut
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
    esac
}

# Valider le mot de passe contre la politique
validate_password() {
    local password="$1"
    local policy="$2"
    local min_length complexity
    
    min_length=$(echo "$policy" | grep -o 'longueur_min:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexite:[a-z]*' | cut -d: -f2)
    
    # Vérifier la longueur
    if [[ ${#password} -lt $min_length ]]; then
        echo "❌ Mot de passe trop court (minimum $min_length caractères)"
        return 1
    fi
    
    # Vérifier la complexité
    case "$complexity" in
        "haute")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] && "$password" =~ [^A-Za-z0-9] ]]; then
                echo "❌ Le mot de passe doit contenir majuscules, minuscules, chiffres et caractères spéciaux"
                return 1
            fi
            ;;
        "moyenne")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] ]]; then
                echo "❌ Le mot de passe doit contenir majuscules, minuscules et chiffres"
                return 1
            fi
            ;;
    esac
    
    echo "✅ Le mot de passe respecte les exigences de la politique"
    return 0
}

Profils de Déploiement d'Entreprise

Modèles de Configuration de Déploiement

#!/bin/bash

# Profils de déploiement d'entreprise pour différents besoins organisationnels
declare -A DEPLOYMENT_PROFILES=(
    ["entreprise_standard"]="Déploiement d'entreprise standard avec sécurité de base"
    ["haute_securite_finance"]="Déploiement haute sécurité pour départements financiers"
    ["acces_invite_accueil"]="Déploiement d'accès invité pour zones d'accueil/publiques"
    ["collaboration_partenaire"]="Déploiement de collaboration partenaire externe"
    ["kiosque_public_bibliotheque"]="Déploiement kiosque public pour bibliothèques/espaces publics"
    ["recherche_developpement"]="Déploiement équipe recherche et développement"
    ["executif_securise"]="Déploiement sécurisé niveau exécutif"
)

# Configurations spécifiques aux profils
get_deployment_config() {
    local profile="$1"
    
    case "$profile" in
        "entreprise_standard")
            cat << EOF
{
    "categorie_utilisateur": "partage_standard",
    "politique_mot_de_passe": "standard",
    "niveau_acces": "fichiers_departement",
    "delai_session": "8h",
    "niveau_audit": "basique",
    "appartenance_groupe": ["staff", "partage_fichiers"],
    "restrictions": {
        "acces_shell": false,
        "repertoire_home": false,
        "privileges_admin": false
    },
    "surveillance": {
        "suivi_connexion": true,
        "journal_acces_fichiers": true,
        "tentatives_echec": 5
    }
}
EOF
            ;;
        "haute_securite_finance")
            cat << EOF
{
    "categorie_utilisateur": "partage_securise",
    "politique_mot_de_passe": "fort",
    "niveau_acces": "finance_restreint",
    "delai_session": "2h",
    "niveau_audit": "complet",
    "appartenance_groupe": ["finance", "partage_securise"],
    "restrictions": {
        "acces_shell": false,
        "repertoire_home": false,
        "privileges_admin": false,
        "acces_reseau": "vlan_finance_seulement",
        "restrictions_horaires": "heures_bureau"
    },
    "securite": {
        "mfa_requis": true,
        "chiffrement": "aes256",
        "rotation_cles": "mensuelle"
    },
    "surveillance": {
        "alertes_temps_reel": true,
        "suivi_connexion": true,
        "journal_acces_fichiers": true,
        "tentatives_echec": 3,
        "rapport_conformite": "sox_hipaa"
    }
}
EOF
            ;;
        "acces_invite_accueil")
            cat << EOF
{
    "categorie_utilisateur": "invite_temporaire",
    "politique_mot_de_passe": "basique",
    "niveau_acces": "ressources_invite",
    "delai_session": "1h",
    "niveau_audit": "complet",
    "appartenance_groupe": ["invite", "acces_public"],
    "restrictions": {
        "acces_shell": false,
        "repertoire_home": false,
        "privileges_admin": false,
        "acces_internet": "wifi_invite_seulement",
        "telechargement_fichiers": false
    },
    "automatisation": {
        "expiration_auto": "24h",
        "nettoyage_auto": true,
        "reinitialisation_deconnexion": true
    },
    "surveillance": {
        "enregistrement_session": true,
        "suivi_connexion": true,
        "journal_activite": true,
        "tentatives_echec": 3
    }
}
EOF
            ;;
        *)
            echo "Profil de déploiement inconnu : $profile"
            return 1
            ;;
    esac
}

# Appliquer un profil de déploiement
apply_deployment_profile() {
    local profile="$1"
    local config_file="/tmp/deployment_config.json"
    
    echo "Application du profil de déploiement : $profile"
    
    # Obtenir la configuration
    get_deployment_config "$profile" > "$config_file"
    
    if [[ ! -f "$config_file" ]]; then
        echo "❌ Échec de génération de configuration pour le profil : $profile"
        return 1
    fi
    
    echo "✅ Configuration de déploiement prête"
    echo "Configuration sauvegardée dans : $config_file"
    
    # Analyser et afficher les paramètres clés
    echo "=== Résumé du Profil ==="
    echo "Catégorie Utilisateur : $(jq -r '.categorie_utilisateur' "$config_file")"
    echo "Politique Mot de Passe : $(jq -r '.politique_mot_de_passe' "$config_file")"
    echo "Niveau d'Accès : $(jq -r '.niveau_acces' "$config_file")"
    echo "Délai Session : $(jq -r '.delai_session' "$config_file")"
    echo "Niveau Audit : $(jq -r '.niveau_audit' "$config_file")"
    
    return 0
}

Système de Gestion d'Utilisateurs d'Entreprise

#!/bin/bash

# Système de Gestion d'Utilisateurs d'Entreprise Roundfleet
# Création et gestion complètes d'utilisateurs de partage

# Configuration
CONFIG_DIR="/etc/roundfleet/users"
LOG_FILE="/var/log/roundfleet_gestion_utilisateurs.log"
BACKUP_DIR="/var/backups/roundfleet/users"
REPORTS_DIR="/var/reports/roundfleet/users"
AUDIT_LOG="/var/log/roundfleet_audit_utilisateurs.log"

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

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

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

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

# Gestion d'ID utilisateur
get_next_user_id() {
    local start_id="$1"
    local current_id="$start_id"
    
    while dscl . list /Users UniqueID | awk '{print $2}' | grep -q "^${current_id}$"; do
        ((current_id++))
    done
    
    echo "$current_id"
}

# Fonction de création d'utilisateur complète
create_enterprise_user() {
    local username="$1"
    local display_name="$2"
    local user_category="$3"
    local deployment_profile="$4"
    local department="$5"
    local expiry_date="$6"
    
    log_action "Début création utilisateur : $username (Catégorie : $user_category, Profil : $deployment_profile)"
    
    # Valider les entrées
    if [[ -z "$username" || -z "$display_name" || -z "$user_category" ]]; then
        log_error "Paramètres requis manquants pour la création d'utilisateur"
        return 1
    fi
    
    # Vérifier si l'utilisateur existe déjà
    if dscl . read /Users/"$username" &>/dev/null; then
        log_error "L'utilisateur $username existe déjà"
        return 1
    fi
    
    # Obtenir la configuration de déploiement
    local config_file="/tmp/user_config_${username}.json"
    get_deployment_config "$deployment_profile" > "$config_file"
    
    # Analyser la configuration
    local password_policy
    password_policy=$(jq -r '.politique_mot_de_passe' "$config_file")
    
    # Obtenir le prochain ID utilisateur disponible
    local user_id
    user_id=$(get_next_user_id 550)
    
    # Générer un mot de passe sécurisé
    local policy_details
    policy_details=$(generate_password_policy "$password_policy")
    local password
    password=$(generate_secure_password "$policy_details")
    
    # Créer les métadonnées utilisateur
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    cat > "$metadata_file" << EOF
{
    "nom_utilisateur": "$username",
    "nom_affichage": "$display_name",
    "categorie_utilisateur": "$user_category",
    "profil_deploiement": "$deployment_profile",
    "departement": "$department",
    "id_utilisateur": $user_id,
    "date_creation": "$(date -Iseconds)",
    "cree_par": "$(whoami)",
    "date_expiration": "$expiry_date",
    "politique_mot_de_passe": "$password_policy",
    "statut": "actif"
}
EOF
    
    # Créer l'utilisateur
    log_action "Création de l'enregistrement utilisateur pour $username"
    sudo dscl . create /Users/"$username" || {
        log_error "Échec de création de l'enregistrement utilisateur pour $username"
        return 1
    }
    
    # Définir les propriétés de base
    sudo dscl . create /Users/"$username" RealName "$display_name"
    sudo dscl . passwd /Users/"$username" "$password"
    sudo dscl . create /Users/"$username" UniqueID "$user_id"
    sudo dscl . create /Users/"$username" PrimaryGroupID 20
    sudo dscl . create /Users/"$username" UserShell /usr/bin/false
    sudo dscl . create /Users/"$username" NFSHomeDirectory /dev/null
    
    # Ajouter des attributs personnalisés
    sudo dscl . create /Users/"$username" Comment "Utilisateur géré Roundfleet - $user_category"
    sudo dscl . create /Users/"$username" Keywords "roundfleet,$user_category,$deployment_profile,$department"
    
    # Définir la date d'expiration si fournie
    if [[ -n "$expiry_date" ]]; then
        sudo dscl . create /Users/"$username" ExpiryDate "$expiry_date"
    fi
    
    # Appliquer les appartenances de groupe
    local groups
    groups=$(jq -r '.appartenance_groupe[]' "$config_file" 2>/dev/null)
    while IFS= read -r group; do
        if [[ -n "$group" && "$group" != "null" ]]; then
            sudo dseditgroup -o edit -a "$username" -t user "$group" 2>/dev/null || {
                log_action "Le groupe $group n'existe pas, ignoré"
            }
        fi
    done <<< "$groups"
    
    # Stocker le mot de passe sécurisé (chiffré)
    echo "$password" | openssl enc -aes-256-cbc -pbkdf2 -k "roundfleet_$(hostname)" -out "$CONFIG_DIR/${username}_password.enc"
    
    # Créer une sauvegarde
    create_user_backup "$username"
    
    # Journalisation d'audit
    audit_log "Utilisateur créé : $username (UID : $user_id, Catégorie : $user_category, Profil : $deployment_profile)"
    
    log_action "✅ Utilisateur $username créé avec succès (UID : $user_id)"
    
    # Retourner le mot de passe pour communication initiale (en production, utiliser une livraison sécurisée)
    echo "INFO_UTILISATEUR_CREE:$username:$password:$user_id"
    
    return 0
}

# Création d'utilisateurs en masse
bulk_create_users() {
    local csv_file="$1"
    local created_count=0
    local failed_count=0
    
    if [[ ! -f "$csv_file" ]]; then
        log_error "Fichier CSV non trouvé : $csv_file"
        return 1
    fi
    
    log_action "Début création en masse d'utilisateurs depuis : $csv_file"
    
    # Traiter le fichier CSV (ignorer l'en-tête)
    tail -n +2 "$csv_file" | while IFS=',' read -r username display_name category profile department expiry; do
        if create_enterprise_user "$username" "$display_name" "$category" "$profile" "$department" "$expiry"; then
            ((created_count++))
        else
            ((failed_count++))
        fi
    done
    
    log_action "Création en masse terminée. Créés : $created_count, Échecs : $failed_count"
    
    # Générer un rapport
    generate_user_report "creation_masse_$(date +%Y%m%d_%H%M%S)"
}

# Fonctions de gestion d'utilisateurs
list_enterprise_users() {
    echo "=== Utilisateurs Gérés Roundfleet ==="
    echo "Nom d'utilisateur | Nom d'affichage | Catégorie | Statut | Créé"
    echo "------------------|-----------------|-----------|--------|------"
    
    for metadata_file in "$CONFIG_DIR"/*_metadata.json; do
        if [[ -f "$metadata_file" ]]; then
            local username display_name category status created_date
            username=$(jq -r '.nom_utilisateur' "$metadata_file")
            display_name=$(jq -r '.nom_affichage' "$metadata_file")
            category=$(jq -r '.categorie_utilisateur' "$metadata_file")
            status=$(jq -r '.statut' "$metadata_file")
            created_date=$(jq -r '.date_creation' "$metadata_file" | cut -d'T' -f1)
            
            printf "%-17s | %-15s | %-9s | %-6s | %s\n" "$username" "$display_name" "$category" "$status" "$created_date"
        fi
    done
}

# Suppression d'utilisateur avec nettoyage
remove_enterprise_user() {
    local username="$1"
    local backup_before_removal="$2"
    
    log_action "Début suppression de l'utilisateur : $username"
    
    # Vérifier si l'utilisateur existe
    if ! dscl . read /Users/"$username" &>/dev/null; then
        log_error "L'utilisateur $username n'existe pas"
        return 1
    fi
    
    # Créer une sauvegarde avant suppression
    if [[ "$backup_before_removal" == "true" ]]; then
        create_user_backup "$username"
    fi
    
    # Supprimer l'utilisateur du système
    sudo dscl . delete /Users/"$username" || {
        log_error "Échec de suppression de l'utilisateur $username du système"
        return 1
    }
    
    # Mettre à jour les métadonnées
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    if [[ -f "$metadata_file" ]]; then
        jq '.statut = "supprime" | .date_suppression = now | .supprime_par = "'"$(whoami)"'"' "$metadata_file" > "${metadata_file}.tmp" && mv "${metadata_file}.tmp" "$metadata_file"
    fi
    
    # Journalisation d'audit
    audit_log "Utilisateur supprimé : $username par $(whoami)"
    
    log_action "✅ Utilisateur $username supprimé avec succès"
    return 0
}

# Sauvegarde et restauration d'utilisateur
create_user_backup() {
    local username="$1"
    local backup_file="$BACKUP_DIR/${username}_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    log_action "Création de sauvegarde pour l'utilisateur : $username"
    
    # Exporter l'enregistrement utilisateur
    sudo dscl . read /Users/"$username" > "$backup_file"
    
    # Sauvegarder les métadonnées
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    if [[ -f "$metadata_file" ]]; then
        cp "$metadata_file" "$BACKUP_DIR/${username}_metadata_$(date +%Y%m%d_%H%M%S).json"
    fi
    
    log_action "✅ Sauvegarde utilisateur créée : $backup_file"
}

# Surveillance de la santé du système
monitor_user_system() {
    echo "=== Vérification de Santé du Système Utilisateur ==="
    
    # Vérifier les utilisateurs expirés
    local expired_users=0
    for metadata_file in "$CONFIG_DIR"/*_metadata.json; do
        if [[ -f "$metadata_file" ]]; then
            local expiry_date username
            expiry_date=$(jq -r '.date_expiration' "$metadata_file")
            username=$(jq -r '.nom_utilisateur' "$metadata_file")
            
            if [[ "$expiry_date" != "null" && "$expiry_date" != "" ]]; then
                if [[ $(date -d "$expiry_date" +%s 2>/dev/null) -lt $(date +%s) ]]; then
                    echo "⚠️  Utilisateur expiré : $username (expiré : $expiry_date)"
                    ((expired_users++))
                fi
            fi
        fi
    done
    
    # Vérifier les enregistrements d'utilisateurs orphelins
    local system_users
    system_users=$(dscl . list /Users | grep -E "^(Partage|Invite|Service|Externe)" || true)
    local orphaned_users=0
    
    while IFS= read -r user; do
        if [[ -n "$user" && ! -f "$CONFIG_DIR/${user}_metadata.json" ]]; then
            echo "⚠️  Utilisateur orphelin (pas de métadonnées) : $user"
            ((orphaned_users++))
        fi
    done <<< "$system_users"
    
    # Résumé
    echo ""
    echo "Résumé de Santé :"
    echo "  Utilisateurs expirés : $expired_users"
    echo "  Utilisateurs orphelins : $orphaned_users"
    
    if [[ $expired_users -eq 0 && $orphaned_users -eq 0 ]]; then
        echo "✅ Le système utilisateur est en bonne santé"
    else
        echo "⚠️  Le système utilisateur nécessite une attention"
    fi
}

# Générer des rapports complets
generate_user_report() {
    local report_name="$1"
    local report_file="$REPORTS_DIR/${report_name}.json"
    
    log_action "Génération du rapport utilisateur : $report_name"
    
    # Collecter les statistiques utilisateur
    local total_users active_users inactive_users
    total_users=$(find "$CONFIG_DIR" -name "*_metadata.json" | wc -l)
    active_users=$(grep -l '"statut": "actif"' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | wc -l)
    inactive_users=$((total_users - active_users))
    
    # Répartition par catégorie
    local categories
    categories=$(jq -r '.categorie_utilisateur' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | sort | uniq -c | awk '{print "{\"categorie\": \"" $2 "\", \"compte\": " $1 "}"}' | jq -s '.')
    
    # Générer le rapport
    cat > "$report_file" << EOF
{
    "nom_rapport": "$report_name",
    "date_generation": "$(date -Iseconds)",
    "genere_par": "$(whoami)",
    "nom_hote": "$(hostname)",
    "statistiques": {
        "total_utilisateurs": $total_users,
        "utilisateurs_actifs": $active_users,
        "utilisateurs_inactifs": $inactive_users
    },
    "repartition_categorie": $categories,
    "info_systeme": {
        "version_roundfleet": "2025.07.07",
        "version_os": "$(sw_vers -productVersion)",
        "nom_hote": "$(hostname)"
    }
}
EOF
    
    log_action "✅ Rapport généré : $report_file"
    echo "Rapport sauvegardé dans : $report_file"
}

# Fonctions de déploiement en flotte
deploy_to_fleet() {
    local fleet_config="$1"
    local user_config="$2"
    
    log_action "Début du déploiement en flotte"
    
    if [[ ! -f "$fleet_config" ]]; then
        log_error "Fichier de configuration de flotte non trouvé : $fleet_config"
        return 1
    fi
    
    if [[ ! -f "$user_config" ]]; then
        log_error "Fichier de configuration utilisateur non trouvé : $user_config"
        return 1
    fi
    
    # Lire la configuration de flotte
    local hosts
    hosts=$(jq -r '.hosts[]' "$fleet_config")
    
    # Déployer sur chaque hôte
    while IFS= read -r host; do
        if [[ -n "$host" ]]; then
            log_action "Déploiement sur l'hôte : $host"
            
            # Copier le script de gestion d'utilisateur et la configuration
            scp "$0" "$user_config" "root@${host}:/tmp/" || {
                log_error "Échec de copie des fichiers vers $host"
                continue
            }
            
            # Exécuter le déploiement sur l'hôte distant
            ssh "root@${host}" "chmod +x /tmp/$(basename "$0") && /tmp/$(basename "$0") deploy_from_config /tmp/$(basename "$user_config")" || {
                log_error "Échec d'exécution du déploiement sur $host"
                continue
            }
            
            log_action "✅ Déploiement terminé sur : $host"
        fi
    done <<< "$hosts"
    
    log_action "Déploiement en flotte terminé"
}

# Fonction principale avec routage de commandes
main() {
    local command="$1"
    shift
    
    # Initialiser
    create_directories
    
    case "$command" in
        "creer")
            create_enterprise_user "$@"
            ;;
        "creation_masse")
            bulk_create_users "$@"
            ;;
        "lister")
            list_enterprise_users
            ;;
        "supprimer")
            remove_enterprise_user "$@"
            ;;
        "sauvegarder")
            create_user_backup "$@"
            ;;
        "surveiller")
            monitor_user_system
            ;;
        "rapport")
            generate_user_report "$@"
            ;;
        "deployer_flotte")
            deploy_to_fleet "$@"
            ;;
        "afficher_categories")
            print_user_categories
            ;;
        "afficher_politiques")
            for policy in standard fort basique service departement externe public; do
                echo "Politique : $policy"
                echo "  $(generate_password_policy "$policy")"
                echo ""
            done
            ;;
        *)
            echo "Système de Gestion d'Utilisateurs d'Entreprise Roundfleet"
            echo "Utilisation : $0 <commande> [options]"
            echo ""
            echo "Commandes :"
            echo "  creer <nom_utilisateur> <nom_affichage> <categorie> <profil> [departement] [expiration]"
            echo "  creation_masse <fichier_csv>"
            echo "  lister"
            echo "  supprimer <nom_utilisateur> [sauvegarde_avant_suppression]"
            echo "  sauvegarder <nom_utilisateur>"
            echo "  surveiller"
            echo "  rapport <nom_rapport>"
            echo "  deployer_flotte <config_flotte> <config_utilisateur>"
            echo "  afficher_categories"
            echo "  afficher_politiques"
            echo ""
            echo "Exemples :"
            echo "  $0 creer PartagerFichiers 'Compte de Partage de Fichiers' partage_standard entreprise_standard IT"
            echo "  $0 creation_masse utilisateurs.csv"
            echo "  $0 lister"
            echo "  $0 surveiller"
            echo "  $0 rapport audit_mensuel"
            ;;
    esac
}

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

Exemple de Déploiement en Flotte

Modèle CSV pour Création en Masse

nom_utilisateur,nom_affichage,categorie,profil,departement,expiration
PartagerFichiers01,Compte de Partage de Fichiers 1,partage_standard,entreprise_standard,IT,
InviteAccueil,Accès Invité Accueil,invite_temporaire,acces_invite_accueil,Reception,2025-12-31
PartenaireExt,Accès Partenaire Externe,partage_securise,collaboration_partenaire,Legal,2025-09-30
KiosqueBib,Compte Kiosque Bibliothèque,kiosque_public,kiosque_public_bibliotheque,Public,
PartageFinance,Compte Partagé Finance,partage_securise,haute_securite_finance,Finance,
EquipeDev,Partage Équipe Développement,partage_standard,recherche_developpement,Ingenierie,

Exemple de Configuration de Flotte

{
    "nom_flotte": "Roundfleet Entreprise",
    "date_deploiement": "2025-07-07",
    "hotes": [
        "mac-bureau-01.entreprise.com",
        "mac-bureau-02.entreprise.com",
        "mac-conference-01.entreprise.com"
    ],
    "profil_deploiement": "entreprise_standard",
    "politique_securite": "standard_entreprise",
    "surveillance": {
        "active": true,
        "intervalle_rapport": "quotidien",
        "seuil_alerte": "haute"
    }
}

Considérations de Sécurité

Sécurité des Comptes Utilisateur

  • Pas d'Accès Shell - Les utilisateurs de partage ne peuvent pas accéder à la ligne de commande
  • Pas de Répertoire Home - Empêche le stockage de fichiers dans les répertoires utilisateur
  • Appartenance de Groupe Limitée - Restreint l'accès système
  • Politiques de Mot de Passe - Applique des exigences de mot de passe fort
  • Journalisation d'Audit - Suit toutes les activités de gestion d'utilisateur

Conformité d'Entreprise

  • Conformité SOX - Contrôles d'accès utilisateur financier
  • Conformité HIPAA - Protection des données de santé
  • Cadre NIST - Implémentation des contrôles de sécurité
  • ISO 27001 - Gestion de la sécurité de l'information

Guide de Dépannage

Problèmes Courants

Échec de Création d'Utilisateur

  • Vérifier si l'ID utilisateur est déjà utilisé
  • Vérifier les privilèges administratifs
  • S'assurer que les services d'annuaire fonctionnent

Problèmes d'Authentification

  • Vérifier la conformité à la politique de mot de passe
  • Vérifier le statut du compte utilisateur
  • Examiner les journaux d'audit pour les tentatives échouées

Erreurs de Permission

  • Confirmer les appartenances de groupe
  • Vérifier les permissions de partage de fichiers
  • Vérifier l'application de la politique de sécurité

Commandes de Diagnostic

# Vérifier l'existence de l'utilisateur
dscl . read /Users/nom_utilisateur

# Lister tous les utilisateurs
dscl . list /Users

# Vérifier les groupes utilisateur
groups nom_utilisateur

# Voir les propriétés utilisateur
id nom_utilisateur

Notes Importantes

  • Tester minutieusement avant le déploiement en flotte
  • Sauvegarder les données utilisateur avant d'apporter des modifications
  • Surveiller les journaux d'audit pour les événements de sécurité
  • Mettre à jour les politiques selon les exigences de sécurité
  • Documenter les changements pour l'audit de conformité
  • Utiliser des méthodes de livraison de mot de passe sécurisées en production

Exécuter l'Assistant de configuration sur les appareils macOS au prochain redémarrage

Ce guide complet démontre comment déclencher l'Assistant de configuration macOS au prochain redémarrage de l'appareil, permettant la reconfiguration des appareils, l'intégration des utilisateurs et les flux de déploiement d'entreprise.

Aperçu

L'Assistant de configuration est l'assistant de configuration intégré de macOS qui guide les utilisateurs dans la configuration initiale de l'appareil. Il peut être déclenché manuellement pour divers scénarios d'entreprise :

  • Reconfiguration d'appareils : Réinitialiser les appareils à un état proche de l'usine tout en préservant les données
  • Intégration d'utilisateurs : Rationaliser la configuration des appareils pour les nouveaux employés
  • Déploiement de masse : Standardiser la configuration des appareils dans les organisations
  • Dépannage : Réinitialiser les configurations système sans effacement complet de l'appareil
  • Conformité : S'assurer que les appareils répondent aux exigences de configuration organisationnelle

Déclenchement de base de l'Assistant de configuration

Script simple pour l'Assistant de configuration

Créez un script de base pour déclencher l'Assistant de configuration au prochain redémarrage :

#!/bin/bash

# Script de déclenchement de base de l'Assistant de configuration
# Utilisation : ./declencher_assistant_config.sh

declencher_assistant_config() {
    # Vérifier si le script est exécuté en tant que root
    if [ "$(id -u)" != "0" ]; then
        echo "Erreur : Ce script doit être exécuté en tant que root"
        exit 1
    fi
    
    # Vérifier si le fichier .AppleSetupDone existe
    if [ ! -f "/private/var/db/.AppleSetupDone" ]; then
        echo "Fichier marqueur de l'Assistant de configuration non trouvé. L'Assistant de configuration pourrait déjà être programmé pour s'exécuter."
        exit 0
    fi
    
    # Supprimer le fichier .AppleSetupDone
    sudo rm /private/var/db/.AppleSetupDone
    
    if [ $? -eq 0 ]; then
        echo "L'Assistant de configuration s'exécutera au prochain redémarrage."
        echo "Veuillez redémarrer l'appareil pour commencer l'Assistant de configuration."
    else
        echo "Erreur : Impossible de supprimer le fichier marqueur de l'Assistant de configuration."
        exit 1
    fi
}

# Exécuter la fonction
declencher_assistant_config

Assistant de configuration avancé avec validation

#!/bin/bash

# Assistant de configuration avancé avec validation et journalisation
# Utilisation : ./assistant_config_avance.sh

assistant_config_avance() {
    local fichier_log="/var/log/roundfleet_assistant_config.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local fichier_config_termine="/private/var/db/.AppleSetupDone"
    local nom_ordinateur=$(scutil --get ComputerName)
    
    # Vérifier si le script est exécuté en tant que root
    if [ "$EUID" -ne 0 ]; then
        echo "Erreur : Ce script doit être exécuté en tant que root"
        exit 1
    fi
    
    # Créer le répertoire de log s'il n'existe pas
    mkdir -p /var/log
    
    # Enregistrer le début de l'opération
    echo "[$timestamp] Démarrage du déclenchement de l'Assistant de configuration sur $nom_ordinateur" >> "$fichier_log"
    
    # Vérifier la compatibilité de la version macOS
    local version_os=$(sw_vers -productVersion)
    local version_majeure=$(echo "$version_os" | cut -d. -f1)
    
    if [ "$version_majeure" -ge 14 ]; then
        echo "[$timestamp] ATTENTION : macOS $version_os détecté. Le déclenchement de l'Assistant de configuration pourrait ne pas fonctionner sur macOS 14+" >> "$fichier_log"
        echo "Attention : Ce script est pris en charge sur les versions macOS inférieures à 14. Version actuelle : $version_os"
        read -p "Voulez-vous continuer quand même ? (o/N) : " continuer_quand_meme
        if [ "$continuer_quand_meme" != "o" ] && [ "$continuer_quand_meme" != "O" ]; then
            echo "[$timestamp] Opération annulée par l'utilisateur en raison de la compatibilité de version" >> "$fichier_log"
            echo "Opération annulée."
            exit 0
        fi
    fi
    
    # Vérifier si le fichier marqueur de l'Assistant de configuration existe
    if [ ! -f "$fichier_config_termine" ]; then
        echo "[$timestamp] Fichier marqueur de l'Assistant de configuration non trouvé à $fichier_config_termine" >> "$fichier_log"
        echo "Fichier marqueur de l'Assistant de configuration non trouvé. L'Assistant de configuration pourrait déjà être programmé pour s'exécuter."
        echo "Emplacement du fichier : $fichier_config_termine"
        exit 0
    fi
    
    # Obtenir les informations du fichier avant suppression
    local info_fichier=$(ls -la "$fichier_config_termine" 2>/dev/null)
    echo "[$timestamp] Informations actuelles du fichier marqueur : $info_fichier" >> "$fichier_log"
    
    # Créer une sauvegarde du fichier marqueur
    local repertoire_sauvegarde="/var/backups/roundfleet"
    mkdir -p "$repertoire_sauvegarde"
    cp "$fichier_config_termine" "$repertoire_sauvegarde/.AppleSetupDone.sauvegarde.$(date +%Y%m%d_%H%M%S)" 2>/dev/null
    
    # Supprimer le fichier .AppleSetupDone
    rm "$fichier_config_termine"
    
    # Vérifier la suppression
    if [ ! -f "$fichier_config_termine" ]; then
        echo "[$timestamp] Fichier marqueur de l'Assistant de configuration supprimé avec succès" >> "$fichier_log"
        echo "L'Assistant de configuration a été configuré pour s'exécuter au prochain redémarrage."
        echo ""
        echo "Informations sur l'appareil :"
        echo "  Nom de l'ordinateur : $nom_ordinateur"
        echo "  Version macOS : $version_os"
        echo "  Horodatage : $timestamp"
        echo ""
        echo "Prochaines étapes :"
        echo "  1. Redémarrer l'appareil pour commencer l'Assistant de configuration"
        echo "  2. Suivre les instructions à l'écran pour configurer l'appareil"
        echo "  3. L'Assistant de configuration vous guidera à travers la langue, la région, les comptes et autres paramètres"
        echo ""
        echo "Note : Toutes les données utilisateur et applications existantes resteront intactes."
    else
        echo "[$timestamp] ERREUR : Impossible de supprimer le fichier marqueur de l'Assistant de configuration" >> "$fichier_log"
        echo "Erreur : Impossible de supprimer le fichier marqueur de l'Assistant de configuration."
        echo "Veuillez vérifier les permissions et réessayer."
        exit 1
    fi
}

# Exécuter la configuration avancée
assistant_config_avance

Gestion avancée de l'Assistant de configuration

Déclenchement conditionnel de l'Assistant de configuration

#!/bin/bash

# Déclenchement conditionnel de l'Assistant de configuration avec plusieurs scénarios
# Utilisation : ./assistant_config_conditionnel.sh [scenario]

assistant_config_conditionnel() {
    local scenario=${1:-"defaut"}
    local fichier_log="/var/log/roundfleet_assistant_config.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Vérifier si le script est exécuté en tant que root
    if [ "$EUID" -ne 0 ]; then
        echo "Erreur : Ce script doit être exécuté en tant que root"
        exit 1
    fi
    
    echo "[$timestamp] Déclenchement conditionnel de l'Assistant de configuration - Scénario : $scenario" >> "$fichier_log"
    
    case $scenario in
        "nouvel_employe")
            declencher_config_nouvel_employe
            ;;
        "actualisation_appareil")
            declencher_config_actualisation_appareil
            ;;
        "reinitialisation_conformite")
            declencher_reinitialisation_conformite
            ;;
        "depannage")
            declencher_config_depannage
            ;;
        "deploiement_masse")
            declencher_config_deploiement_masse
            ;;
        "defaut")
            declencher_config_defaut
            ;;
        *)
            echo "Scénario inconnu : $scenario"
            echo "Scénarios disponibles : nouvel_employe, actualisation_appareil, reinitialisation_conformite, depannage, deploiement_masse, defaut"
            exit 1
            ;;
    esac
}

declencher_config_nouvel_employe() {
    echo "Configuration de l'Assistant de configuration pour l'intégration d'un nouvel employé..."
    
    # Supprimer le marqueur de l'Assistant de configuration
    rm -f /private/var/db/.AppleSetupDone
    
    echo "[$timestamp] Configuration nouvel employé - Assistant de configuration configuré" >> "$fichier_log"
    
    cat << 'EOF'
Assistant de configuration configuré pour l'intégration d'un nouvel employé.

Les éléments suivants seront présentés à l'utilisateur :
• Sélection de la langue et de la région
• Configuration du réseau Wi-Fi
• Connexion avec l'Apple ID
• Création d'un compte utilisateur
• Paramètres de confidentialité et de sécurité
• Configuration de Touch ID (si disponible)
• Préférences d'apparence du bureau

Veuillez redémarrer l'appareil et le fournir au nouvel employé.
EOF
}

declencher_config_actualisation_appareil() {
    echo "Configuration de l'Assistant de configuration pour l'actualisation d'appareil..."
    
    # Vérifier si les données utilisateur doivent être préservées
    local repertoires_utilisateur=$(ls /Users | grep -v "Shared" | grep -v "Guest" | head -5)
    if [ -n "$repertoires_utilisateur" ]; then
        echo "Comptes utilisateur existants détectés :"
        echo "$repertoires_utilisateur"
        echo ""
        read -p "Préserver les données utilisateur existantes ? (O/n) : " preserver_donnees
        
        if [ "$preserver_donnees" = "n" ] || [ "$preserver_donnees" = "N" ]; then
            echo "Attention : Cela supprimera les données utilisateur lors de l'actualisation."
            read -p "Êtes-vous sûr ? (o/N) : " confirmer
            if [ "$confirmer" != "o" ] && [ "$confirmer" != "O" ]; then
                echo "Opération annulée."
                return 1
            fi
        fi
    fi
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Configuration actualisation appareil - Assistant de configuration configuré" >> "$fichier_log"
    
    echo "Assistant de configuration configuré pour l'actualisation d'appareil."
    echo "Redémarrez l'appareil pour commencer le processus de reconfiguration."
}

declencher_reinitialisation_conformite() {
    echo "Configuration de l'Assistant de configuration pour la réinitialisation de conformité..."
    
    # Enregistrer la réinitialisation de conformité
    echo "[$timestamp] Réinitialisation de conformité initiée - Assistant de configuration déclenché" >> "$fichier_log"
    
    # Supprimer le marqueur de l'Assistant de configuration
    rm -f /private/var/db/.AppleSetupDone
    
    cat << 'EOF'
Assistant de configuration configuré pour la réinitialisation de conformité.

Cela garantira que l'appareil répond aux exigences de conformité organisationnelle :
• Forcer la re-acceptation des termes et politiques
• Vérifier les configurations des comptes utilisateur
• Confirmer les paramètres de sécurité
• Mettre à jour les préférences de confidentialité
• Valider les paramètres organisationnels

Redémarrez l'appareil pour commencer la vérification de conformité.
EOF
}

declencher_config_depannage() {
    echo "Configuration de l'Assistant de configuration pour le dépannage..."
    
    # Créer un rapport de dépannage
    local rapport_depannage="/tmp/rapport_depannage_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$rapport_depannage" << EOF
Rapport de dépannage Roundfleet
Généré : $(date)
Appareil : $(scutil --get ComputerName)
Version macOS : $(sw_vers -productVersion)

Problèmes que l'Assistant de configuration peut résoudre :
• Problèmes de configuration des comptes utilisateur
• Corruption des préférences système
• Problèmes de configuration réseau
• Problèmes d'authentification Apple ID
• Incohérences des paramètres de confidentialité

L'Assistant de configuration sera déclenché au prochain redémarrage.
EOF
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Configuration dépannage - Assistant de configuration configuré" >> "$fichier_log"
    
    echo "Assistant de configuration configuré pour le dépannage."
    echo "Rapport de dépannage sauvegardé à : $rapport_depannage"
    echo "Redémarrez l'appareil pour commencer le processus de configuration."
}

declencher_config_deploiement_masse() {
    echo "Configuration de l'Assistant de configuration pour le déploiement de masse..."
    
    # Obtenir le numéro de série de l'appareil pour le suivi
    local numero_serie=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    
    # Enregistrer le déploiement
    echo "[$timestamp] Configuration déploiement de masse - Appareil : $numero_serie" >> "$fichier_log"
    
    rm -f /private/var/db/.AppleSetupDone
    
    cat << EOF
Assistant de configuration configuré pour le déploiement de masse.

Numéro de série de l'appareil : $numero_serie
Date de déploiement : $(date)

La configuration standardisée inclura :
• Langue : Français
• Région : France
• Réseau : Wi-Fi d'entreprise
• Compte : Compte utilisateur standard
• Sécurité : Politiques de sécurité d'entreprise
• Applications : Applications d'entreprise standard

L'appareil est prêt pour le déploiement. Redémarrez pour commencer la configuration.
EOF
}

declencher_config_defaut() {
    echo "Configuration de l'Assistant de configuration avec les paramètres par défaut..."
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Configuration par défaut - Assistant de configuration configuré" >> "$fichier_log"
    
    echo "Assistant de configuration configuré avec les paramètres par défaut."
    echo "Redémarrez l'appareil pour commencer le processus de configuration."
}

# Exécution principale
if [ $# -eq 0 ]; then
    echo "Utilisation : $0 [scenario]"
    echo "Scénarios disponibles :"
    echo "  nouvel_employe        - Configurer pour l'intégration d'un nouvel employé"
    echo "  actualisation_appareil - Configurer pour l'actualisation/reconfiguration d'appareil"
    echo "  reinitialisation_conformite - Configurer pour la vérification de conformité"
    echo "  depannage             - Configurer pour le dépannage"
    echo "  deploiement_masse     - Configurer pour le déploiement de masse"
    echo "  defaut                - Configurer avec les paramètres par défaut"
    echo ""
    assistant_config_conditionnel "defaut"
else
    assistant_config_conditionnel "$1"
fi

Automatisation et surveillance de l'Assistant de configuration

Gestionnaire d'entreprise de l'Assistant de configuration

#!/bin/bash

# Gestionnaire d'entreprise de l'Assistant de configuration
# Utilisation : ./gestionnaire_entreprise_assistant.sh

gestionnaire_entreprise_assistant() {
    local fichier_config="/etc/roundfleet/config_assistant_configuration.conf"
    local fichier_log="/var/log/roundfleet_assistant_config.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Vérifier si le script est exécuté en tant que root
    if [ "$EUID" -ne 0 ]; then
        echo "Erreur : Ce script doit être exécuté en tant que root"
        exit 1
    fi
    
    # Créer le répertoire de configuration
    mkdir -p /etc/roundfleet
    
    # Charger ou créer la configuration
    if [ -f "$fichier_config" ]; then
        source "$fichier_config"
    else
        creer_config_entreprise
        source "$fichier_config"
    fi
    
    echo "[$timestamp] Gestionnaire d'entreprise de l'Assistant de configuration démarré" >> "$fichier_log"
    
    # Afficher le menu de configuration
    afficher_menu_entreprise
}

creer_config_entreprise() {
    cat > "/etc/roundfleet/config_assistant_configuration.conf" << 'EOF'
# Configuration de l'Assistant de configuration d'entreprise Roundfleet

# Informations de l'organisation
NOM_ORGANISATION="Organisation Roundfleet"
EMAIL_CONTACT_IT="[email protected]"
TELEPHONE_CONTACT_IT="1-800-ROUNDFLEET"

# Configuration par défaut
LANGUE_DEFAUT="Français"
REGION_DEFAUT="France"
NECESSITER_APPLE_ID="false"
ACTIVER_SERVICES_LOCALISATION="false"
ACTIVER_SIRI="false"
NECESSITER_ACCEPTATION_TERMES="true"

# Paramètres de sécurité
NECESSITER_MOT_PASSE_FORT="true"
ACTIVER_FILEVAULT="true"
NECESSITER_TOUCH_ID="true"

# Paramètres de déploiement
MODE_DEPLOIEMENT="entreprise"
IGNORER_ETAPES_OPTIONNELLES="true"
AUTO_CONFIGURER_RESEAU="true"
EOF
    
    echo "Configuration d'entreprise créée à /etc/roundfleet/config_assistant_configuration.conf"
}

afficher_menu_entreprise() {
    while true; do
        clear
        echo "======================================="
        echo "Assistant de configuration d'entreprise Roundfleet"
        echo "======================================="
        echo ""
        echo "Organisation : $NOM_ORGANISATION"
        echo "Contact : $EMAIL_CONTACT_IT"
        echo ""
        echo "Actions disponibles :"
        echo "1. Déclencher l'Assistant de configuration (Appareil unique)"
        echo "2. Préparer le déploiement de masse"
        echo "3. Configurer les options de l'Assistant"
        echo "4. Voir le statut de l'Assistant de configuration"
        echo "5. Générer un rapport de déploiement"
        echo "6. Sauvegarder/Restaurer l'état de configuration"
        echo "7. Voir la configuration"
        echo "8. Quitter"
        echo ""
        read -p "Sélectionnez une option (1-8) : " choix
        
        case $choix in
            1)
                declencher_config_appareil_unique
                ;;
            2)
                preparer_deploiement_masse
                ;;
            3)
                configurer_options_assistant
                ;;
            4)
                voir_statut_assistant
                ;;
            5)
                generer_rapport_deploiement
                ;;
            6)
                sauvegarder_restaurer_config
                ;;
            7)
                voir_configuration
                ;;
            8)
                echo "Fermeture du gestionnaire d'entreprise de l'Assistant de configuration."
                exit 0
                ;;
            *)
                echo "Option invalide. Veuillez réessayer."
                ;;
        esac
        
        echo ""
        read -p "Appuyez sur Entrée pour continuer..."
    done
}

declencher_config_appareil_unique() {
    echo "======================================="
    echo "Déclencher l'Assistant de configuration - Appareil unique"
    echo "======================================="
    
    local nom_appareil=$(scutil --get ComputerName)
    local numero_serie=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    
    echo "Appareil : $nom_appareil"
    echo "Numéro de série : $numero_serie"
    echo ""
    
    read -p "Confirmer le déclenchement de l'Assistant de configuration sur cet appareil ? (o/N) : " confirmer
    if [ "$confirmer" = "o" ] || [ "$confirmer" = "O" ]; then
        # Supprimer le marqueur de l'Assistant de configuration
        if rm -f /private/var/db/.AppleSetupDone; then
            echo "[$timestamp] Configuration appareil unique déclenchée - $nom_appareil ($numero_serie)" >> "$fichier_log"
            echo "Assistant de configuration configuré avec succès."
            echo "Veuillez redémarrer l'appareil pour commencer la configuration."
        else
            echo "Erreur : Impossible de configurer l'Assistant de configuration."
        fi
    else
        echo "Opération annulée."
    fi
}

preparer_deploiement_masse() {
    echo "======================================="
    echo "Préparer le déploiement de masse"
    echo "======================================="
    
    read -p "Entrez le nombre d'appareils pour le déploiement : " nombre_appareils
    read -p "Entrez le nom du lot de déploiement : " nom_lot
    
    local repertoire_deploiement="/var/roundfleet/deploiements/$nom_lot"
    mkdir -p "$repertoire_deploiement"
    
    # Créer le package de déploiement
    cat > "$repertoire_deploiement/deployer_assistant_config.sh" << 'EOF'
#!/bin/bash
# Déclencheur de l'Assistant de configuration pour déploiement de masse Roundfleet
# Script de déploiement auto-généré

# Vérifier si le script est exécuté en tant que root
if [ "$EUID" -ne 0 ]; then
    echo "Erreur : Ce script doit être exécuté en tant que root"
    exit 1
fi

# Supprimer le marqueur de l'Assistant de configuration
rm -f /private/var/db/.AppleSetupDone

# Enregistrer le déploiement
echo "$(date '+%Y-%m-%d %H:%M:%S') - Configuration déploiement de masse déclenchée sur $(scutil --get ComputerName)" >> /var/log/roundfleet_deploiement_masse.log

echo "Assistant de configuration configuré pour le déploiement de masse."
echo "Redémarrez l'appareil pour commencer le processus de configuration."
EOF
    
    chmod +x "$repertoire_deploiement/deployer_assistant_config.sh"
    
    # Créer le manifeste de déploiement
    cat > "$repertoire_deploiement/manifeste_deploiement.txt" << EOF
Manifeste de déploiement de masse Roundfleet
Nom du lot : $nom_lot
Nombre d'appareils : $nombre_appareils
Créé : $(date)
Organisation : $NOM_ORGANISATION

Instructions de déploiement :
1. Copier deployer_assistant_config.sh sur chaque appareil
2. Exécuter le script en tant que root sur chaque appareil
3. Redémarrer les appareils pour commencer l'Assistant de configuration
4. Suivre les procédures de configuration standard

Contact : $EMAIL_CONTACT_IT
EOF
    
    echo "Package de déploiement de masse créé à : $repertoire_deploiement"
    echo "Script de déploiement : $repertoire_deploiement/deployer_assistant_config.sh"
    echo "Manifeste : $repertoire_deploiement/manifeste_deploiement.txt"
}

configurer_options_assistant() {
    echo "======================================="
    echo "Configurer les options de l'Assistant"
    echo "======================================="
    
    echo "Configuration actuelle :"
    echo "  Langue : $LANGUE_DEFAUT"
    echo "  Région : $REGION_DEFAUT"
    echo "  Nécessiter Apple ID : $NECESSITER_APPLE_ID"
    echo "  Activer les services de localisation : $ACTIVER_SERVICES_LOCALISATION"
    echo "  Activer Siri : $ACTIVER_SIRI"
    echo ""
    
    read -p "Modifier la configuration ? (o/N) : " modifier
    if [ "$modifier" = "o" ] || [ "$modifier" = "O" ]; then
        echo "La modification de la configuration nécessiterait une configuration supplémentaire..."
        echo "Veuillez modifier : /etc/roundfleet/config_assistant_configuration.conf"
    fi
}

voir_statut_assistant() {
    echo "======================================="
    echo "Statut de l'Assistant de configuration"
    echo "======================================="
    
    local fichier_config_termine="/private/var/db/.AppleSetupDone"
    local nom_appareil=$(scutil --get ComputerName)
    local version_os=$(sw_vers -productVersion)
    
    echo "Appareil : $nom_appareil"
    echo "Version macOS : $version_os"
    echo "Horodatage : $(date)"
    echo ""
    
    if [ -f "$fichier_config_termine" ]; then
        echo "Statut : Assistant de configuration TERMINÉ"
        echo "Fichier : $fichier_config_termine existe"
        echo "Modifié : $(stat -f "%Sm" "$fichier_config_termine")"
        echo ""
        echo "L'Assistant de configuration ne s'exécutera PAS au prochain redémarrage."
    else
        echo "Statut : Assistant de configuration PROGRAMMÉ"
        echo "Fichier : $fichier_config_termine n'existe pas"
        echo ""
        echo "L'Assistant de configuration s'exécutera au prochain redémarrage."
    fi
}

generer_rapport_deploiement() {
    echo "======================================="
    echo "Générer un rapport de déploiement"
    echo "======================================="
    
    local fichier_rapport="/tmp/rapport_roundfleet_assistant_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$fichier_rapport" << EOF
Rapport de déploiement de l'Assistant de configuration Roundfleet
Généré : $(date)
Organisation : $NOM_ORGANISATION

Informations sur l'appareil :
  Nom de l'ordinateur : $(scutil --get ComputerName)
  Numéro de série : $(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
  Version macOS : $(sw_vers -productVersion)
  Modèle matériel : $(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)

Statut de l'Assistant de configuration :
EOF
    
    if [ -f "/private/var/db/.AppleSetupDone" ]; then
        echo "  Statut : Terminé" >> "$fichier_rapport"
        echo "  Dernière exécution : $(stat -f "%Sm" "/private/var/db/.AppleSetupDone")" >> "$fichier_rapport"
    else
        echo "  Statut : Programmé pour le prochain redémarrage" >> "$fichier_rapport"
    fi
    
    cat >> "$fichier_rapport" << EOF

Configuration :
  Langue par défaut : $LANGUE_DEFAUT
  Région par défaut : $REGION_DEFAUT
  Mode de déploiement : $MODE_DEPLOIEMENT
  Contact : $EMAIL_CONTACT_IT

Entrées de log récentes :
EOF
    
    if [ -f "/var/log/roundfleet_assistant_config.log" ]; then
        tail -10 "/var/log/roundfleet_assistant_config.log" >> "$fichier_rapport"
    else
        echo "  Aucune entrée de log trouvée" >> "$fichier_rapport"
    fi
    
    echo "Rapport de déploiement généré : $fichier_rapport"
}

sauvegarder_restaurer_config() {
    echo "======================================="
    echo "Sauvegarder/Restaurer l'état de configuration"
    echo "======================================="
    
    echo "1. Sauvegarder l'état actuel de l'Assistant de configuration"
    echo "2. Restaurer l'état de l'Assistant de configuration"
    echo ""
    read -p "Sélectionnez une option (1-2) : " option_sauvegarde
    
    case $option_sauvegarde in
        1)
            sauvegarder_etat_config
            ;;
        2)
            restaurer_etat_config
            ;;
        *)
            echo "Option invalide."
            ;;
    esac
}

sauvegarder_etat_config() {
    local repertoire_sauvegarde="/var/backups/roundfleet"
    local timestamp=$(date +%Y%m%d_%H%M%S)
    
    mkdir -p "$repertoire_sauvegarde"
    
    if [ -f "/private/var/db/.AppleSetupDone" ]; then
        cp "/private/var/db/.AppleSetupDone" "$repertoire_sauvegarde/.AppleSetupDone.sauvegarde.$timestamp"
        echo "État de l'Assistant de configuration sauvegardé à : $repertoire_sauvegarde/.AppleSetupDone.sauvegarde.$timestamp"
    else
        echo "Aucun état de l'Assistant de configuration à sauvegarder (fichier n'existe pas)."
    fi
}

restaurer_etat_config() {
    local repertoire_sauvegarde="/var/backups/roundfleet"
    
    if [ -d "$repertoire_sauvegarde" ]; then
        echo "Sauvegardes disponibles :"
        ls -la "$repertoire_sauvegarde"/.AppleSetupDone.sauvegarde.* 2>/dev/null || echo "Aucune sauvegarde trouvée."
        echo ""
        read -p "Entrez le nom du fichier de sauvegarde à restaurer : " fichier_sauvegarde
        
        if [ -f "$repertoire_sauvegarde/$fichier_sauvegarde" ]; then
            cp "$repertoire_sauvegarde/$fichier_sauvegarde" "/private/var/db/.AppleSetupDone"
            echo "État de l'Assistant de configuration restauré depuis : $fichier_sauvegarde"
        else
            echo "Fichier de sauvegarde non trouvé."
        fi
    else
        echo "Aucun répertoire de sauvegarde trouvé."
    fi
}

voir_configuration() {
    echo "======================================="
    echo "Configuration actuelle"
    echo "======================================="
    
    if [ -f "/etc/roundfleet/config_assistant_configuration.conf" ]; then
        cat "/etc/roundfleet/config_assistant_configuration.conf"
    else
        echo "Aucun fichier de configuration trouvé."
    fi
}

# Exécuter le gestionnaire d'entreprise
gestionnaire_entreprise_assistant

Dépannage et bonnes pratiques

Problèmes courants et solutions

1. Compatibilité de version macOS

# Vérifier la version macOS avant l'exécution
version_os=$(sw_vers -productVersion)
version_majeure=$(echo "$version_os" | cut -d. -f1)

if [ "$version_majeure" -ge 14 ]; then
    echo "Attention : Ce script pourrait ne pas fonctionner sur macOS 14 ou ultérieur"
    echo "Version actuelle : $version_os"
fi

2. Problèmes de permissions

# S'assurer que le script s'exécute avec les privilèges appropriés
if [ "$EUID" -ne 0 ]; then
    echo "Erreur : Ce script doit être exécuté en tant que root"
    echo "Veuillez utiliser : sudo $0"
    exit 1
fi

3. Protection du système de fichiers

# Vérifier si la protection d'intégrité du système affecte l'opération
csrutil status | grep -q "enabled"
if [ $? -eq 0 ]; then
    echo "Note : SIP est activé. Cela pourrait affecter le fonctionnement du script."
fi

Bonnes pratiques pour la gestion de l'Assistant de configuration

  1. Compatibilité de version : Toujours vérifier la compatibilité de version macOS avant le déploiement
  2. Communication utilisateur : Notifier les utilisateurs avant de déclencher l'Assistant de configuration
  3. Sauvegarde de données : Créer des sauvegardes avant les changements de configuration majeurs
  4. Tests : Tester les scripts dans des environnements contrôlés avant le déploiement de masse
  5. Journalisation : Maintenir des logs détaillés de toutes les opérations de l'Assistant de configuration
  6. Plans de retour : Préparer des procédures de retour en arrière pour les échecs de déploiement

Considérations de déploiement d'entreprise

  • Planification : Planifier les déploiements pendant les fenêtres de maintenance
  • Impact utilisateur : Considérer les flux de travail des utilisateurs et minimiser les perturbations
  • Exigences réseau : S'assurer d'une connectivité réseau adéquate pour les services Apple
  • Sécurité : Implémenter des mesures de sécurité appropriées pour les déploiements automatisés
  • Conformité : S'assurer que les déploiements respectent les exigences de conformité organisationnelle

Conclusion

La gestion de l'Assistant de configuration est un outil puissant pour l'administration des appareils macOS. Ces scripts fournissent des solutions complètes pour déclencher, gérer et automatiser l'Assistant de configuration dans les flottes Mac. Des déclencheurs simples pour un seul appareil à l'automatisation d'entreprise complexe, ces outils permettent une gestion efficace des appareils tout en maintenant l'expérience utilisateur et la conformité organisationnelle.

N'oubliez pas de tester tous les scripts de manière approfondie dans des environnements contrôlés avant le déploiement en production, et de toujours maintenir des sauvegardes appropriées des configurations système. La surveillance régulière et la journalisation garantissent des déploiements réussis de l'Assistant de configuration et aident à identifier les problèmes potentiels avant qu'ils n'affectent les utilisateurs.

Configurer l'Économiseur d'Écran sur macOS

Apprenez à configurer et déployer des économiseurs d'écran sur Mac à l'aide de scripts. Cela vous permet de définir des styles de diaporama personnalisés, des temps d'inactivité et des sources de photos sur votre flotte Mac.

Configuration Basique d'Économiseur d'Écran

Configurez un économiseur d'écran de diaporama avec paramètres personnalisés :

#!/bin/bash

# Configuration économiseur d'écran
STYLE="Ken Burns"
IDLE_TIME=300  # 5 minutes en secondes
SHUFFLE_PHOTOS=true
PHOTOS_PATH="/System/Library/Screen Savers/Default Collections/1-National Geographic"

# Définir le style d'économiseur d'écran
defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "$STYLE"

# Définir le temps d'inactivité avant activation
defaults -currentHost write com.apple.screensaver idleTime -int $IDLE_TIME

# Configurer le mélange des photos
defaults -currentHost write com.apple.screensaver ShufflePhotos -bool $SHUFFLE_PHOTOS

# Définir le chemin du dossier photos
defaults -currentHost write com.apple.screensaver PhotosFolderPath "$PHOTOS_PATH"

echo "Économiseur d'écran configuré : Style=$STYLE, TempInactivité=${IDLE_TIME}s"

Styles d'Économiseur d'Écran Disponibles

Choisissez parmi les styles de diaporama intégrés d'Apple :

#!/bin/bash

# Styles d'économiseur d'écran disponibles
STYLES=(
    "Floating"
    "Flip-up"
    "Reflections"
    "Origami"
    "Shifting Tiles"
    "Sliding Panels"
    "Photo Mobile"
    "Holiday Mobile"
    "Photo Wall"
    "Vintage Prints"
    "Ken Burns"
    "Classic"
)

# Fonction pour définir le style d'économiseur d'écran
set_screen_saver_style() {
    local style="$1"
    local idle_time="${2:-600}"  # Défaut 10 minutes
    local photos_path="${3:-/System/Library/Screen Savers/Default Collections}"
    
    echo "Configuration économiseur d'écran : $style"
    
    # Configurer l'économiseur d'écran
    defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "$style"
    defaults -currentHost write com.apple.screensaver idleTime -int $idle_time
    defaults -currentHost write com.apple.screensaver PhotosFolderPath "$photos_path"
    
    echo "Économiseur d'écran configuré avec succès"
}

# Exemple : Définir style Ken Burns avec temps d'inactivité de 5 minutes
set_screen_saver_style "Ken Burns" 300 "/Users/Shared/ScreenSaver Photos"

Gestionnaire d'Économiseur d'Écran Interactif

Script avec interface conviviale pour la configuration :

#!/bin/bash

# Fonction pour afficher les styles disponibles
show_styles() {
    echo "Styles d'Économiseur d'Écran Disponibles :"
    echo "1. Floating"
    echo "2. Flip-up"
    echo "3. Reflections"
    echo "4. Origami"
    echo "5. Shifting Tiles"
    echo "6. Sliding Panels"
    echo "7. Photo Mobile"
    echo "8. Holiday Mobile"
    echo "9. Photo Wall"
    echo "10. Vintage Prints"
    echo "11. Ken Burns"
    echo "12. Classic"
}

# Fonction pour configurer l'économiseur d'écran
configure_screen_saver() {
    local style="$1"
    local idle_minutes="$2"
    local shuffle="$3"
    local photos_folder="$4"
    
    local idle_seconds=$((idle_minutes * 60))
    
    # Définir toutes les options de configuration
    defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "$style"
    defaults -currentHost write com.apple.screensaver idleTime -int $idle_seconds
    defaults -currentHost write com.apple.screensaver ShufflePhotos -bool $shuffle
    defaults -currentHost write com.apple.screensaver PhotosFolderPath "$photos_folder"
    
    # Fermer Préférences Système pour forcer la mise à jour
    killall "System Preferences" 2>/dev/null || true
    
    echo "✓ Économiseur d'écran configuré :"
    echo "  Style : $style"
    echo "  Temps d'inactivité : $idle_minutes minutes"
    echo "  Mélanger photos : $shuffle"
    echo "  Dossier photos : $photos_folder"
}

# Configuration par défaut
STYLE="Ken Burns"
IDLE_MINUTES=10
SHUFFLE_PHOTOS=true
PHOTOS_FOLDER="/System/Library/Screen Savers/Default Collections/1-National Geographic"

# Configurer avec les valeurs par défaut
configure_screen_saver "$STYLE" "$IDLE_MINUTES" "$SHUFFLE_PHOTOS" "$PHOTOS_FOLDER"

Déploiement d'Économiseur d'Écran Entreprise

Déployez des paramètres d'économiseur d'écran standardisés sur plusieurs appareils :

#!/bin/bash

# Configuration économiseur d'écran d'entreprise
CORPORATE_CONFIG() {
    # Configuration de marque d'entreprise
    local style="Classic"
    local idle_time=600  # 10 minutes
    local photos_path="/Library/Desktop Pictures/Corporate"
    local shuffle=false
    
    echo "Déploiement des paramètres économiseur d'écran d'entreprise..."
    
    # Créer le répertoire photos d'entreprise s'il n'existe pas
    if [[ ! -d "$photos_path" ]]; then
        sudo mkdir -p "$photos_path"
        echo "Répertoire photos d'entreprise créé : $photos_path"
    fi
    
    # Appliquer les paramètres
    defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "$style"
    defaults -currentHost write com.apple.screensaver idleTime -int $idle_time
    defaults -currentHost write com.apple.screensaver ShufflePhotos -bool $shuffle
    defaults -currentHost write com.apple.screensaver PhotosFolderPath "$photos_path"
    
    # Désactiver l'exigence de mot de passe pour l'environnement d'entreprise
    defaults write com.apple.screensaver askForPassword -int 0
    
    echo "Configuration économiseur d'écran d'entreprise appliquée"
    echo "Style : $style | Inactivité : ${idle_time}s | Mélange : $shuffle"
}

# Appliquer la configuration d'entreprise
CORPORATE_CONFIG

Statut et Gestion de l'Économiseur d'Écran

Vérifiez les paramètres actuels de l'économiseur d'écran et gérez la configuration :

#!/bin/bash

# Fonction pour afficher les paramètres actuels de l'économiseur d'écran
show_current_settings() {
    echo "=== Paramètres Actuels de l'Économiseur d'Écran ==="
    
    # Obtenir le style actuel
    local current_style=$(defaults -currentHost read com.apple.screensaver moduleDict 2>/dev/null | grep moduleName | cut -d'"' -f4)
    
    # Obtenir le temps d'inactivité
    local idle_time=$(defaults -currentHost read com.apple.screensaver idleTime 2>/dev/null)
    
    # Obtenir le paramètre de mélange
    local shuffle=$(defaults -currentHost read com.apple.screensaver ShufflePhotos 2>/dev/null)
    
    # Obtenir le chemin des photos
    local photos_path=$(defaults -currentHost read com.apple.screensaver PhotosFolderPath 2>/dev/null)
    
    echo "Style : ${current_style:-Non défini}"
    echo "Temps d'inactivité : ${idle_time:-Non défini} secondes"
    echo "Mélanger photos : ${shuffle:-Non défini}"
    echo "Dossier photos : ${photos_path:-Non défini}"
}

# Fonction pour désactiver l'économiseur d'écran
disable_screen_saver() {
    defaults -currentHost write com.apple.screensaver idleTime -int 0
    echo "Économiseur d'écran désactivé (temps d'inactivité défini à 0)"
}

# Fonction pour activer l'économiseur d'écran avec paramètres par défaut
enable_screen_saver() {
    defaults -currentHost write com.apple.screensaver idleTime -int 600
    defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "Ken Burns"
    echo "Économiseur d'écran activé avec paramètres par défaut"
}

# Afficher les paramètres actuels
show_current_settings

Utilisation avec Roundfleet

  1. Choisissez votre style d'économiseur d'écran préféré parmi les options disponibles
  2. Définissez le temps d'inactivité en secondes (0 désactive l'économiseur d'écran)
  3. Configurez le mélange des photos et le chemin du dossier source
  4. Déployez via l'exécution de script distant Roundfleet
  5. Surveillez le déploiement dans l'historique des actions

Chemins Photos Communs

EmplacementChemin
Collections par Défaut/System/Library/Screen Savers/Default Collections
Images de Bureau/Library/Desktop Pictures
Images Utilisateur/Users/nomutilisateur/Pictures
Dossier Partagé/Users/Shared/ScreenSaver Photos

Dépannage

Paramètres non appliqués : Fermez Préférences Système et redémarrez pour actualiser les paramètres Photos non affichées : Vérifiez que le chemin du dossier existe et contient des fichiers image Économiseur d'écran ne s'active pas : Vérifiez le paramètre de temps d'inactivité et les préférences de veille du système


Note : Les modifications prennent effet immédiatement mais peuvent nécessiter de redémarrer Préférences Système pour voir dans l'interface graphique. Testez la configuration avant le déploiement en masse.