Guide

Nouvelles mises à jour et améliorations de Macfleet.

Récupérer les Journaux d'Appareils sur macOS

macOS fournit un système de journalisation unifié puissant qui capture des informations détaillées sur les processus système, applications et activités utilisateur. Ce tutoriel montre comment collecter et analyser efficacement les journaux d'appareils dans votre MacFleet pour le dépannage, la surveillance de sécurité et l'analyse de performance.

Comprendre la Journalisation macOS

macOS utilise le système de journalisation unifié introduit dans macOS 10.12, qui consolide diverses sources de journaux :

  • Journaux système - Noyau, services système et démons
  • Journaux d'applications - Applications utilisateur et processus d'arrière-plan
  • Journaux de sécurité - Authentification, autorisation et événements de sécurité
  • Journaux réseau - Activité réseau et connectivité

Commandes de Journal de Base

Voir les Journaux Système Récents

#!/bin/bash

# Afficher les journaux de la dernière minute
sudo log show --last 1m

# Afficher les journaux de la dernière heure
sudo log show --last 1h

# Afficher les journaux du dernier jour
sudo log show --last 1d

Diffusion de Journaux en Direct

#!/bin/bash

# Diffuser les journaux en direct
sudo log stream

# Diffuser avec horodatage
sudo log stream --info --debug

Journaux Spécifiques aux Applications

Obtenir les Journaux pour une Application Spécifique

#!/bin/bash

# Requête de journal d'app basique
log show --predicate 'processImagePath CONTAINS[c] "safari"'

# Requête avec plage de temps
log show --predicate 'processImagePath CONTAINS[c] "Finder"' --last 30m

# Sauvegarder les journaux d'app dans un fichier
log show --predicate 'processImagePath CONTAINS[c] "Mail"' --last 1h > ~/Desktop/mail_logs.txt

Script de Collection de Journaux Entreprise

#!/bin/bash

# Script de Collection de Journaux d'Appareils pour MacFleet
# Compatible avec macOS 10.14+

# Configuration
LOG_DIR="/var/log/macfleet_logs"
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
HOSTNAME=$(hostname -s)
OUTPUT_DIR="$LOG_DIR/${HOSTNAME}_${TIMESTAMP}"
ARCHIVE_NAME="${HOSTNAME}_logs_${TIMESTAMP}.tar.gz"

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

# Fonction pour créer le répertoire de sortie
setup_directories() {
    if mkdir -p "$OUTPUT_DIR"; then
        log_message "✓ Répertoire de sortie créé : $OUTPUT_DIR"
        return 0
    else
        log_message "✗ Échec de la création du répertoire de sortie"
        return 1
    fi
}

# Fonction pour collecter les journaux système
collect_system_logs() {
    log_message "Collecte des journaux système..."
    
    # Journaux système récents (dernières 24 heures)
    if log show --last 24h > "$OUTPUT_DIR/system_logs_24h.log"; then
        log_message "✓ Journaux système collectés (24h)"
    else
        log_message "✗ Échec de la collecte des journaux système"
    fi
    
    # Journaux critiques et d'erreur uniquement
    if log show --last 24h --predicate 'messageType == 16 OR messageType == 17' > "$OUTPUT_DIR/critical_errors.log"; then
        log_message "✓ Journaux critiques/erreurs collectés"
    else
        log_message "✗ Échec de la collecte des journaux critiques"
    fi
    
    # Journaux de démarrage
    if log show --predicate 'process == "kernel"' --last 7d > "$OUTPUT_DIR/kernel_logs.log"; then
        log_message "✓ Journaux du noyau collectés"
    else
        log_message "✗ Échec de la collecte des journaux du noyau"
    fi
}

# Fonction pour collecter les journaux d'applications
collect_app_logs() {
    log_message "Collecte des journaux d'applications..."
    
    # Applications communes à surveiller
    local apps=("Safari" "Finder" "Mail" "Calendar" "Contacts" "Notes" "Spotlight" "WindowServer")
    
    for app in "${apps[@]}"; do
        local output_file="$OUTPUT_DIR/${app,,}_logs.log"
        if log show --predicate "processImagePath CONTAINS[c] \"$app\"" --last 24h > "$output_file" 2>/dev/null; then
            # Garder le fichier seulement s'il a du contenu
            if [[ -s "$output_file" ]]; then
                log_message "✓ Journaux $app collectés"
            else
                rm -f "$output_file"
                log_message "! Aucun journal trouvé pour $app"
            fi
        else
            log_message "✗ Échec de la collecte des journaux $app"
        fi
    done
}

# Fonction pour collecter les journaux de sécurité
collect_security_logs() {
    log_message "Collecte des journaux de sécurité..."
    
    # Journaux d'authentification
    if log show --predicate 'category == "authorization" OR process == "authd"' --last 7d > "$OUTPUT_DIR/auth_logs.log"; then
        log_message "✓ Journaux d'authentification collectés"
    else
        log_message "✗ Échec de la collecte des journaux d'auth"
    fi
    
    # Événements de connexion/déconnexion
    if log show --predicate 'eventMessage CONTAINS "login" OR eventMessage CONTAINS "logout"' --last 7d > "$OUTPUT_DIR/login_events.log"; then
        log_message "✓ Événements de connexion collectés"
    else
        log_message "✗ Échec de la collecte des événements de connexion"
    fi
}

# Fonction pour collecter les informations système
collect_system_info() {
    log_message "Collecte des informations système..."
    
    {
        echo "=== Informations Système ==="
        echo "Nom d'hôte : $(hostname)"
        echo "Version macOS : $(sw_vers -productVersion)"
        echo "Build : $(sw_vers -buildVersion)"
        echo "Uptime : $(uptime)"
        echo "Date : $(date)"
        echo ""
        
        echo "=== Informations Matériel ==="
        system_profiler SPHardwareDataType
        echo ""
        
        echo "=== Usage Disque ==="
        df -h
        echo ""
        
        echo "=== Usage Mémoire ==="
        vm_stat
        echo ""
        
        echo "=== Processus en Cours ==="
        ps aux | head -20
        
    } > "$OUTPUT_DIR/system_info.txt"
    
    log_message "✓ Informations système collectées"
}

# Fonction pour créer une archive
create_archive() {
    log_message "Création de l'archive..."
    
    cd "$LOG_DIR" || return 1
    
    if tar -czf "$ARCHIVE_NAME" "$(basename "$OUTPUT_DIR")"; then
        log_message "✓ Archive créée : $LOG_DIR/$ARCHIVE_NAME"
        
        # Nettoyer le répertoire temporaire
        rm -rf "$OUTPUT_DIR"
        log_message "✓ Fichiers temporaires nettoyés"
        
        # Afficher la taille de l'archive
        local size
        size=$(du -h "$LOG_DIR/$ARCHIVE_NAME" | cut -f1)
        log_message "Taille de l'archive : $size"
        
        return 0
    else
        log_message "✗ Échec de la création de l'archive"
        return 1
    fi
}

# Fonction pour télécharger l'archive (placeholder pour intégration entreprise)
upload_archive() {
    local archive_path="$LOG_DIR/$ARCHIVE_NAME"
    
    # Exemple : Télécharger vers serveur de journalisation central
    # Remplacer par votre mécanisme de téléchargement actuel
    log_message "Archive prête pour collecte : $archive_path"
    
    # Placeholder pour logique de téléchargement
    # scp "$archive_path" user@logserver:/logs/
    # curl -F "file=@$archive_path" https://logserver.company.com/upload
    
    return 0
}

# Fonction d'exécution principale
main() {
    log_message "=== Début de la collecte de journaux MacFleet ==="
    
    # Configuration
    if ! setup_directories; then
        exit 1
    fi
    
    # Collecter les journaux
    collect_system_logs
    collect_app_logs
    collect_security_logs
    collect_system_info
    
    # Créer l'archive
    if create_archive; then
        upload_archive
        log_message "=== Collecte de journaux terminée avec succès ==="
        exit 0
    else
        log_message "=== Échec de la collecte de journaux ==="
        exit 1
    fi
}

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

Scripts de Collection de Journaux Rapide

Collecter les Journaux pour une Période Spécifique

#!/bin/bash

# Collecter les journaux entre des dates spécifiques
START_DATE="2025-01-01"
END_DATE="2025-01-02"
OUTPUT_FILE="~/Desktop/logs_${START_DATE}_to_${END_DATE}.txt"

log show --start "$START_DATE" --end "$END_DATE" > "$OUTPUT_FILE"
echo "Journaux sauvegardés dans : $OUTPUT_FILE"

Collecter les Journaux de Crash d'Applications

#!/bin/bash

# Collecter les rapports de crash
CRASH_DIR="~/Library/Logs/DiagnosticReports"
OUTPUT_DIR="~/Desktop/crash_logs"

mkdir -p "$OUTPUT_DIR"
find "$CRASH_DIR" -name "*.crash" -mtime -7 -exec cp {} "$OUTPUT_DIR/" \;

echo "Journaux de crash récents copiés dans : $OUTPUT_DIR"

Surveiller des Événements Spécifiques

#!/bin/bash

# Surveiller les connexions de périphériques USB
log stream --predicate 'eventMessage CONTAINS "USB"' --info

# Surveiller les changements réseau
log stream --predicate 'subsystem == "com.apple.network"' --info

# Surveiller les événements du système de fichiers
log stream --predicate 'subsystem == "com.apple.filesystem"' --debug

Scripts d'Analyse de Journaux

Analyser les Événements d'Authentification

#!/bin/bash

# Extraire les tentatives de connexion échouées
log show --predicate 'eventMessage CONTAINS "authentication failure"' --last 7d \
    | grep -E "(authentication failure|failed)" \
    | sort | uniq -c | sort -nr > ~/Desktop/failed_logins.txt

echo "Analyse des connexions échouées sauvegardée dans ~/Desktop/failed_logins.txt"

Statistiques d'Usage d'Applications

#!/bin/bash

# Analyser les lancements d'applications
log show --predicate 'process == "launchd" AND eventMessage CONTAINS "spawn"' --last 24h \
    | grep -oE '"[^"]*\.app"' \
    | sort | uniq -c | sort -nr > ~/Desktop/app_usage.txt

echo "Statistiques d'usage d'applications sauvegardées dans ~/Desktop/app_usage.txt"

Gestion des Archives de Journaux

Créer une Archive de Journal Système

#!/bin/bash

# Créer une archive complète des journaux système
ARCHIVE_PATH="~/Desktop/SystemLogs_$(date +%Y%m%d_%H%M%S).logarchive"

log collect --output "$ARCHIVE_PATH" --last 24h

echo "Archive des journaux système créée : $ARCHIVE_PATH"

Voir les Journaux Archivés

#!/bin/bash

# Voir les journaux depuis l'archive
ARCHIVE_PATH="~/Desktop/SystemLogs.logarchive"

if [[ -f "$ARCHIVE_PATH" ]]; then
    log show --archive "$ARCHIVE_PATH" --last 1h
else
    echo "Archive non trouvée : $ARCHIVE_PATH"
fi

Dépannage des Problèmes Courants

ProblèmeSolution
Permission refuséeExécuter avec sudo pour les journaux système
Aucun journal trouvéVérifier la plage de dates et les prédicats
Gros fichiers de journauxUtiliser des filtres de temps et prédicats spécifiques
Timeouts de scriptRéduire la plage de temps ou utiliser la collecte asynchrone
Corruption d'archiveVérifier l'espace disque et les permissions

Exemples de Filtrage de Journaux

Filtrer par Niveau de Journal

# Messages d'erreur uniquement
log show --predicate 'messageType == 16' --last 1h

# Messages info et debug
log show --predicate 'messageType >= 1' --last 30m

# Erreurs critiques uniquement
log show --predicate 'messageType == 17' --last 24h

Filtrer par Processus

# Processus système
log show --predicate 'process == "kernel" OR process == "launchd"' --last 1h

# Processus utilisateur
log show --predicate 'processImagePath BEGINSWITH "/Applications"' --last 1h

# Démons d'arrière-plan
log show --predicate 'processImagePath CONTAINS "daemon"' --last 1h

Considérations de Sécurité

  • Confidentialité - Être attentif aux données utilisateur dans les journaux
  • Rétention - Implémenter la rotation et le nettoyage des journaux
  • Contrôle d'accès - Restreindre l'accès aux journaux au personnel autorisé
  • Chiffrement - Chiffrer les archives de journaux avant transmission
  • Conformité - Suivre les politiques de rétention des données

Conseils de Performance

  • Utiliser des plages de temps spécifiques pour limiter le volume de données
  • Filtrer par processus ou catégorie pour réduire le bruit
  • Diffuser les journaux en temps réel pour une analyse immédiate
  • Compresser les archives pour économiser l'espace de stockage
  • Programmer la collecte régulière de journaux pendant les heures creuses

Notes Importantes

  • Les journaux système peuvent contenir des informations sensibles
  • Les grandes plages de temps peuvent générer des fichiers de journaux massifs
  • Certains journaux nécessitent des privilèges admin pour l'accès
  • La collecte de journaux peut impacter les performances système
  • Tester les scripts sur des appareils individuels avant le déploiement de flotte

Vider la Corbeille sur macOS

Apprenez à vider à distance les corbeilles sur Mac à l'aide de scripts. Cela aide à libérer de l'espace disque et gérer le stockage efficacement sur votre flotte Mac.

Vider la Corbeille d'un Utilisateur Spécifique

Supprimer tous les éléments de la corbeille d'un utilisateur spécifique :

#!/bin/bash

# Spécifier le nom d'utilisateur
USERNAME="john"

# Vider la corbeille pour un utilisateur spécifique
sudo rm -rf /Users/"${USERNAME}"/.Trash/*

echo "Corbeille vidée pour l'utilisateur : ${USERNAME}"

Vider la Corbeille de l'Utilisateur Actuel

Détecter automatiquement et vider la corbeille de l'utilisateur actuellement connecté :

#!/bin/bash

# Obtenir l'utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)

# Vider la corbeille pour l'utilisateur actuel
su "$CURRENT_USER" -c "rm -rf ~/.Trash/*"

echo "Corbeille vidée pour l'utilisateur actuel : ${CURRENT_USER}"

Script Avancé avec Validation

Script avec gestion d'erreur et journalisation :

#!/bin/bash

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

# Obtenir l'utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)

if [[ -z "$CURRENT_USER" ]]; then
    log_message "Erreur : Impossible de déterminer l'utilisateur actuel"
    exit 1
fi

log_message "Vidage de la corbeille pour l'utilisateur : ${CURRENT_USER}"

# Vérifier si le répertoire corbeille existe
TRASH_DIR="/Users/${CURRENT_USER}/.Trash"
if [[ ! -d "$TRASH_DIR" ]]; then
    log_message "Répertoire corbeille non trouvé : ${TRASH_DIR}"
    exit 1
fi

# Compter les éléments avant suppression
ITEM_COUNT=$(find "$TRASH_DIR" -mindepth 1 -maxdepth 1 | wc -l)
log_message "Trouvé ${ITEM_COUNT} éléments dans la corbeille"

if [[ $ITEM_COUNT -eq 0 ]]; then
    log_message "La corbeille est déjà vide"
    exit 0
fi

# Vider la corbeille
if su "$CURRENT_USER" -c "rm -rf ~/.Trash/*"; then
    log_message "Corbeille vidée avec succès pour ${CURRENT_USER}"
else
    log_message "Échec du vidage de la corbeille"
    exit 1
fi

Gestion Corbeille Multi-Utilisateurs

Vider la corbeille pour tous les utilisateurs du système :

#!/bin/bash

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

log_message "Démarrage du nettoyage corbeille multi-utilisateurs"

# Trouver tous les répertoires utilisateurs
for USER_DIR in /Users/*; do
    if [[ -d "$USER_DIR" && ! "$USER_DIR" =~ /Users/(Shared|Guest) ]]; then
        USERNAME=$(basename "$USER_DIR")
        TRASH_DIR="$USER_DIR/.Trash"
        
        if [[ -d "$TRASH_DIR" ]]; then
            ITEM_COUNT=$(find "$TRASH_DIR" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l)
            
            if [[ $ITEM_COUNT -gt 0 ]]; then
                log_message "Vidage corbeille pour utilisateur : ${USERNAME} (${ITEM_COUNT} éléments)"
                sudo rm -rf "$TRASH_DIR"/*
                log_message "Nettoyage corbeille terminé pour : ${USERNAME}"
            else
                log_message "Corbeille déjà vide pour utilisateur : ${USERNAME}"
            fi
        fi
    fi
done

log_message "Nettoyage corbeille multi-utilisateurs terminé"

Utilisation avec MacFleet

  1. Choisissez le script approprié selon vos besoins
  2. Pour des utilisateurs spécifiques, modifiez la variable USERNAME
  3. Déployez via l'exécution de script distant MacFleet
  4. Surveillez les résultats dans l'historique des actions

Prérequis

  • Accès Disque Complet : Accordez l'accès disque complet à l'agent MacFleet dans Réglages Système > Confidentialité et Sécurité > Accès Disque Complet
  • Privilèges administrateur : Les scripts nécessitent un accès sudo pour les opérations système

Considérations de Sécurité

  • Vérifiez les permissions utilisateur avant d'exécuter les scripts
  • Considérez sauvegarder les fichiers importants avant suppression de corbeille en masse
  • Testez sur un nombre limité d'appareils avant déploiement flotte

Dépannage

Permission refusée : Assurez-vous que l'agent MacFleet a l'Accès Disque Complet Utilisateur non trouvé : Vérifiez que le nom d'utilisateur existe sur l'appareil cible Échec du script : Vérifiez si l'utilisateur est actuellement connecté pour les opérations spécifiques


Note : Les éléments supprimés ne peuvent pas être récupérés après exécution de ces scripts. Validez toujours sur des systèmes de test d'abord.

Gestion d'Entreprise du Dock et Personnalisation d'Interface sur macOS

Optimisez la productivité des utilisateurs et maintenez des standards d'interface cohérents sur vos appareils MacFleet avec une gestion complète du dock et la personnalisation d'interface. Ce tutoriel couvre la configuration du dock d'entreprise, le déploiement à l'échelle de la flotte, l'optimisation de l'expérience utilisateur et la gestion automatisée d'interface pour une productivité organisationnelle améliorée.

Comprendre la Gestion du Dock macOS

Le Dock macOS sert de lanceur d'applications principal et d'organisateur d'espace de travail :

  • Lanceur d'Applications - Accès rapide aux applications fréquemment utilisées
  • Indicateur d'Applications Actives - Représentation visuelle des applications en cours d'exécution
  • Accès Fichiers & Dossiers - Accès direct aux documents et répertoires
  • Gestion Corbeille - Interface de suppression et récupération de fichiers
  • Hub Productivité - Navigation centralisée de l'espace de travail

Configuration Basique du Dock

Définir un Arrangement d'Applications Personnalisé

#!/bin/bash

# Configurer les applications personnalisées du dock
configure_basic_dock() {
    echo "=== Configuration Basique du Dock ==="
    
    local logged_user=$(stat -f%Su /dev/console)
    
    if [[ -z "$logged_user" || "$logged_user" == "root" ]]; then
        echo "❌ Aucun utilisateur connecté ou utilisateur invalide"
        return 1
    fi
    
    echo "Configuration du dock pour l'utilisateur: $logged_user"
    
    # Définir un ensemble d'applications standard
    local standard_apps=(
        "/Applications/Safari.app"
        "/Applications/Mail.app"
        "/System/Applications/Messages.app"
        "/Applications/Calendar.app"
        "/Applications/Notes.app"
        "/System/Applications/System Preferences.app"
        "/Applications/Google Chrome.app"
        "/Applications/Microsoft Outlook.app"
        "/Applications/Slack.app"
        "/Applications/Zoom.app"
    )
    
    # Construire la configuration du dock
    local dock_config="<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>PLACEHOLDER</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>"
    local dock_array=""
    
    for app in "${standard_apps[@]}"; do
        if [[ -d "$app" ]]; then
            local app_entry="${dock_config/PLACEHOLDER/$app}"
            if [[ -n "$dock_array" ]]; then
                dock_array="$dock_array "
            fi
            dock_array="$dock_array'$app_entry'"
            echo "✅ Ajouté au dock: $(basename "$app" .app)"
        else
            echo "⚠️  Application non trouvée: $app"
        fi
    done
    
    # Appliquer la configuration du dock
    if [[ -n "$dock_array" ]]; then
        sudo su "$logged_user" -c "defaults write com.apple.dock persistent-apps -array $dock_array"
        sudo su "$logged_user" -c "killall Dock"
        echo "✅ Configuration basique du dock appliquée"
    else
        echo "❌ Aucune application trouvée à configurer"
        return 1
    fi
    
    return 0
}

# Exécuter la fonction
configure_basic_dock

Réinitialiser le Dock à l'État par Défaut

#!/bin/bash

# Réinitialiser le dock à la configuration par défaut de macOS
reset_dock_default() {
    echo "=== Réinitialisation du Dock à l'État par Défaut ==="
    
    local logged_user=$(stat -f%Su /dev/console)
    
    if [[ -z "$logged_user" || "$logged_user" == "root" ]]; then
        echo "❌ Aucun utilisateur connecté ou utilisateur invalide"
        return 1
    fi
    
    echo "Réinitialisation du dock pour l'utilisateur: $logged_user"
    
    # Créer une sauvegarde de la configuration actuelle du dock
    local backup_file="/tmp/dock_backup_$(date '+%Y%m%d_%H%M%S').plist"
    sudo su "$logged_user" -c "defaults export com.apple.dock '$backup_file'"
    
    if [[ -f "$backup_file" ]]; then
        echo "✅ Configuration du dock sauvegardée dans: $backup_file"
    fi
    
    # Réinitialiser les préférences du dock
    sudo su "$logged_user" -c "defaults delete com.apple.dock"
    
    # Redémarrer le dock
    killall Dock
    
    echo "✅ Dock réinitialisé à l'état par défaut"
    return 0
}

# Exécuter la fonction
reset_dock_default

Configurer l'Apparence Visuelle

#!/bin/bash

# Configurer l'apparence visuelle et le comportement du dock
configure_dock_appearance() {
    local logged_user=$(stat -f%Su /dev/console)
    local dock_size="${1:-48}"
    local magnification="${2:-true}"
    local autohide="${3:-false}"
    local position="${4:-bottom}"
    
    echo "=== Configuration de l'Apparence du Dock ==="
    echo "Utilisateur: $logged_user"
    echo "Taille: $dock_size"
    echo "Agrandissement: $magnification"
    echo "Masquage automatique: $autohide"
    echo "Position: $position"
    
    if [[ -z "$logged_user" || "$logged_user" == "root" ]]; then
        echo "❌ Aucun utilisateur connecté"
        return 1
    fi
    
    # Configurer la taille du dock
    sudo su "$logged_user" -c "defaults write com.apple.dock tilesize -int $dock_size"
    
    # Configurer l'agrandissement
    if [[ "$magnification" == "true" ]]; then
        sudo su "$logged_user" -c "defaults write com.apple.dock magnification -bool true"
        sudo su "$logged_user" -c "defaults write com.apple.dock largesize -int 128"
    else
        sudo su "$logged_user" -c "defaults write com.apple.dock magnification -bool false"
    fi
    
    # Configurer le masquage automatique
    sudo su "$logged_user" -c "defaults write com.apple.dock autohide -bool $autohide"
    
    # Configurer la position du dock
    sudo su "$logged_user" -c "defaults write com.apple.dock orientation -string $position"
    
    # Configurer l'effet de minimisation
    sudo su "$logged_user" -c "defaults write com.apple.dock mineffect -string genie"
    
    # Afficher les indicateurs d'applications masquées
    sudo su "$logged_user" -c "defaults write com.apple.dock showhidden -bool true"
    
    # Redémarrer le dock pour appliquer les changements
    killall Dock
    
    echo "✅ Apparence du dock configurée avec succès"
    return 0
}

# Exemple d'utilisation
# configure_dock_appearance 64 true false bottom

Système de Gestion d'Entreprise du Dock

#!/bin/bash

# Système de Gestion d'Entreprise du Dock MacFleet
# Personnalisation d'interface complète, optimisation de productivité et déploiement à l'échelle de la flotte

# Configuration
LOG_FILE="/var/log/macfleet_dock_management.log"
CONFIG_DIR="/etc/macfleet/dock_management"
POLICIES_DIR="$CONFIG_DIR/policies"
TEMPLATES_DIR="$CONFIG_DIR/templates"
PROFILES_DIR="$CONFIG_DIR/profiles"
REPORTS_DIR="$CONFIG_DIR/reports"
BACKUP_DIR="$CONFIG_DIR/backups"
COMPLIANCE_DIR="$CONFIG_DIR/compliance"
DEPLOYMENT_DIR="$CONFIG_DIR/deployment"

# Modèles de configuration du dock
declare -A DOCK_TEMPLATES=(
    ["developer"]="Xcode,Terminal,Visual Studio Code,GitHub Desktop,Docker,Postman,Simulator,Activity Monitor"
    ["designer"]="Adobe Creative Suite,Figma,Sketch,Affinity Designer,ColorSync Utility,Digital Color Meter,Preview"
    ["business"]="Microsoft Office Suite,Slack,Zoom,Teams,Outlook,OneNote,Salesforce,Tableau"
    ["executive"]="Mail,Calendar,Contacts,Safari,Numbers,Keynote,Pages,Messages,FaceTime"
    ["support"]="Remote Desktop,TeamViewer,Console,Activity Monitor,Network Utility,Disk Utility,Terminal"
    ["education"]="Safari,Mail,Classroom,Pages,Numbers,Keynote,GarageBand,iMovie,Books"
    ["finance"]="Excel,QuickBooks,Sage,TaxAct,Calculator,Numbers,Banking Apps,PDF Expert"
    ["healthcare"]="Epic,Cerner,MEDITECH,DICOM Viewer,Medical Calculator,Secure Messaging,Telemedicine Apps"
)

# Configurations de rôles utilisateur
declare -A USER_ROLES=(
    ["admin"]="developer,support"
    ["power_user"]="business,developer"
    ["standard_user"]="business"
    ["guest"]="executive"
    ["kiosk"]="education"
)

# Préréglages de taille du dock
declare -A DOCK_SIZES=(
    ["small"]="32"
    ["medium"]="48"
    ["large"]="64"
    ["extra_large"]="80"
    ["jumbo"]="128"
)

# Politiques d'entreprise
declare -A ENTERPRISE_POLICIES=(
    ["corporate_standard"]="consistent_layout,security_apps,productivity_focused,compliance_enabled"
    ["byod_friendly"]="user_customizable,personal_apps_allowed,flexible_layout"
    ["kiosk_mode"]="locked_layout,essential_apps_only,no_customization"
    ["developer_optimized"]="development_tools,large_dock,custom_shortcuts"
    ["executive_minimal"]="essential_apps,clean_interface,quick_access"
)

# Optimisations de productivité
declare -A PRODUCTIVITY_FEATURES=(
    ["hot_corners"]="mission_control,desktop,dashboard,screen_saver"
    ["gestures"]="swipe_navigation,expose,spaces"
    ["shortcuts"]="application_switching,dock_navigation,quick_launch"
    ["organization"]="folder_stacks,recent_items,favorites"
)

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

# Configuration des répertoires
setup_directories() {
    for dir in "$CONFIG_DIR" "$POLICIES_DIR" "$TEMPLATES_DIR" "$PROFILES_DIR" "$REPORTS_DIR" "$BACKUP_DIR" "$COMPLIANCE_DIR" "$DEPLOYMENT_DIR"; do
        if [[ ! -d "$dir" ]]; then
            mkdir -p "$dir"
            log_action "Répertoire créé: $dir"
        fi
    done
}

# Installer les dépendances de gestion du dock
install_dock_dependencies() {
    echo "🔧 Installation des Dépendances de Gestion du Dock"
    
    local dockutil_version="3.0.2"
    local dockutil_pkg="/tmp/dockutil-${dockutil_version}.pkg"
    
    # Vérifier si dockutil est déjà installé
    if command -v dockutil &>/dev/null; then
        echo "✅ dockutil déjà installé"
        return 0
    fi
    
    # Télécharger et installer dockutil
    echo "📥 Téléchargement de dockutil ${dockutil_version}..."
    if curl -sL "https://github.com/kcrawford/dockutil/releases/download/${dockutil_version}/dockutil-${dockutil_version}.pkg" -o "$dockutil_pkg"; then
        echo "📦 Installation de dockutil..."
        if sudo installer -pkg "$dockutil_pkg" -target /; then
            echo "✅ dockutil installé avec succès"
            rm -f "$dockutil_pkg"
        else
            echo "❌ Échec de l'installation de dockutil"
            return 1
        fi
    else
        echo "❌ Échec du téléchargement de dockutil"
        return 1
    fi
    
    # Installer des outils de productivité supplémentaires
    install_productivity_tools
    
    return 0
}

# Créer une configuration de dock à partir d'un modèle
create_dock_from_template() {
    local template_name="$1"
    local username="$2"
    local customize_options="$3"
    
    log_action "Création de la configuration du dock à partir du modèle: $template_name pour l'utilisateur: $username"
    
    local template_apps="${DOCK_TEMPLATES[$template_name]}"
    if [[ -z "$template_apps" ]]; then
        log_action "❌ Modèle de dock inconnu: $template_name"
        return 1
    fi
    
    local logged_user=$(stat -f%Su /dev/console)
    local target_user="${username:-$logged_user}"
    
    if [[ -z "$target_user" || "$target_user" == "root" ]]; then
        log_action "❌ Utilisateur cible invalide: $target_user"
        return 1
    fi
    
    echo "🎨 Création de la configuration du dock à partir du modèle: $template_name"
    echo "Utilisateur cible: $target_user"
    
    # Sauvegarder la configuration actuelle du dock
    backup_dock_configuration "$target_user"
    
    # Analyser les applications du modèle
    IFS=',' read -ra TEMPLATE_APPS <<< "$template_apps"
    
    # Vider le dock actuel
    sudo su "$target_user" -c "defaults write com.apple.dock persistent-apps -array"
    
    # Ajouter les applications du modèle
    for app_name in "${TEMPLATE_APPS[@]}"; do
        add_application_to_dock "$app_name" "$target_user"
    done
    
    # Appliquer les options de personnalisation
    if [[ -n "$customize_options" ]]; then
        apply_dock_customizations "$customize_options" "$target_user"
    fi
    
    # Sauvegarder la configuration du modèle
    save_dock_template_config "$template_name" "$target_user"
    
    # Redémarrer le dock
    killall Dock
    
    log_action "✅ Configuration du dock créée à partir du modèle: $template_name"
    return 0
}

# Ajouter une application au dock intelligemment
add_application_to_dock() {
    local app_name="$1"
    local username="$2"
    
    # Mappage des chemins d'applications
    local app_paths=(
        "/Applications/${app_name}.app"
        "/System/Applications/${app_name}.app"
        "/Applications/Utilities/${app_name}.app"
        "/Applications/Microsoft Office 2011/${app_name}.app"
        "/Applications/Adobe Creative Suite/${app_name}.app"
        "/Applications/Google Chrome.app"
        "/Applications/Microsoft Outlook.app"
        "/Applications/Microsoft Word.app"
        "/Applications/Microsoft Excel.app"
        "/Applications/Microsoft PowerPoint.app"
        "/Applications/Slack.app"
        "/Applications/Zoom.app"
        "/Applications/Figma.app"
        "/Applications/Visual Studio Code.app"
        "/Applications/Xcode.app"
    )
    
    # Trouver le chemin de l'application
    local app_path=""
    for path in "${app_paths[@]}"; do
        if [[ -d "$path" ]]; then
            app_path="$path"
            break
        fi
    done
    
    # Gérer les noms d'applications spéciaux
    case "$app_name" in
        "Microsoft Office Suite")
            add_application_to_dock "Microsoft Word" "$username"
            add_application_to_dock "Microsoft Excel" "$username"
            add_application_to_dock "Microsoft PowerPoint" "$username"
            add_application_to_dock "Microsoft Outlook" "$username"
            return 0
            ;;
        "Adobe Creative Suite")
            add_application_to_dock "Adobe Photoshop" "$username"
            add_application_to_dock "Adobe Illustrator" "$username"
            add_application_to_dock "Adobe InDesign" "$username"
            return 0
            ;;
        "Terminal")
            app_path="/System/Applications/Utilities/Terminal.app"
            ;;
        "Activity Monitor")
            app_path="/System/Applications/Utilities/Activity Monitor.app"
            ;;
        "System Preferences")
            app_path="/System/Applications/System Preferences.app"
            ;;
    esac
    
    if [[ -n "$app_path" && -d "$app_path" ]]; then
        # Utiliser dockutil si disponible
        if command -v dockutil &>/dev/null; then
            dockutil --add "$app_path" --allhomes 2>/dev/null
            echo "✅ Ajouté au dock: $app_name"
        else
            # Solution de rechange avec la commande defaults
            local dock_entry="<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>$app_path</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>"
            sudo su "$username" -c "defaults write com.apple.dock persistent-apps -array-add '$dock_entry'"
            echo "✅ Ajouté au dock: $app_name"
        fi
    else
        echo "⚠️  Application non trouvée: $app_name"
    fi
}

# Surveiller la conformité du dock
monitor_dock_compliance() {
    log_action "Démarrage de la surveillance de conformité du dock"
    
    local compliance_report="$COMPLIANCE_DIR/dock_compliance_$(date '+%Y%m%d_%H%M%S').json"
    local logged_user=$(stat -f%Su /dev/console)
    
    cat > "$compliance_report" << EOF
{
    "compliance_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)",
        "logged_user": "$logged_user",
        "monitor_type": "dock_compliance"
    },
    "dock_assessment": {
        "current_configuration": $(get_current_dock_config "$logged_user"),
        "policy_compliance": $(assess_policy_compliance "$logged_user"),
        "security_compliance": $(assess_dock_security "$logged_user"),
        "productivity_metrics": $(calculate_productivity_metrics "$logged_user")
    },
    "compliance_status": {
        "overall_score": $(calculate_compliance_score),
        "violations": $(detect_policy_violations "$logged_user"),
        "recommendations": $(generate_compliance_recommendations),
        "remediation_actions": $(generate_remediation_actions)
    }
}
EOF

    log_action "✅ Surveillance de conformité du dock terminée: $compliance_report"
    echo "$compliance_report"
}

# Optimiser le dock pour la productivité
optimize_dock_productivity() {
    local optimization_level="$1"
    local username="$2"
    local role="$3"
    
    log_action "Optimisation du dock pour la productivité: niveau=$optimization_level, utilisateur=$username, rôle=$role"
    
    local logged_user=$(stat -f%Su /dev/console)
    local target_user="${username:-$logged_user}"
    
    echo "🚀 Optimisation du Dock pour la Productivité"
    echo "Niveau d'optimisation: $optimization_level"
    echo "Utilisateur cible: $target_user"
    echo "Rôle utilisateur: $role"
    
    case "$optimization_level" in
        "basic")
            apply_basic_productivity_optimizations "$target_user" "$role"
            ;;
        "advanced")
            apply_advanced_productivity_optimizations "$target_user" "$role"
            ;;
        "expert")
            apply_expert_productivity_optimizations "$target_user" "$role"
            ;;
        *)
            log_action "⚠️  Niveau d'optimisation inconnu: $optimization_level"
            return 1
            ;;
    esac
    
    # Configurer les coins actifs pour la productivité
    configure_hot_corners "$target_user"
    
    # Configurer les raccourcis du dock
    configure_dock_shortcuts "$target_user"
    
    # Appliquer les optimisations spécifiques au rôle
    apply_role_specific_optimizations "$role" "$target_user"
    
    # Redémarrer le dock
    killall Dock
    
    log_action "✅ Optimisation de la productivité du dock terminée"
    return 0
}

# Fonction d'exécution principale
main() {
    local action="${1:-status}"
    local parameter="$2"
    local additional_param="$3"
    local extra_param="$4"
    
    log_action "=== Gestion du Dock MacFleet Démarrée ==="
    log_action "Action: $action"
    log_action "Paramètre: ${parameter:-N/A}"
    
    setup_directories
    
    case "$action" in
        "install")
            install_dock_dependencies
            ;;
        "template")
            if [[ -z "$parameter" ]]; then
                echo "Modèles de dock disponibles:"
                for template in "${!DOCK_TEMPLATES[@]}"; do
                    echo "  - $template: ${DOCK_TEMPLATES[$template]}"
                done
                echo ""
                echo "Usage: $0 template <nom_modèle> [nom_utilisateur] [personnalisations]"
                exit 1
            fi
            create_dock_from_template "$parameter" "$additional_param" "$extra_param"
            ;;
        "optimize")
            if [[ -z "$parameter" ]]; then
                echo "Niveaux d'optimisation: basic, advanced, expert"
                echo "Rôles utilisateur: ${!USER_ROLES[*]}"
                echo ""
                echo "Usage: $0 optimize <niveau> [nom_utilisateur] [rôle]"
                exit 1
            fi
            optimize_dock_productivity "$parameter" "$additional_param" "$extra_param"
            ;;
        "monitor")
            monitor_dock_compliance
            ;;
        "reset")
            reset_dock_default
            ;;
        "appearance")
            if [[ -z "$parameter" ]]; then
                echo "Tailles de dock disponibles: ${!DOCK_SIZES[*]}"
                echo ""
                echo "Usage: $0 appearance <taille> [agrandissement] [masquage_auto] [position]"
                echo "Exemple: $0 appearance medium true false bottom"
                exit 1
            fi
            local size="${DOCK_SIZES[$parameter]:-$parameter}"
            configure_dock_appearance "$size" "$additional_param" "$extra_param" "${5:-bottom}"
            ;;
        *)
            echo "Usage: $0 {install|template|optimize|monitor|reset|appearance}"
            echo "  install     - Installer les dépendances de gestion du dock"
            echo "  template    - Appliquer la configuration du dock à partir d'un modèle"
            echo "  optimize    - Optimiser le dock pour la productivité"
            echo "  monitor     - Surveiller la conformité du dock"
            echo "  reset       - Réinitialiser le dock à l'état par défaut"
            echo "  appearance  - Configurer l'apparence visuelle du dock"
            exit 1
            ;;
    esac
    
    log_action "=== Opération de gestion du dock terminée ==="
}

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

Fonctionnalités Avancées de Gestion du Dock

Organisation Intelligente des Applications

#!/bin/bash

# Organisation intelligente des applications basée sur les modèles d'utilisation
smart_dock_organization() {
    local username="$1"
    local analysis_period="${2:-30}"  # jours
    
    echo "🧠 Organisation Intelligente du Dock"
    echo "Analyse des modèles d'utilisation pour $analysis_period jours"
    
    local usage_data="$REPORTS_DIR/app_usage_${username}.json"
    
    # Analyser l'utilisation des applications
    cat > "$usage_data" << EOF
{
    "analysis_period": $analysis_period,
    "usage_patterns": $(analyze_app_usage "$username" "$analysis_period"),
    "frequency_ranking": $(rank_apps_by_frequency "$username"),
    "time_based_usage": $(analyze_time_based_usage "$username"),
    "productivity_score": $(calculate_app_productivity_score "$username")
}
EOF

    # Réorganiser le dock basé sur les modèles d'utilisation
    reorganize_dock_by_usage "$username" "$usage_data"
    
    echo "✅ Organisation intelligente du dock terminée"
}

# Adaptation dynamique du dock
dynamic_dock_adaptation() {
    echo "🔄 Adaptation Dynamique du Dock"
    
    local adaptation_script="$DEPLOYMENT_DIR/dynamic_adaptation.sh"
    
    cat > "$adaptation_script" << 'EOF'
#!/bin/bash

# Adaptation dynamique du dock basée sur le contexte

while true; do
    CURRENT_HOUR=$(date +%H)
    CURRENT_USER=$(stat -f%Su /dev/console)
    
    # Adapter le dock selon l'heure de la journée
    if [[ $CURRENT_HOUR -ge 9 && $CURRENT_HOUR -le 17 ]]; then
        # Heures de bureau - focus productivité
        apply_business_hours_dock "$CURRENT_USER"
    elif [[ $CURRENT_HOUR -ge 18 && $CURRENT_HOUR -le 22 ]]; then
        # Soirée - travail créatif/personnel
        apply_evening_dock "$CURRENT_USER"
    else
        # Heures creuses - dock minimal
        apply_minimal_dock "$CURRENT_USER"
    fi
    
    # Vérifier toutes les 30 minutes
    sleep 1800
done
EOF

    chmod +x "$adaptation_script"
    echo "🤖 Script d'adaptation dynamique créé"
}

Fonctionnalités d'Intégration d'Entreprise

🔗 Intégration Système

  • Intégration Active Directory avec mappage des rôles utilisateur
  • Authentification LDAP pour l'attribution de politiques de dock
  • Intégration de gestion de configuration (Puppet, Ansible, Chef)
  • Synchronisation de politiques MDM (Mobile Device Management)

📱 Gestion de Flotte

  • Déploiement centralisé sur des milliers d'appareils
  • Héritage de politiques avec mappage d'unités organisationnelles
  • Mises à jour de configuration en lot avec capacités de rollback
  • Surveillance de santé avec vérification automatisée de conformité

🎯 Optimisation de l'Expérience Utilisateur

  • Adaptation contextuelle basée sur l'heure, la localisation, le rôle
  • Insights d'apprentissage automatique pour des recommandations personnalisées
  • Analytics de productivité avec insights actionnables
  • Tests A/B pour l'efficacité de la configuration du dock

🛡️ Sécurité et Conformité

  • Application de politiques avec protection contre la falsification
  • Intégration d'applications de sécurité dans les configurations de dock
  • Rapports de conformité pour les exigences réglementaires
  • Pistes d'audit pour toutes les modifications du dock

Notes Importantes

  • Permissions utilisateur requises pour les modifications du dock à l'échelle de l'entreprise
  • Considérations de licence d'application pour les modèles de dock d'entreprise
  • Impact sur les performances minimal avec stratégies de déploiement optimisées
  • Stratégies de sauvegarde essentielles avant les reconfigurations majeures du dock
  • Formation utilisateur importante pour l'adoption de l'optimisation de productivité
  • Surveillance régulière nécessaire pour maintenir la conformité et l'efficacité du dock

Configuration des paramètres DNS pour le Wi-Fi sur Mac

Le système de nom de domaine (DNS) est l'épine dorsale d'Internet, convertissant les noms de domaine lisibles par l'homme en adresses IP qui permettent une communication transparente entre les appareils. Une configuration DNS appropriée peut impacter significativement votre expérience Internet, affectant la vitesse, la sécurité et la confidentialité. Ce guide complet fournit des méthodes pour configurer les paramètres DNS pour le Wi-Fi sur les appareils macOS.

Comprendre le DNS et son importance

Les serveurs DNS agissent comme des traducteurs entre les noms de domaine (comme google.com) et les adresses IP (comme 142.250.80.14). Lorsque vous tapez une adresse web, votre appareil interroge un serveur DNS pour trouver l'adresse IP correspondante, puis se connecte à ce serveur.

Pourquoi changer les paramètres DNS ?

Il y a plusieurs raisons convaincantes de modifier votre configuration DNS :

  • Performance améliorée : Des serveurs DNS plus rapides peuvent réduire les temps de chargement des sites web
  • Sécurité renforcée : Le filtrage DNS peut bloquer les sites web malveillants et les tentatives de phishing
  • Protection de la vie privée : Certains fournisseurs DNS n'enregistrent pas vos activités de navigation
  • Accès au contenu : Contourner les restrictions géographiques et la censure
  • Contrôle parental : Filtrer le contenu inapproprié pour les réseaux familiaux
  • Blocage des publicités : Certains services DNS bloquent les publicités au niveau DNS

Fournisseurs DNS populaires

Avant de configurer les paramètres DNS, considérez ces fournisseurs DNS populaires :

Google Public DNS

  • Primaire : 8.8.8.8
  • Secondaire : 8.8.4.4
  • Caractéristiques : Rapide, fiable, journalisation minimale

Cloudflare DNS

  • Primaire : 1.1.1.1
  • Secondaire : 1.0.0.1
  • Caractéristiques : Axé sur la confidentialité, très rapide, fonctionnalités de sécurité

OpenDNS

  • Primaire : 208.67.222.222
  • Secondaire : 208.67.220.220
  • Caractéristiques : Filtrage de contenu, protection contre les malwares

Quad9

  • Primaire : 9.9.9.9
  • Secondaire : 149.112.112.112
  • Caractéristiques : Axé sur la sécurité, bloque les domaines malveillants

Prérequis

Avant de configurer les paramètres DNS, assurez-vous d'avoir :

  • Privilèges administrateur sur le Mac
  • Accès au Terminal ou aux Préférences Système
  • Connaissance de votre configuration réseau actuelle
  • Sauvegarde des paramètres DNS actuels (optionnel mais recommandé)

Méthode 1 : Utilisation de scripts shell

Script de configuration DNS de base

Ce script configure les paramètres de serveur DNS pour le Wi-Fi sur macOS :

#!/bin/bash

# Configurer les serveurs DNS pour le Wi-Fi
sudo networksetup -setdnsservers "Wi-Fi" 8.8.8.8 8.8.4.4

# Vérifier la configuration
output=$(networksetup -getdnsservers "Wi-Fi")
echo "Serveurs DNS actuels: $output"

# Vider le cache DNS
sudo dscacheutil -flushcache
echo "Cache DNS vidé"

Script de configuration DNS avancé

Un script plus complet avec plusieurs options DNS :

#!/bin/bash

# Script de configuration DNS avancé pour macOS Wi-Fi
# Usage: ./dns_config.sh [fournisseur]
# Fournisseurs: google, cloudflare, opendns, quad9, reset

PROVIDER=${1:-google}
INTERFACE="Wi-Fi"

# Fonction pour définir les serveurs DNS
set_dns_servers() {
    local primary=$1
    local secondary=$2
    local provider_name=$3
    
    echo "Configuration des serveurs DNS vers $provider_name..."
    sudo networksetup -setdnsservers "$INTERFACE" "$primary" "$secondary"
    
    # Vérifier la configuration
    current_dns=$(networksetup -getdnsservers "$INTERFACE")
    echo "Serveurs DNS actuels: $current_dns"
    
    # Vider le cache DNS
    sudo dscacheutil -flushcache
    echo "Cache DNS vidé"
    
    # Tester la résolution DNS
    echo "Test de résolution DNS..."
    nslookup google.com "$primary" | head -5
}

# Fonction pour réinitialiser vers DNS automatique
reset_dns() {
    echo "Réinitialisation DNS vers automatique (DHCP)..."
    sudo networksetup -setdnsservers "$INTERFACE" "Empty"
    current_dns=$(networksetup -getdnsservers "$INTERFACE")
    echo "Serveurs DNS actuels: $current_dns"
}

# Logique de configuration principale
case $PROVIDER in
    google)
        set_dns_servers "8.8.8.8" "8.8.4.4" "Google Public DNS"
        ;;
    cloudflare)
        set_dns_servers "1.1.1.1" "1.0.0.1" "Cloudflare DNS"
        ;;
    opendns)
        set_dns_servers "208.67.222.222" "208.67.220.220" "OpenDNS"
        ;;
    quad9)
        set_dns_servers "9.9.9.9" "149.112.112.112" "Quad9"
        ;;
    reset)
        reset_dns
        ;;
    *)
        echo "Usage: $0 [google|cloudflare|opendns|quad9|reset]"
        echo "Par défaut: google"
        exit 1
        ;;
esac

echo "Configuration DNS terminée!"

Configuration DNS par lot pour plusieurs Mac

Pour gérer les paramètres DNS sur plusieurs appareils Mac :

#!/bin/bash

# Configuration DNS par lot pour plusieurs Mac
HOSTS=(
    "mac1.local"
    "mac2.local"
    "mac3.local"
)

DNS_PRIMARY="1.1.1.1"
DNS_SECONDARY="1.0.0.1"
INTERFACE="Wi-Fi"

echo "Configuration DNS sur plusieurs Mac..."
echo "DNS primaire: $DNS_PRIMARY"
echo "DNS secondaire: $DNS_SECONDARY"
echo ""

for host in "${HOSTS[@]}"; do
    echo "Configuration de $host..."
    
    if ping -c 1 -W 1000 "$host" >/dev/null 2>&1; then
        # Créer un script à exécuter sur l'hôte distant
        remote_script="sudo networksetup -setdnsservers '$INTERFACE' '$DNS_PRIMARY' '$DNS_SECONDARY' && sudo dscacheutil -flushcache"
        
        if ssh -o ConnectTimeout=5 -o BatchMode=yes "$host" "$remote_script" 2>/dev/null; then
            echo "  ✓ $host - DNS configuré avec succès"
        else
            echo "  ✗ $host - Échec de la configuration DNS"
        fi
    else
        echo "  ✗ $host - Hôte inaccessible"
    fi
done

echo ""
echo "Configuration DNS par lot terminée!"

Méthode 2 : Configuration manuelle via les Préférences Système

Configuration GUI étape par étape

  1. Ouvrir les Préférences Système

    • Cliquer sur le menu Apple > Préférences Système
    • Ou utiliser Spotlight : Presser Cmd+Espace, taper "Préférences Système"
  2. Accéder aux paramètres réseau

    • Cliquer sur "Réseau"
    • Sélectionner "Wi-Fi" dans la barre latérale gauche
    • Cliquer sur le bouton "Avancé..."
  3. Configurer DNS

    • Cliquer sur l'onglet "DNS"
    • Cliquer sur le bouton "+" pour ajouter des serveurs DNS
    • Entrer vos serveurs DNS préférés (ex: 1.1.1.1, 1.0.0.1)
    • Faire glisser les serveurs pour les réorganiser par priorité
  4. Appliquer les paramètres

    • Cliquer sur "OK" pour fermer la fenêtre Avancé
    • Cliquer sur "Appliquer" pour sauvegarder les changements

Vérification en ligne de commande

Après la configuration manuelle, vérifiez les paramètres en utilisant Terminal :

# Vérifier les serveurs DNS actuels
networksetup -getdnsservers "Wi-Fi"

# Tester la résolution DNS
nslookup google.com
dig google.com

# Vérifier le temps de réponse DNS
time nslookup google.com

Scripts de gestion DNS

Script d'information DNS actuel

Script pour recueillir des informations DNS complètes :

#!/bin/bash

# Script de collecte d'informations DNS
echo "Rapport de configuration DNS"
echo "============================"
echo "Date: $(date)"
echo "Nom d'hôte: $(hostname)"
echo ""

# Obtenir toutes les interfaces réseau
interfaces=$(networksetup -listallnetworkservices | grep -v "denotes")

echo "Interfaces réseau et paramètres DNS:"
echo "-----------------------------------"

while IFS= read -r interface; do
    if [[ "$interface" != "" ]]; then
        echo "Interface: $interface"
        dns_servers=$(networksetup -getdnsservers "$interface")
        
        if [[ "$dns_servers" == "There aren't any DNS Servers set on"* ]]; then
            echo "  DNS: Automatique (DHCP)"
        else
            echo "  Serveurs DNS:"
            echo "$dns_servers" | while read -r server; do
                echo "    - $server"
            done
        fi
        echo ""
    fi
done <<< "$interfaces"

# Tester les performances de résolution DNS
echo "Test de résolution DNS:"
echo "----------------------"
test_domains=("google.com" "cloudflare.com" "github.com")

for domain in "${test_domains[@]}"; do
    echo "Test de $domain..."
    time_result=$(time (nslookup "$domain" >/dev/null 2>&1) 2>&1 | grep real | awk '{print $2}')
    echo "  Temps de résolution: $time_result"
done

Script de sauvegarde et restauration DNS

#!/bin/bash

# Script de sauvegarde et restauration DNS
BACKUP_DIR="$HOME/dns_backups"
BACKUP_FILE="$BACKUP_DIR/dns_backup_$(date +%Y%m%d_%H%M%S).txt"

# Créer le répertoire de sauvegarde
mkdir -p "$BACKUP_DIR"

# Fonction pour sauvegarder les paramètres DNS
backup_dns() {
    echo "Sauvegarde des paramètres DNS..."
    
    {
        echo "Sauvegarde DNS - $(date)"
        echo "======================="
        echo ""
        
        # Obtenir toutes les interfaces réseau
        interfaces=$(networksetup -listallnetworkservices | grep -v "denotes")
        
        while IFS= read -r interface; do
            if [[ "$interface" != "" ]]; then
                echo "Interface: $interface"
                networksetup -getdnsservers "$interface"
                echo ""
            fi
        done <<< "$interfaces"
        
    } > "$BACKUP_FILE"
    
    echo "Paramètres DNS sauvegardés dans: $BACKUP_FILE"
}

# Fonction pour restaurer les paramètres DNS
restore_dns() {
    local backup_file=$1
    
    if [[ ! -f "$backup_file" ]]; then
        echo "Fichier de sauvegarde introuvable: $backup_file"
        return 1
    fi
    
    echo "Restauration des paramètres DNS depuis: $backup_file"
    echo "Note: Restauration manuelle requise - le fichier de sauvegarde contient la configuration pour référence"
    cat "$backup_file"
}

# Logique principale du script
case "${1:-backup}" in
    backup)
        backup_dns
        ;;
    restore)
        restore_dns "$2"
        ;;
    list)
        echo "Sauvegardes disponibles:"
        ls -la "$BACKUP_DIR"
        ;;
    *)
        echo "Usage: $0 [backup|restore <fichier>|list]"
        exit 1
        ;;
esac

Dépannage des problèmes DNS

Problèmes DNS courants et solutions

  1. Navigation Internet lente

    # Tester les temps de réponse DNS
    time nslookup google.com 8.8.8.8
    time nslookup google.com 1.1.1.1
    
    # Passer à un serveur DNS plus rapide
    sudo networksetup -setdnsservers "Wi-Fi" 1.1.1.1 1.0.0.1
  2. Impossible d'accéder à certains sites web

    # Vérifier si le DNS résout le domaine
    nslookup site-problematique.com
    
    # Essayer un serveur DNS différent
    nslookup site-problematique.com 8.8.8.8
  3. Problèmes de cache DNS

    # Vider le cache DNS
    sudo dscacheutil -flushcache
    sudo killall -HUP mDNSResponder

Script de diagnostic DNS

#!/bin/bash

# Script de diagnostic DNS
echo "Rapport de diagnostic DNS"
echo "========================"
echo "Date: $(date)"
echo ""

# Vérifier la configuration DNS actuelle
echo "1. Configuration DNS actuelle:"
echo "-----------------------------"
networksetup -getdnsservers "Wi-Fi"
echo ""

# Tester la connectivité aux serveurs DNS courants
echo "2. Test de connectivité aux serveurs DNS:"
echo "----------------------------------------"
dns_servers=("8.8.8.8" "1.1.1.1" "208.67.222.222" "9.9.9.9")

for server in "${dns_servers[@]}"; do
    if ping -c 1 -W 1000 "$server" >/dev/null 2>&1; then
        echo "✓ $server - Accessible"
    else
        echo "✗ $server - Inaccessible"
    fi
done
echo ""

# Tester la résolution DNS
echo "3. Test de résolution DNS:"
echo "-------------------------"
test_domains=("google.com" "cloudflare.com" "github.com")

for domain in "${test_domains[@]}"; do
    if nslookup "$domain" >/dev/null 2>&1; then
        echo "✓ $domain - Résolu correctement"
    else
        echo "✗ $domain - Échec de résolution"
    fi
done
echo ""

# Vérifier les fuites DNS
echo "4. Vérification des fuites DNS:"
echo "-------------------------------"
echo "Résolveur DNS actuel:"
nslookup myip.opendns.com resolver1.opendns.com | grep "Address" | tail -1
echo ""

echo "Diagnostic terminé!"

Bonnes pratiques pour la configuration DNS

1. Considérations de sécurité

  • Utiliser des fournisseurs DNS réputés avec des fonctionnalités de sécurité
  • Mettre à jour régulièrement les paramètres DNS basés sur la veille des menaces
  • Considérer DNS-over-HTTPS (DoH) pour une confidentialité renforcée
  • Surveiller les requêtes DNS pour détecter les activités suspectes

2. Optimisation des performances

  • Tester plusieurs fournisseurs DNS pour trouver le plus rapide pour votre localisation
  • Utiliser des serveurs DNS primaires et secondaires pour la redondance
  • Considérer la proximité géographique lors de la sélection des serveurs DNS
  • Surveiller régulièrement les temps de résolution DNS

3. Gestion d'entreprise

  • Standardiser les paramètres DNS sur tous les appareils organisationnels
  • Documenter les configurations DNS pour la récupération après sinistre
  • Implémenter le filtrage DNS pour la sécurité et la conformité
  • Utiliser des scripts automatisés pour les changements de configuration en masse

4. Sauvegarde et récupération

  • Toujours sauvegarder les paramètres DNS actuels avant de faire des changements
  • Tester les nouvelles configurations DNS dans un environnement contrôlé
  • Avoir un plan de retour en arrière pour les changements DNS
  • Documenter tous les changements de configuration DNS

Configuration DNS avancée

Configuration DNS-over-HTTPS (DoH)

Pour une confidentialité renforcée, configurez DNS-over-HTTPS :

#!/bin/bash

# Configurer DNS-over-HTTPS (DoH) sur macOS
# Note: Cela nécessite macOS 11.0 ou ultérieur

# Activer DoH avec Cloudflare
sudo networksetup -setdnsservers "Wi-Fi" 1.1.1.1 1.0.0.1
sudo defaults write /Library/Preferences/com.apple.networkd.plist DoHServers -dict-add "1.1.1.1" "https://cloudflare-dns.com/dns-query"
sudo defaults write /Library/Preferences/com.apple.networkd.plist DoHServers -dict-add "1.0.0.1" "https://cloudflare-dns.com/dns-query"

# Redémarrer les services réseau
sudo launchctl unload /System/Library/LaunchDaemons/com.apple.networkd.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.networkd.plist

echo "DNS-over-HTTPS configuré avec Cloudflare"

Configuration DNS personnalisée pour des domaines spécifiques

#!/bin/bash

# Configurer DNS personnalisé pour des domaines spécifiques
# Utilise /etc/resolver pour DNS spécifique au domaine

# Créer le répertoire resolver
sudo mkdir -p /etc/resolver

# Configurer un domaine spécifique pour utiliser DNS personnalisé
echo "nameserver 8.8.8.8" | sudo tee /etc/resolver/entreprise.local
echo "nameserver 8.8.4.4" | sudo tee -a /etc/resolver/entreprise.local

# Vider le cache DNS
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

echo "DNS personnalisé configuré pour le domaine entreprise.local"

Surveillance et maintenance

Script de surveillance DNS

#!/bin/bash

# Script de surveillance DNS
LOG_FILE="/var/log/dns_monitor.log"

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

# Surveiller les performances DNS
monitor_dns() {
    local dns_server=$1
    local test_domain=$2
    
    start_time=$(date +%s%N)
    if nslookup "$test_domain" "$dns_server" >/dev/null 2>&1; then
        end_time=$(date +%s%N)
        duration=$((($end_time - $start_time) / 1000000))
        log_message "DNS $dns_server: $test_domain résolu en ${duration}ms"
    else
        log_message "DNS $dns_server: Échec de résolution de $test_domain"
    fi
}

# Surveiller plusieurs serveurs DNS
dns_servers=("8.8.8.8" "1.1.1.1" "208.67.222.222")
test_domain="google.com"

log_message "Début de la surveillance DNS"

for server in "${dns_servers[@]}"; do
    monitor_dns "$server" "$test_domain"
done

log_message "Surveillance DNS terminée"

Conclusion

Une configuration DNS appropriée est cruciale pour des performances Internet optimales, la sécurité et la confidentialité. Les scripts et méthodes fournis dans ce guide offrent des solutions complètes pour gérer les paramètres DNS sur les appareils macOS, des configurations simples aux déploiements d'entreprise avancés.

Points clés à retenir :

  • Choisir des fournisseurs DNS qui s'alignent sur vos exigences de performance et de confidentialité
  • Tester et surveiller régulièrement les performances DNS
  • Implémenter des procédures de sauvegarde et de récupération appropriées
  • Considérer les implications de sécurité de la configuration DNS
  • Utiliser l'automatisation pour les déploiements à grande échelle

N'oubliez pas de tester tous les changements DNS dans un environnement contrôlé avant de les déployer sur votre flotte Mac. Une gestion DNS appropriée peut considérablement améliorer votre expérience réseau tout en renforçant la sécurité et la confidentialité.

Gestion de la Luminosité d'Écran et Optimisation Énergétique sur macOS

Gérez la luminosité d'affichage et la consommation d'énergie sur vos appareils MacFleet avec un contrôle complet de la luminosité, des politiques d'éclairage adaptatif et des outils d'optimisation énergétique d'entreprise. Ce tutoriel couvre l'ajustement de luminosité, la planification automatisée et la gestion d'affichage à l'échelle de la flotte.

Comprendre la Gestion de la Luminosité d'Affichage

Le contrôle de la luminosité d'affichage sur macOS affecte à la fois l'expérience utilisateur et la consommation d'énergie. La gestion d'entreprise inclut :

  • Contrôle de Luminosité - Ajustement direct des niveaux de luminosité d'affichage
  • Éclairage Adaptatif - Ajustement automatique basé sur l'environnement et l'heure
  • Optimisation Énergétique - Conservation de batterie grâce à la gestion intelligente d'affichage
  • Expérience Utilisateur - Paramètres d'affichage cohérents sur les appareils d'entreprise

Avantages d'Entreprise

Une gestion appropriée de la luminosité d'affichage offre des avantages d'entreprise :

  • Conservation d'Énergie - Réduction de la consommation d'énergie et prolongation de la durée de vie de la batterie
  • Confort Utilisateur - Conditions de visualisation optimales pour différents environnements de travail
  • Amélioration de Sécurité - Affichages atténués dans les espaces publics pour la confidentialité
  • Bénéfices Santé - Réduction de la fatigue oculaire grâce à un éclairage approprié
  • Standardisation - Expérience d'affichage cohérente sur toute la flotte d'appareils

Contrôle de Luminosité de Base

Prérequis et Configuration

#!/bin/bash

# Installer Homebrew et l'outil de contrôle de luminosité
install_brightness_tools() {
    echo "=== Installation des Outils de Contrôle de Luminosité ==="
    
    # Vérifier si Homebrew est installé
    if ! command -v brew >/dev/null 2>&1; then
        echo "Installation de Homebrew..."
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
        
        # Ajouter Homebrew au PATH pour la session actuelle
        eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || eval "$(/usr/local/bin/brew shellenv)" 2>/dev/null
    else
        echo "✓ Homebrew déjà installé"
    fi
    
    # Installer l'outil de contrôle de luminosité
    if ! command -v brightness >/dev/null 2>&1; then
        echo "Installation de l'outil de contrôle de luminosité..."
        brew install brightness
    else
        echo "✓ Outil de luminosité déjà installé"
    fi
    
    echo "✓ Installation des outils de contrôle de luminosité terminée"
}

# Usage
install_brightness_tools

Commandes de Luminosité de Base

#!/bin/bash

# Définir la luminosité à des niveaux spécifiques
set_brightness() {
    local level="$1"
    
    if [[ -z "$level" ]]; then
        echo "Usage : set_brightness <niveau>"
        echo "Le niveau doit être entre 0.0 (sombre) et 1.0 (plus lumineux)"
        return 1
    fi
    
    # Valider le niveau de luminosité
    if ! [[ "$level" =~ ^[0-9]*\.?[0-9]+$ ]] || (( $(echo "$level > 1.0" | bc -l) )) || (( $(echo "$level < 0.0" | bc -l) )); then
        echo "Erreur : Le niveau de luminosité doit être entre 0.0 et 1.0"
        return 1
    fi
    
    echo "Définition de la luminosité à ${level} ($(echo "$level * 100" | bc)%)"
    
    # Essayer différents emplacements de commande de luminosité
    if command -v brightness >/dev/null 2>&1; then
        brightness "$level"
    elif [[ -x "/usr/local/bin/brightness" ]]; then
        /usr/local/bin/brightness "$level"
    elif [[ -x "/opt/homebrew/bin/brightness" ]]; then
        /opt/homebrew/bin/brightness "$level"
    elif [[ -x "/usr/local/Cellar/brightness/1.2/bin/brightness" ]]; then
        /usr/local/Cellar/brightness/1.2/bin/brightness "$level"
    else
        echo "Erreur : Outil de contrôle de luminosité non trouvé"
        return 1
    fi
    
    echo "✓ Luminosité définie à ${level}"
}

# Niveaux de luminosité prédéfinis
set_brightness_full() {
    echo "Définition de la luminosité à 100%"
    set_brightness "1.0"
}

set_brightness_high() {
    echo "Définition de la luminosité à 75%"
    set_brightness "0.75"
}

set_brightness_medium() {
    echo "Définition de la luminosité à 50%"
    set_brightness "0.5"
}

set_brightness_low() {
    echo "Définition de la luminosité à 25%"
    set_brightness "0.25"
}

set_brightness_dim() {
    echo "Définition de la luminosité à 10%"
    set_brightness "0.1"
}

# Exemples d'utilisation
set_brightness_medium

Obtenir le Niveau de Luminosité Actuel

#!/bin/bash

# Obtenir le niveau de luminosité actuel
get_current_brightness() {
    echo "=== Luminosité d'Affichage Actuelle ==="
    
    # Essayer d'obtenir la luminosité en utilisant différentes méthodes
    local current_brightness=""
    
    # Méthode 1 : Utiliser la commande brightness
    if command -v brightness >/dev/null 2>&1; then
        current_brightness=$(brightness -l 2>/dev/null | grep -o '[0-9]*\.[0-9]*' | head -1)
    fi
    
    # Méthode 2 : Utiliser system_profiler (solution de repli)
    if [[ -z "$current_brightness" ]]; then
        current_brightness=$(system_profiler SPDisplaysDataType | grep -i "brightness" | awk '{print $2}' | head -1)
    fi
    
    # Méthode 3 : Utiliser ioreg (solution de repli alternative)
    if [[ -z "$current_brightness" ]]; then
        local brightness_raw=$(ioreg -c AppleBacklightDisplay | grep brightness | head -1)
        if [[ -n "$brightness_raw" ]]; then
            current_brightness=$(echo "$brightness_raw" | grep -o '[0-9]*\.[0-9]*')
        fi
    fi
    
    if [[ -n "$current_brightness" ]]; then
        local percentage=$(echo "$current_brightness * 100" | bc)
        echo "Luminosité Actuelle : $current_brightness (${percentage}%)"
        return 0
    else
        echo "Impossible de déterminer le niveau de luminosité actuel"
        return 1
    fi
}

# Usage
get_current_brightness

Gestion Avancée de la Luminosité

Contrôle de Luminosité Adaptatif

#!/bin/bash

# Luminosité adaptative basée sur l'heure du jour et les conditions
adaptive_brightness_control() {
    local mode="${1:-auto}"
    local location_lat="${2:-}"
    local location_lon="${3:-}"
    
    echo "=== Contrôle de Luminosité Adaptatif ==="
    echo "Mode : $mode"
    echo "Date : $(date)"
    echo ""
    
    case "$mode" in
        "auto")
            automatic_brightness_adjustment
            ;;
        "schedule")
            scheduled_brightness_adjustment
            ;;
        "ambient")
            ambient_light_brightness "$location_lat" "$location_lon"
            ;;
        "work_hours")
            work_hours_brightness
            ;;
        "battery_saver")
            battery_aware_brightness
            ;;
        *)
            echo "Mode inconnu : $mode"
            echo "Modes disponibles : auto, schedule, ambient, work_hours, battery_saver"
            return 1
            ;;
    esac
}

# Ajustement automatique de luminosité basé sur l'heure du jour
automatic_brightness_adjustment() {
    local current_hour=$(date +%H)
    local current_minute=$(date +%M)
    local time_decimal=$(echo "$current_hour + $current_minute / 60" | bc -l)
    
    echo "--- Ajustement Automatique de Luminosité ---"
    echo "Heure actuelle : $current_hour:$(printf "%02d" $current_minute)"
    
    local brightness_level
    
    if (( $(echo "$time_decimal >= 6 && $time_decimal < 9" | bc -l) )); then
        # Matin : Augmentation graduelle
        brightness_level="0.4"
        echo "Période : Matin (6:00-9:00) - Définition luminosité modérée"
    elif (( $(echo "$time_decimal >= 9 && $time_decimal < 17" | bc -l) )); then
        # Heures de travail : Luminosité complète
        brightness_level="0.8"
        echo "Période : Heures de travail (9:00-17:00) - Définition luminosité élevée"
    elif (( $(echo "$time_decimal >= 17 && $time_decimal < 20" | bc -l) )); then
        # Soirée : Luminosité moyenne
        brightness_level="0.6"
        echo "Période : Soirée (17:00-20:00) - Définition luminosité moyenne"
    elif (( $(echo "$time_decimal >= 20 && $time_decimal < 22" | bc -l) )); then
        # Nuit : Luminosité faible
        brightness_level="0.3"
        echo "Période : Nuit (20:00-22:00) - Définition luminosité faible"
    else
        # Tard dans la nuit/tôt le matin : Très faible
        brightness_level="0.1"
        echo "Période : Tard dans la nuit/Tôt le matin - Définition luminosité très faible"
    fi
    
    set_brightness "$brightness_level"
}

# Changements de luminosité programmés
scheduled_brightness_adjustment() {
    echo "--- Ajustement de Luminosité Programmé ---"
    
    # Définir l'horaire (heure:niveau_luminosité)
    local schedule=(
        "06:00:0.3"  # Aube
        "08:00:0.6"  # Matin
        "09:00:0.8"  # Début travail
        "12:00:0.9"  # Midi
        "17:00:0.7"  # Fin travail
        "19:00:0.5"  # Soirée
        "21:00:0.3"  # Nuit
        "23:00:0.1"  # Tard dans la nuit
    )
    
    local current_time=$(date +%H:%M)
    echo "Heure actuelle : $current_time"
    
    # Trouver le niveau de luminosité approprié pour l'heure actuelle
    local target_brightness="0.5"  # Par défaut
    
    for schedule_entry in "${schedule[@]}"; do
        IFS=':' read -r schedule_time schedule_brightness <<< "$schedule_entry"
        
        if [[ "$current_time" > "$schedule_time" ]] || [[ "$current_time" == "$schedule_time" ]]; then
            target_brightness="$schedule_brightness"
        fi
    done
    
    echo "Niveau de luminosité programmé : $target_brightness"
    set_brightness "$target_brightness"
}

# Gestion de luminosité consciente de la batterie
battery_aware_brightness() {
    echo "--- Gestion de Luminosité Consciente de la Batterie ---"
    
    # Obtenir les informations de batterie
    local battery_info=$(pmset -g batt)
    local battery_percentage=$(echo "$battery_info" | grep -o '[0-9]*%' | head -1 | tr -d '%')
    local power_source=$(echo "$battery_info" | grep -o "AC Power\|Battery Power" | head -1)
    
    echo "Niveau de batterie : ${battery_percentage}%"
    echo "Source d'alimentation : $power_source"
    
    local brightness_level
    
    if [[ "$power_source" == "AC Power" ]]; then
        # Sur alimentation secteur - luminosité normale
        brightness_level="0.8"
        echo "Sur alimentation secteur - Définition luminosité normale"
    else
        # Sur batterie - ajuster selon le niveau de batterie
        if [[ $battery_percentage -gt 50 ]]; then
            brightness_level="0.6"
            echo "Batterie > 50% - Définition luminosité moyenne"
        elif [[ $battery_percentage -gt 20 ]]; then
            brightness_level="0.4"
            echo "Batterie 20-50% - Définition luminosité faible"
        else
            brightness_level="0.2"
            echo "Batterie < 20% - Définition luminosité très faible"
        fi
    fi
    
    set_brightness "$brightness_level"
}

# Usage
adaptive_brightness_control "auto"

Système de Gestion d'Affichage d'Entreprise

#!/bin/bash

# Outil de Gestion de Luminosité d'Affichage MacFleet
# Contrôle d'affichage complet, optimisation énergétique et gestion de flotte

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_display_management.log"
REPORT_DIR="/etc/macfleet/reports/display"
CONFIG_DIR="/etc/macfleet/display"
POLICY_DIR="/etc/macfleet/policies/display"
SCHEDULE_DIR="/etc/macfleet/schedules/display"

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

# Modèles de politiques de gestion d'affichage
declare -A DISPLAY_POLICIES=(
    ["enterprise_standard"]="adaptive_brightness,battery_optimization,work_hours_profile,user_override_limited"
    ["energy_saver"]="aggressive_dimming,battery_priority,low_brightness_default,power_aware_scheduling"
    ["presentation_mode"]="high_brightness,stable_settings,no_auto_dimming,optimal_visibility"
    ["kiosk_display"]="fixed_brightness,no_user_control,scheduled_adjustments,energy_optimized"
    ["healthcare"]="eye_strain_reduction,shift_appropriate,patient_privacy,energy_conscious"
    ["financial"]="security_dimming,privacy_protection,energy_compliance,professional_display"
    ["education"]="classroom_optimized,energy_teaching,adaptive_learning,student_friendly"
    ["retail"]="customer_facing,bright_displays,brand_consistency,operational_hours"
    ["manufacturing"]="industrial_visibility,safety_priority,harsh_environment,energy_efficient"
    ["government"]="security_compliant,energy_mandates,accessibility_aware,audit_ready"
)

# Profils de luminosité pour différents cas d'usage
declare -A BRIGHTNESS_PROFILES=(
    ["work_day"]="morning:0.4,work_start:0.8,lunch:0.9,afternoon:0.8,work_end:0.6"
    ["energy_saver"]="morning:0.3,work_start:0.6,lunch:0.7,afternoon:0.6,work_end:0.4"
    ["presentation"]="all_day:0.9,constant_high:1.0"
    ["night_shift"]="evening:0.4,night:0.2,late_night:0.1,dawn:0.3"
    ["retail_hours"]="open:0.9,peak:1.0,closing:0.7,after_hours:0.2"
    ["healthcare_24"]="day_shift:0.7,evening_shift:0.5,night_shift:0.3,emergency:0.8"
)

# Seuils d'optimisation énergétique
declare -A ENERGY_THRESHOLDS=(
    ["battery_critical"]="20:0.2"      # Sous 20% batterie : 20% luminosité
    ["battery_low"]="30:0.4"           # Sous 30% batterie : 40% luminosité
    ["battery_medium"]="50:0.6"        # Sous 50% batterie : 60% luminosité
    ["battery_high"]="80:0.8"          # Au-dessus 80% batterie : 80% luminosité
    ["ac_power"]="100:0.9"             # Sur alimentation secteur : 90% luminosité
)

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

# Contrôle de luminosité amélioré avec validation
set_brightness_enhanced() {
    local brightness_level="$1"
    local reason="${2:-Ajustement manuel}"
    local user="${3:-$(whoami)}"
    
    log_action "Définition luminosité à $brightness_level pour utilisateur $user - Raison : $reason"
    
    # Valider le niveau de luminosité
    if ! [[ "$brightness_level" =~ ^[0-9]*\.?[0-9]+$ ]] || 
       (( $(echo "$brightness_level > 1.0" | bc -l) )) || 
       (( $(echo "$brightness_level < 0.0" | bc -l) )); then
        log_action "ERREUR : Niveau de luminosité invalide : $brightness_level"
        return 1
    fi
    
    # Stocker la luminosité précédente pour capacité de retour en arrière
    local previous_brightness=$(get_current_brightness_value)
    
    # Appliquer le changement de luminosité
    local brightness_cmd=""
    if command -v brightness >/dev/null 2>&1; then
        brightness_cmd="brightness"
    elif [[ -x "/opt/homebrew/bin/brightness" ]]; then
        brightness_cmd="/opt/homebrew/bin/brightness"
    elif [[ -x "/usr/local/bin/brightness" ]]; then
        brightness_cmd="/usr/local/bin/brightness"
    elif [[ -x "/usr/local/Cellar/brightness/1.2/bin/brightness" ]]; then
        brightness_cmd="/usr/local/Cellar/brightness/1.2/bin/brightness"
    else
        log_action "ERREUR : Commande de contrôle de luminosité non trouvée"
        return 1
    fi
    
    if $brightness_cmd "$brightness_level" 2>/dev/null; then
        local percentage=$(echo "$brightness_level * 100" | bc)
        log_action "SUCCÈS : Luminosité définie à $brightness_level (${percentage}%)"
        
        # Enregistrer le changement dans l'historique
        echo "$(date '+%Y-%m-%d %H:%M:%S'),$user,$previous_brightness,$brightness_level,$reason" >> "$CONFIG_DIR/brightness_history.csv"
        
        return 0
    else
        log_action "ERREUR : Échec de définition de luminosité à $brightness_level"
        return 1
    fi
}

# Obtenir la luminosité actuelle comme valeur numérique
get_current_brightness_value() {
    local current_brightness=""
    
    if command -v brightness >/dev/null 2>&1; then
        current_brightness=$(brightness -l 2>/dev/null | grep -o '[0-9]*\.[0-9]*' | head -1)
    fi
    
    if [[ -n "$current_brightness" ]]; then
        echo "$current_brightness"
    else
        echo "0.5"  # Valeur par défaut de repli
    fi
}

# Appliquer un profil de luminosité
apply_brightness_profile() {
    local profile_name="$1"
    local override_time="${2:-}"
    
    log_action "Application du profil de luminosité : $profile_name"
    
    if [[ -z "${BRIGHTNESS_PROFILES[$profile_name]}" ]]; then
        log_action "ERREUR : Profil de luminosité inconnu : $profile_name"
        echo "Profils disponibles : ${!BRIGHTNESS_PROFILES[*]}"
        return 1
    fi
    
    local profile_settings="${BRIGHTNESS_PROFILES[$profile_name]}"
    local current_time="${override_time:-$(date +%H:%M)}"
    local current_hour=$(echo "$current_time" | cut -d: -f1)
    
    echo "=== Application du Profil de Luminosité : $profile_name ==="
    echo "Heure actuelle : $current_time"
    echo "Paramètres de profil : $profile_settings"
    
    # Analyser les paramètres de profil et trouver la luminosité appropriée
    local target_brightness="0.5"  # Par défaut
    local matched_period="default"
    
    IFS=',' read -ra SETTINGS <<< "$profile_settings"
    for setting in "${SETTINGS[@]}"; do
        IFS=':' read -ra TIME_BRIGHTNESS <<< "$setting"
        local time_period="${TIME_BRIGHTNESS[0]}"
        local brightness_value="${TIME_BRIGHTNESS[1]}"
        
        case "$time_period" in
            "morning")
                if [[ $current_hour -ge 6 && $current_hour -lt 9 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="morning"
                fi
                ;;
            "work_start"|"work")
                if [[ $current_hour -ge 9 && $current_hour -lt 12 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="work_start"
                fi
                ;;
            "lunch"|"midday")
                if [[ $current_hour -ge 12 && $current_hour -lt 14 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="lunch"
                fi
                ;;
            "afternoon")
                if [[ $current_hour -ge 14 && $current_hour -lt 17 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="afternoon"
                fi
                ;;
            "work_end"|"evening")
                if [[ $current_hour -ge 17 && $current_hour -lt 20 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="evening"
                fi
                ;;
            "night")
                if [[ $current_hour -ge 20 && $current_hour -lt 23 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="night"
                fi
                ;;
            "late_night")
                if [[ $current_hour -ge 23 || $current_hour -lt 6 ]]; then
                    target_brightness="$brightness_value"
                    matched_period="late_night"
                fi
                ;;
            "all_day"|"constant_high")
                target_brightness="$brightness_value"
                matched_period="all_day"
                ;;
        esac
    done
    
    echo "Période correspondante : $matched_period"
    echo "Luminosité cible : $target_brightness"
    
    # Appliquer la luminosité
    set_brightness_enhanced "$target_brightness" "Profil : $profile_name ($matched_period)"
}

# Gestion de luminosité consciente de l'énergie
energy_aware_brightness() {
    local policy="${1:-balanced}"
    
    log_action "Démarrage gestion luminosité consciente énergie avec politique : $policy"
    
    echo "=== Gestion de Luminosité Consciente de l'Énergie ==="
    echo "Politique : $policy"
    echo ""
    
    # Obtenir le statut d'alimentation
    local battery_info=$(pmset -g batt)
    local battery_percentage=$(echo "$battery_info" | grep -o '[0-9]*%' | head -1 | tr -d '%')
    local power_source=$(echo "$battery_info" | grep -o "AC Power\|Battery Power" | head -1)
    local charging_status=$(echo "$battery_info" | grep -o "charging\|charged\|discharging" | head -1)
    
    echo "--- Statut d'Alimentation ---"
    echo "Source d'Alimentation : $power_source"
    echo "Niveau de Batterie : ${battery_percentage}%"
    echo "Statut de Charge : $charging_status"
    
    # Déterminer la luminosité basée sur la politique énergétique
    local target_brightness=""
    local energy_reason=""
    
    case "$policy" in
        "aggressive")
            if [[ "$power_source" == "AC Power" ]]; then
                target_brightness="0.8"
                energy_reason="Alimentation secteur - luminosité normale"
            else
                if [[ $battery_percentage -lt 20 ]]; then
                    target_brightness="0.15"
                    energy_reason="Batterie critique - luminosité minimale"
                elif [[ $battery_percentage -lt 40 ]]; then
                    target_brightness="0.25"
                    energy_reason="Batterie faible - luminosité très faible"
                else
                    target_brightness="0.4"
                    energy_reason="Alimentation batterie - luminosité faible"
                fi
            fi
            ;;
        "balanced")
            if [[ "$power_source" == "AC Power" ]]; then
                target_brightness="0.8"
                energy_reason="Alimentation secteur - luminosité normale"
            else
                if [[ $battery_percentage -lt 20 ]]; then
                    target_brightness="0.2"
                    energy_reason="Batterie faible - luminosité réduite"
                elif [[ $battery_percentage -lt 50 ]]; then
                    target_brightness="0.4"
                    energy_reason="Batterie moyenne - luminosité modérée"
                else
                    target_brightness="0.6"
                    energy_reason="Bonne batterie - luminosité normale"
                fi
            fi
            ;;
        "performance")
            if [[ "$power_source" == "AC Power" ]]; then
                target_brightness="0.9"
                energy_reason="Alimentation secteur - luminosité élevée"
            else
                if [[ $battery_percentage -lt 15 ]]; then
                    target_brightness="0.3"
                    energy_reason="Batterie critique - économie d'énergie"
                else
                    target_brightness="0.7"
                    energy_reason="Alimentation batterie - maintenir visibilité"
                fi
            fi
            ;;
    esac
    
    echo ""
    echo "--- Décision Énergétique ---"
    echo "Politique : $policy"
    echo "Décision : $energy_reason"
    echo "Luminosité Cible : $target_brightness"
    
    # Appliquer le changement de luminosité
    set_brightness_enhanced "$target_brightness" "$energy_reason"
    
    # Journaliser l'estimation d'économie d'énergie
    local current_brightness=$(get_current_brightness_value)
    local energy_savings=$(echo "($current_brightness - $target_brightness) * 20" | bc)  # Estimation approximative
    
    if (( $(echo "$energy_savings > 0" | bc -l) )); then
        echo "Économies d'énergie estimées : ${energy_savings}% réduction puissance affichage"
        log_action "Économies d'énergie estimées : ${energy_savings}% réduction puissance affichage"
    fi
}

# Gestion de luminosité de flotte
manage_fleet_brightness() {
    local operation="$1"
    local target_brightness="$2"
    local fleet_scope="${3:-local}"
    
    log_action "Gestion luminosité flotte : $operation (portée : $fleet_scope)"
    
    echo "=== Gestion de Luminosité de Flotte ==="
    echo "Opération : $operation"
    echo "Luminosité Cible : $target_brightness"
    echo "Portée Flotte : $fleet_scope"
    echo ""
    
    case "$operation" in
        "set_all")
            echo "Définition luminosité à $target_brightness sur toute la flotte..."
            set_brightness_enhanced "$target_brightness" "Ajustement à l'échelle de la flotte"
            ;;
        "energy_optimize")
            echo "Optimisation de la luminosité pour l'efficacité énergétique..."
            energy_aware_brightness "balanced"
            ;;
        "sync_profiles")
            echo "Synchronisation des profils de luminosité sur la flotte..."
            apply_brightness_profile "work_day"
            ;;
        "emergency_dim")
            echo "Application atténuation d'urgence pour conservation énergie..."
            set_brightness_enhanced "0.1" "Conservation d'énergie d'urgence"
            ;;
        "restore_normal")
            echo "Restauration des niveaux de luminosité normaux..."
            apply_brightness_profile "work_day"
            ;;
        *)
            log_action "ERREUR : Opération de flotte inconnue : $operation"
            return 1
            ;;
    esac
    
    # Générer le rapport de statut de flotte
    generate_brightness_status_report
}

# Générer un rapport de statut de luminosité
generate_brightness_status_report() {
    local report_file="$REPORT_DIR/brightness_status_$(date +%Y%m%d_%H%M%S).json"
    
    local current_brightness=$(get_current_brightness_value)
    local battery_info=$(pmset -g batt)
    local battery_percentage=$(echo "$battery_info" | grep -o '[0-9]*%' | head -1 | tr -d '%')
    local power_source=$(echo "$battery_info" | grep -o "AC Power\|Battery Power" | head -1)
    
    cat > "$report_file" << EOF
{
    "brightness_status_report": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION",
        "display_status": {
            "current_brightness": $current_brightness,
            "brightness_percentage": $(echo "$current_brightness * 100" | bc),
            "power_source": "$power_source",
            "battery_level": $battery_percentage
        },
        "system_info": {
            "os_version": "$(sw_vers -productVersion)",
            "hardware_model": "$(system_profiler SPHardwareDataType | grep 'Model Identifier' | awk '{print $3}')",
            "display_count": $(system_profiler SPDisplaysDataType | grep "Display Type" | wc -l | tr -d ' ')
        }
    }
}
EOF
    
    echo "Rapport de statut de luminosité généré : $report_file"
    log_action "Rapport de statut généré : $report_file"
}

# Fonction d'exécution principale
main() {
    local action="${1:-help}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Gestion de Luminosité d'Affichage MacFleet Démarrée ==="
    log_action "Action : $action"
    
    case "$action" in
        "set")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 set <niveau_luminosité> [raison]"
                echo "Niveau de luminosité : 0.0-1.0 (0-100%)"
                exit 1
            fi
            set_brightness_enhanced "$param1" "${param2:-Définition manuelle}"
            ;;
        "get")
            echo "Luminosité actuelle : $(get_current_brightness_value)"
            ;;
        "profile")
            if [[ -z "$param1" ]]; then
                echo "Profils disponibles : ${!BRIGHTNESS_PROFILES[*]}"
                exit 1
            fi
            apply_brightness_profile "$param1" "$param2"
            ;;
        "energy")
            energy_aware_brightness "${param1:-balanced}"
            ;;
        "fleet")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 fleet <opération> [luminosité] [portée]"
                echo "Opérations : set_all, energy_optimize, sync_profiles, emergency_dim, restore_normal"
                exit 1
            fi
            manage_fleet_brightness "$param1" "$param2" "$param3"
            ;;
        "adaptive")
            adaptive_brightness_control "${param1:-auto}"
            ;;
        "install")
            install_brightness_tools
            ;;
        "help")
            echo "Usage : $0 [action] [options...]"
            echo "Actions :"
            echo "  set <niveau> [raison] - Définir niveau luminosité (0.0-1.0)"
            echo "  get - Obtenir niveau luminosité actuel"
            echo "  profile <nom> [heure] - Appliquer profil luminosité"
            echo "  energy [politique] - Gestion luminosité consciente énergie"
            echo "  fleet <opération> [params] - Gestion luminosité flotte"
            echo "  adaptive [mode] - Contrôle luminosité adaptatif"
            echo "  install - Installer outils contrôle luminosité"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Profils : ${!BRIGHTNESS_PROFILES[*]}"
            echo "Politiques : ${!DISPLAY_POLICIES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion de luminosité d'affichage terminée ==="
}

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

Notes Importantes

  • Homebrew Requis - L'outil de contrôle de luminosité nécessite l'installation de Homebrew
  • Support Mac Intel - Certaines commandes de luminosité fonctionnent uniquement sur les Mac basés Intel
  • Conscience Batterie - La luminosité doit être ajustée selon la source d'alimentation et le niveau de batterie
  • Expérience Utilisateur - Les changements soudains de luminosité peuvent être dérangeants ; implémenter des transitions graduelles
  • Politiques d'Entreprise - Différents environnements de travail nécessitent différentes stratégies de luminosité
  • Conservation d'Énergie - Une luminosité plus faible prolonge significativement la durée de vie de la batterie
  • Considérations Santé - Une luminosité appropriée réduit la fatigue et la tension oculaires