Tutorial

New updates and improvements to Roundfleet.

System Preferences Management on macOS

Manage and control System Preferences access on your Roundfleet devices with comprehensive preference pane management, user restriction controls, and enterprise configuration solutions. This tutorial covers hiding, disabling, and controlling System Preferences for enhanced security and compliance.

Understanding System Preferences Management

System Preferences on macOS provides access to system configuration settings:

  • Preference Panes - Individual configuration modules (Network, Security, Users, etc.)
  • Bundle Identifiers - Unique identifiers for each preference pane
  • Hidden vs Disabled - Different levels of access restriction
  • Enterprise Control - Centralized management of user access to system settings

Enterprise Use Cases

System Preferences management benefits enterprise environments:

  • Security Hardening - Prevent unauthorized configuration changes
  • Compliance - Ensure devices meet regulatory requirements
  • User Experience - Simplify interfaces by hiding irrelevant options
  • Administrative Control - Centralize configuration management
  • Data Protection - Restrict access to sensitive system settings

Basic System Preferences Control

Hide Profiles Pane

#!/bin/bash

# Hide Profiles pane from System Preferences
hide_profiles_pane() {
    echo "=== Hiding Profiles Pane ==="
    
    # Check macOS version (hiding requires macOS 13.0+)
    local macos_version=$(sw_vers -productVersion | cut -d. -f1)
    if [[ $macos_version -lt 13 ]]; then
        echo "Warning: Hiding panes requires macOS 13.0 or later"
        echo "Current version: $(sw_vers -productVersion)"
        echo "Using disable instead of hide..."
        disable_profiles_pane
        return
    fi
    
    # Hide the Profiles pane
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        HiddenPreferencePanes -array "com.apple.preferences.configurationprofiles"
    
    if [[ $? -eq 0 ]]; then
        echo "✓ Profiles pane hidden successfully"
        echo "Users will no longer see the Profiles pane in System Preferences"
    else
        echo "✗ Failed to hide Profiles pane"
        return 1
    fi
}

# Disable Profiles pane (alternative for older macOS)
disable_profiles_pane() {
    echo "=== Disabling Profiles Pane ==="
    
    # Disable the Profiles pane (works on macOS 10.2+)
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "com.apple.preferences.configurationprofiles"
    
    if [[ $? -eq 0 ]]; then
        echo "✓ Profiles pane disabled successfully"
        echo "Profiles pane will appear greyed out in System Preferences"
    else
        echo "✗ Failed to disable Profiles pane"
        return 1
    fi
}

# Usage
hide_profiles_pane

Unhide/Re-enable Profiles Pane

#!/bin/bash

# Restore Profiles pane access
restore_profiles_pane() {
    echo "=== Restoring Profiles Pane Access ==="
    
    # Remove from hidden panes
    local hidden_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null)
    if [[ -n "$hidden_panes" ]]; then
        echo "Removing from hidden panes..."
        defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
    fi
    
    # Remove from disabled panes
    local disabled_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null)
    if [[ -n "$disabled_panes" ]]; then
        echo "Removing from disabled panes..."
        defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
    fi
    
    echo "✓ Profiles pane access restored"
    echo "Users can now access the Profiles pane in System Preferences"
}

# Usage
restore_profiles_pane

Multiple Preference Panes Management

#!/bin/bash

# Manage multiple preference panes simultaneously
manage_multiple_panes() {
    local action="${1:-hide}"  # hide, disable, or restore
    local panes=("${@:2}")    # Array of pane identifiers
    
    if [[ ${#panes[@]} -eq 0 ]]; then
        echo "Usage: manage_multiple_panes [hide|disable|restore] <pane1> [pane2] ..."
        echo "Example: manage_multiple_panes hide profiles bluetooth network"
        return 1
    fi
    
    echo "=== Managing Multiple Preference Panes ==="
    echo "Action: $action"
    echo "Panes: ${panes[*]}"
    echo ""
    
    # Convert friendly names to bundle identifiers
    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 "✗ Unknown pane: $pane"
        fi
    done
    
    if [[ ${#bundle_ids[@]} -eq 0 ]]; then
        echo "No valid panes specified"
        return 1
    fi
    
    # Apply the action
    case "$action" in
        "hide")
            defaults write "/Library/Preferences/com.apple.systempreferences" \
                HiddenPreferencePanes -array "${bundle_ids[@]}"
            echo "✓ Panes hidden successfully"
            ;;
        "disable")
            defaults write "/Library/Preferences/com.apple.systempreferences" \
                DisabledPreferencePanes -array "${bundle_ids[@]}"
            echo "✓ Panes disabled successfully"
            ;;
        "restore")
            defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
            defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
            echo "✓ All panes restored"
            ;;
        *)
            echo "Invalid action: $action"
            return 1
            ;;
    esac
}

# Convert friendly names to bundle identifiers
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" ;;
        *) echo "" ;;
    esac
}

# Usage examples
# manage_multiple_panes hide profiles bluetooth network
# manage_multiple_panes disable security users sharing
# manage_multiple_panes restore

Advanced System Preferences Management

Policy-Based Preference Management

#!/bin/bash

# Policy-based system preferences management
apply_preference_policy() {
    local policy_name="${1:-standard_office}"
    local user_role="${2:-standard_user}"
    
    echo "=== Applying Preference Policy ==="
    echo "Policy: $policy_name"
    echo "User Role: $user_role"
    echo ""
    
    # Define policies
    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 "Unknown policy: $policy_name"
            return 1
            ;;
    esac
}

# Kiosk mode policy (maximum restrictions)
apply_kiosk_policy() {
    echo "Applying kiosk mode policy..."
    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 "✓ Kiosk policy applied - most preferences hidden"
}

# Locked down policy (high security)
apply_locked_down_policy() {
    echo "Applying locked down policy..."
    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 "✓ Locked down policy applied - security-sensitive panes disabled"
}

# Standard office policy (moderate restrictions)
apply_standard_office_policy() {
    echo "Applying standard office policy..."
    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 "✓ Standard office policy applied - minimal restrictions"
}

# Developer workstation policy (minimal restrictions)
apply_developer_policy() {
    echo "Applying developer workstation policy..."
    local restricted_panes=(
        "com.apple.preferences.configurationprofiles"
    )
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${restricted_panes[@]}"
    
    echo "✓ Developer policy applied - profile management restricted only"
}

# Educational policy (student-appropriate restrictions)
apply_educational_policy() {
    echo "Applying educational policy..."
    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 "✓ Educational policy applied - student-safe configuration"
}

# Healthcare policy (HIPAA compliance focused)
apply_healthcare_policy() {
    echo "Applying healthcare policy..."
    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 "✓ Healthcare policy applied - HIPAA compliance focused"
}

# Financial policy (enhanced security)
apply_financial_policy() {
    echo "Applying financial policy..."
    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 "✓ Financial policy applied - enhanced security restrictions"
}

# Public terminal policy (maximum protection)
apply_public_terminal_policy() {
    echo "Applying public terminal policy..."
    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 "✓ Public terminal policy applied - maximum protection"
}

# Executive policy (minimal restrictions, full access)
apply_executive_policy() {
    echo "Applying executive policy..."
    # Remove all restrictions for executives
    defaults delete "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null
    defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null
    
    echo "✓ Executive policy applied - full access granted"
}

# Contractor policy (temporary access restrictions)
apply_contractor_policy() {
    echo "Applying contractor policy..."
    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 "✓ Contractor policy applied - temporary access restrictions"
}

Enterprise System Preferences Management Tool

#!/bin/bash

# Roundfleet System Preferences Management Tool
# Comprehensive preference pane control and enterprise policy management

# 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"

# Create directories if they don't exist
mkdir -p "$REPORT_DIR" "$CONFIG_DIR" "$POLICY_DIR" "$BACKUP_DIR"

# Comprehensive preference pane mapping
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"
)

# Enterprise policy templates
declare -A POLICY_TEMPLATES=(
    ["kiosk_mode"]="Maximum restrictions for public kiosks and displays"
    ["locked_down"]="High security restrictions for sensitive environments"
    ["standard_office"]="Moderate restrictions for typical office environments"
    ["developer_workstation"]="Minimal restrictions for development environments"
    ["educational"]="Student-appropriate restrictions for educational institutions"
    ["healthcare"]="HIPAA-compliant restrictions for healthcare environments"
    ["financial"]="Enhanced security for financial services environments"
    ["public_terminal"]="Maximum protection for public access terminals"
    ["executive"]="Minimal to no restrictions for executive users"
    ["contractor"]="Temporary access restrictions for contract workers"
)

# Compliance frameworks
declare -A COMPLIANCE_FRAMEWORKS=(
    ["hipaa"]="Health Insurance Portability and Accountability Act"
    ["sox"]="Sarbanes-Oxley Act compliance"
    ["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"]="Common Criteria security evaluation standard"
)

# Logging function
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"
}

# Enterprise system preferences management
enterprise_preferences_management() {
    local operation="${1:-status}"
    local policy_name="${2:-standard_office}"
    local target_panes="${3:-}"
    local compliance_framework="${4:-}"
    
    log_action "Starting enterprise preferences management" "INFO"
    log_action "Operation: $operation, Policy: $policy_name" "INFO"
    
    echo "=== Enterprise System Preferences Management ==="
    echo "Operation: $operation"
    echo "Policy: $policy_name"
    echo "Target Panes: ${target_panes:-all_policy_defined}"
    echo "Compliance Framework: ${compliance_framework:-none}"
    echo "Management ID: $(uuidgen)"
    echo ""
    
    # Backup current configuration
    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 "Error: No target panes specified for hide operation"
                return 1
            fi
            ;;
        "disable_panes")
            if [[ -n "$target_panes" ]]; then
                disable_specific_panes "$target_panes"
            else
                echo "Error: No target panes specified for disable operation"
                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 "Unknown operation: $operation"
            return 1
            ;;
    esac
    
    # Generate management report
    generate_preferences_report "$operation" "$policy_name" "$target_panes" "$compliance_framework"
    
    log_action "preferences management completed" "INFO"
}

# Backup current configuration
backup_current_configuration() {
    local backup_file="$BACKUP_DIR/preferences_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    echo "--- Creating Configuration Backup ---"
    
    # Copy current system preferences configuration
    if [[ -f "/Library/Preferences/com.apple.systempreferences.plist" ]]; then
        cp "/Library/Preferences/com.apple.systempreferences.plist" "$backup_file"
        echo "✓ Configuration backed up to: $backup_file"
        log_action "Configuration backed up: $backup_file" "INFO"
    else
        echo "⚠️ No existing configuration file found"
        log_action "No existing configuration file to backup" "WARNING"
    fi
}

# Apply enterprise policy with compliance considerations
apply_enterprise_policy() {
    local policy_name="$1"
    local compliance_framework="$2"
    
    echo "--- Applying Enterprise Policy ---"
    echo "Policy: $policy_name"
    echo "Compliance: ${compliance_framework:-none}"
    
    # Apply base policy
    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 "Unknown policy: $policy_name"
            return 1
            ;;
    esac
    
    # Apply compliance-specific modifications
    if [[ -n "$compliance_framework" ]]; then
        apply_compliance_modifications "$compliance_framework"
    fi
    
    echo "✓ Enterprise policy applied successfully"
}

# Apply compliance-specific modifications
apply_compliance_modifications() {
    local framework="$1"
    
    echo "--- Applying Compliance Modifications ---"
    echo "Framework: $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 "Unknown compliance framework: $framework"
            ;;
    esac
}

# HIPAA compliance modifications
apply_hipaa_compliance() {
    echo "Applying HIPAA compliance modifications..."
    
    # Additional restrictions for healthcare data protection
    local hipaa_restricted=(
        "com.apple.preferences.sharing"
        "com.apple.preference.network"
        "com.apple.prefs.backup"
        "com.apple.preferences.internetaccounts"
    )
    
    # Get current disabled panes
    local current_disabled=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null | tr -d '(),"' | tr '\n' ' ')
    
    # Combine with HIPAA requirements
    local combined_disabled=($current_disabled "${hipaa_restricted[@]}")
    
    defaults write "/Library/Preferences/com.apple.systempreferences" \
        DisabledPreferencePanes -array "${combined_disabled[@]}"
    
    echo "✓ HIPAA compliance modifications applied"
}

# SOX compliance modifications
apply_sox_compliance() {
    echo "Applying SOX compliance modifications..."
    
    # Financial audit and control requirements
    local sox_restricted=(
        "com.apple.preferences.configurationprofiles"
        "com.apple.preference.security"
        "com.apple.preferences.users"
        "com.apple.preference.datetime"
    )
    
    # Similar pattern for 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 "✓ SOX compliance modifications applied"
}

# PCI DSS compliance modifications
apply_pci_dss_compliance() {
    echo "Applying PCI DSS compliance modifications..."
    
    # Payment card industry requirements
    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 "✓ PCI DSS compliance modifications applied"
}

# FERPA compliance modifications
apply_ferpa_compliance() {
    echo "Applying FERPA compliance modifications..."
    
    # Educational privacy requirements
    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 "✓ FERPA compliance modifications applied"
}

# GDPR compliance modifications
apply_gdpr_compliance() {
    echo "Applying GDPR compliance modifications..."
    
    # European data protection requirements
    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 "✓ GDPR compliance modifications applied"
}

# Show current preferences status
show_preferences_status() {
    echo "--- System Preferences Status ---"
    
    # Check hidden panes
    local hidden_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" HiddenPreferencePanes 2>/dev/null)
    if [[ -n "$hidden_panes" ]]; then
        echo "Hidden Panes:"
        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 "Hidden Panes: None"
    fi
    
    echo ""
    
    # Check disabled panes
    local disabled_panes=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledPreferencePanes 2>/dev/null)
    if [[ -n "$disabled_panes" ]]; then
        echo "Disabled Panes:"
        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 "Disabled Panes: None"
    fi
}

# Get friendly name from bundle identifier
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 "unknown"
}

# Generate comprehensive preferences report
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"
    
    # Get current configuration
    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 "Preferences report generated: $report_file"
    log_action "Preferences report generated: $report_file" "INFO"
}

# List available policies
list_available_policies() {
    echo "--- Available Enterprise Policies ---"
    for policy in "${!POLICY_TEMPLATES[@]}"; do
        echo "  $policy: ${POLICY_TEMPLATES[$policy]}"
    done
}

# List available preference panes
list_available_panes() {
    echo "--- Available Preference Panes ---"
    for pane in "${!PREFERENCE_PANES[@]}"; do
        echo "  $pane: ${PREFERENCE_PANES[$pane]}"
    done
}

# Main execution function
main() {
    local operation="${1:-help}"
    local policy="${2:-}"
    local panes="${3:-}"
    local compliance="${4:-}"
    
    log_action "=== Roundfleet System Preferences Management Started ===" "INFO"
    log_action "Operation: $operation" "INFO"
    
    case "$operation" in
        "apply")
            if [[ -z "$policy" ]]; then
                echo "Usage: $0 apply <policy_name> [compliance_framework]"
                echo "Available policies: ${!POLICY_TEMPLATES[*]}"
                exit 1
            fi
            enterprise_preferences_management "apply_policy" "$policy" "" "$compliance"
            ;;
        "hide")
            if [[ -z "$panes" ]]; then
                echo "Usage: $0 hide <pane1,pane2,...>"
                echo "Available panes: ${!PREFERENCE_PANES[*]}"
                exit 1
            fi
            enterprise_preferences_management "hide_panes" "" "$panes"
            ;;
        "disable")
            if [[ -z "$panes" ]]; then
                echo "Usage: $0 disable <pane1,pane2,...>"
                echo "Available panes: ${!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 [operation] [options...]"
            echo "Operations:"
            echo "  apply <policy> [compliance] - Apply enterprise policy"
            echo "  hide <panes> - Hide specific preference panes"
            echo "  disable <panes> - Disable specific preference panes"
            echo "  restore - Restore all preference panes"
            echo "  status - Show current preferences status"
            echo "  audit [compliance] - Perform compliance audit"
            echo "  list-policies - List available policies"
            echo "  list-panes - List available preference panes"
            echo "  help - Show this help"
            echo ""
            echo "Available Policies: ${!POLICY_TEMPLATES[*]}"
            echo "Compliance Frameworks: ${!COMPLIANCE_FRAMEWORKS[*]}"
            ;;
        *)
            log_action "ERROR: Unknown operation: $operation" "ERROR"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
    
    log_action "=== System preferences management completed ===" "INFO"
}

# Execute main function
main "$@"

Important Considerations

macOS Version Compatibility

  • Hiding Panes: Requires macOS 13.0 or later (HiddenPreferencePanes)
  • Disabling Panes: Works on macOS 10.2 and later (DisabledPreferencePanes)
  • Bundle Identifiers: May change between macOS versions
  • System Integrity Protection: Some restrictions may not apply with SIP enabled

Enterprise Deployment Notes

  • User Impact: Hidden/disabled panes affect all users on the device
  • Administrative Access: Changes require administrator privileges
  • Policy Testing: Always test policies on non-production devices first
  • Backup and Recovery: Maintain configuration backups for policy rollback

Security and Compliance Considerations

  • Principle of Least Privilege: Only restrict access to necessary preference panes
  • Audit Logging: All preference changes should be logged for compliance
  • Compliance Frameworks: Different industries require specific restrictions
  • User Training: Inform users about restricted functionality and alternatives

System Information Management on macOS

Collect and analyze comprehensive system information across your Roundfleet devices using advanced system profiling, automated data collection, and enterprise-grade analytics. This tutorial provides powerful tools for implementing organizational device inventory, monitoring, and compliance reporting.

Understanding macOS System Information

macOS provides several tools for system information gathering:

  • system_profiler - Comprehensive system information collection
  • uname - Basic system and kernel information
  • sw_vers - Software version information
  • hwpref - Hardware preference data
  • ioreg - I/O Registry hardware information
  • System Information.app - GUI system information interface

Basic System Information Operations

Complete System Information

#!/bin/bash

# Get complete system information
echo "=== Complete System Information ==="
system_profiler

echo "System information collection completed"

List Available Data Types

#!/bin/bash

# List all available system profiler data types
echo "=== Available Data Types ==="
system_profiler --listDataTypes

echo "Data types listing completed"

Specific System Information

#!/bin/bash

# Get specific system information
DATA_TYPE="${1:-SPHardwareDataType}"

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

echo "Specific system information retrieved"

Save System Report to File

#!/bin/bash

# Save system information to file
REPORT_FILE="${1:-/tmp/system_report_$(date +%Y%m%d_%H%M%S).txt}"

echo "=== Saving System Report ==="
system_profiler > "$REPORT_FILE"

echo "System report saved to: $REPORT_FILE"

Enterprise System Information Management System

#!/bin/bash

# Roundfleet Enterprise System Information Management System
# Comprehensive system data collection, analysis, and monitoring

# 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"

# Create directory structure
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
}

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

# System Information Categories for Enterprise Management
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"
)

# Data Collection Policies
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"
)

# System Health Monitoring Thresholds
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 week
)

# Comprehensive system information collection
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 "Starting system information collection: $collection_policy"
    
    # Initialize collection metadata
    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/,//')
    
    # Collect data based on policy
    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
    
    # Collect data for each specified type
    for data_type in $data_types; do
        [[ -z "$data_type" ]] && continue
        
        log_action "Collecting data type: $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
    
    # Additional system metrics
    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
    
    # Create structured output
    if [[ "$output_format" == "json" ]]; then
        # Remove trailing comma from collected data
        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
=== Roundfleet System Information Report ===
Collection ID: $collection_id
Timestamp: $(date)
Policy: $collection_policy
Hostname: $hostname
Serial Number: $serial_number
Model: $model_identifier
OS Version: $os_version ($build_version)
Uptime: $uptime

$collected_data
EOF
    fi
    
    log_action "System information collection completed: $output_file"
    echo "$output_file"
}

# System health analysis
analyze_system_health() {
    local analysis_type="$1"
    local health_report="$REPORTS_DIR/system_health_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting system health analysis: $analysis_type"
    
    # Collect basic health metrics
    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 ))
    
    # System load analysis
    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")
    
    # Battery information (if available)
    local battery_cycle_count=0
    local battery_condition="Unknown"
    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
    
    # Determine health status
    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\"High CPU temperature: ${cpu_temp}°C\","
    fi
    
    if [[ $storage_usage -gt ${HEALTH_THRESHOLDS[storage_usage_warning]} ]]; then
        health_status="warning"
        health_alerts="$health_alerts\"High storage usage: ${storage_usage}%\","
    fi
    
    if [[ $battery_cycle_count -gt ${HEALTH_THRESHOLDS[battery_cycle_warning]} ]]; then
        health_status="warning"
        health_alerts="$health_alerts\"High battery cycle count: $battery_cycle_count\","
    fi
    
    if [[ $uptime_hours -gt ${HEALTH_THRESHOLDS[uptime_excessive_hours]} ]]; then
        health_status="attention"
        health_alerts="$health_alerts\"Excessive uptime: ${uptime_hours} hours\","
    fi
    
    # Remove trailing comma
    health_alerts="${health_alerts%,}"
    
    # Create health report
    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 "\"Address health alerts for optimal performance\",")
    $([ $uptime_hours -gt 72 ] && echo "\"Consider system restart for optimal performance\",")
    $([ $storage_usage -gt 80 ] && echo "\"Review storage usage and cleanup if necessary\",")
    "\"Regular health monitoring recommended\""
  ]
}
EOF
    
    if [[ "$health_status" != "healthy" ]]; then
        log_action "HEALTH WARNING: System health issues detected - $health_status"
    fi
    
    log_action "System health analysis completed: $health_report"
    echo "$health_report"
}

# Enterprise device inventory management
manage_device_inventory() {
    local inventory_action="$1"
    local device_group="${2:-default}"
    local inventory_file="$INVENTORY_DIR/device_inventory_${device_group}.json"
    
    log_action "Managing device inventory: $inventory_action for group $device_group"
    
    case "$inventory_action" in
        "register")
            # Register device in inventory
            local device_data=$(collect_system_information "hardware_inventory" "json" "false")
            local hostname=$(hostname)
            local serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
            local model=$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F': ' '{print $2}')
            local mac_address=$(ifconfig en0 | grep ether | awk '{print $2}')
            
            # Update inventory database
            if [[ -f "$inventory_file" ]]; then
                # Update existing inventory
                jq --arg hostname "$hostname" --arg serial "$serial_number" --arg model "$model" --arg mac "$mac_address" --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
                   '.devices[$hostname] = {serial_number: $serial, model: $model, mac_address: $mac, last_updated: $timestamp, status: "active"}' \
                   "$inventory_file" > "${inventory_file}.tmp" && mv "${inventory_file}.tmp" "$inventory_file"
            else
                # Create new inventory
                jq -n --arg hostname "$hostname" --arg serial "$serial_number" --arg model "$model" --arg mac "$mac_address" --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
                   '{inventory_metadata: {group: "'$device_group'", created: $timestamp}, devices: {($hostname): {serial_number: $serial, model: $model, mac_address: $mac, last_updated: $timestamp, status: "active"}}}' \
                   > "$inventory_file"
            fi
            
            log_action "Device registered in inventory: $hostname ($serial_number)"
            ;;
            
        "update")
            # Update device information
            local hostname=$(hostname)
            if [[ -f "$inventory_file" ]] && jq -e ".devices[\"$hostname\"]" "$inventory_file" >/dev/null; then
                jq --arg hostname "$hostname" --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
                   '.devices[$hostname].last_updated = $timestamp | .devices[$hostname].status = "active"' \
                   "$inventory_file" > "${inventory_file}.tmp" && mv "${inventory_file}.tmp" "$inventory_file"
                log_action "Device inventory updated: $hostname"
            else
                log_action "Device not found in inventory, registering: $hostname"
                manage_device_inventory "register" "$device_group"
            fi
            ;;
            
        "list")
            # List devices in inventory
            if [[ -f "$inventory_file" ]]; then
                echo "=== Device Inventory for Group: $device_group ==="
                jq -r '.devices | to_entries[] | "\(.key): \(.value.model) (\(.value.serial_number)) - \(.value.status)"' "$inventory_file"
            else
                echo "No inventory found for group: $device_group"
            fi
            ;;
            
        "remove")
            # Remove device from inventory
            local hostname=$(hostname)
            if [[ -f "$inventory_file" ]]; then
                jq --arg hostname "$hostname" 'del(.devices[$hostname])' "$inventory_file" > "${inventory_file}.tmp" && mv "${inventory_file}.tmp" "$inventory_file"
                log_action "Device removed from inventory: $hostname"
            fi
            ;;
    esac
}

# Compliance and security reporting
generate_compliance_report() {
    local compliance_framework="$1"
    local report_file="$COMPLIANCE_DIR/compliance_${compliance_framework}_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Generating compliance report: $compliance_framework"
    
    # Collect security-relevant system information
    local security_data=$(collect_system_information "security_focused" "json" "true")
    
    # Check specific compliance requirements
    local filevault_status=$(fdesetup status | grep -q "On" && echo "enabled" || echo "disabled")
    local firewall_status=$(sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate | grep -q "enabled" && echo "enabled" || echo "disabled")
    local gatekeeper_status=$(spctl --status | grep -q "enabled" && echo "enabled" || echo "disabled")
    local sip_status=$(csrutil status | grep -q "enabled" && echo "enabled" || echo "disabled")
    local secure_boot_status=$(nvram 94b73556-2197-4702-82a8-3e1337dafbfb:AppleSecureBootPolicy 2>/dev/null | grep -q "2" && echo "full" || echo "reduced")
    
    # Software update status
    local auto_update_status=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo "0")
    local last_update_check=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate LastSuccessfulDate 2>/dev/null || echo "Unknown")
    
    # Certificate information
    local certificate_count=$(security find-certificate -a | grep "labl" | wc -l)
    local expired_certificates=$(security find-certificate -a -p | openssl x509 -noout -checkend 0 2>/dev/null | grep -c "will expire" || echo "0")
    
    # Create compliance report based on framework
    case "$compliance_framework" in
        "nist")
            cat > "$report_file" << EOF
{
  "compliance_report": {
    "framework": "NIST Cybersecurity Framework",
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "device_info": {
      "hostname": "$(hostname)",
      "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')",
      "os_version": "$(sw_vers -productVersion)"
    }
  },
  "security_controls": {
    "identify": {
      "asset_management": "implemented",
      "system_inventory": "automated"
    },
    "protect": {
      "access_control": "$([ "$gatekeeper_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
      "data_security": "$([ "$filevault_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
      "protective_technology": "$([ "$firewall_status" == "enabled" ] && echo "implemented" || echo "needs_attention")"
    },
    "detect": {
      "security_monitoring": "basic",
      "malicious_code_protection": "$([ "$gatekeeper_status" == "enabled" ] && echo "implemented" || echo "needs_attention")"
    },
    "respond": {
      "incident_response": "manual",
      "communications": "standard"
    },
    "recover": {
      "recovery_planning": "$([ "$filevault_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
      "backup_procedures": "time_machine"
    }
  },
  "technical_controls": {
    "filevault_encryption": "$filevault_status",
    "firewall_protection": "$firewall_status",
    "gatekeeper_protection": "$gatekeeper_status",
    "system_integrity_protection": "$sip_status",
    "secure_boot": "$secure_boot_status",
    "automatic_updates": "$([ "$auto_update_status" == "1" ] && echo "enabled" || echo "disabled")",
    "certificate_management": {
      "total_certificates": $certificate_count,
      "expired_certificates": $expired_certificates
    }
  }
}
EOF
            ;;
            
        "hipaa")
            cat > "$report_file" << EOF
{
  "compliance_report": {
    "framework": "HIPAA Security Rule",
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "device_info": {
      "hostname": "$(hostname)",
      "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')",
      "os_version": "$(sw_vers -productVersion)"
    }
  },
  "administrative_safeguards": {
    "access_management": "policy_required",
    "workforce_training": "policy_required",
    "contingency_plan": "policy_required"
  },
  "physical_safeguards": {
    "facility_access": "policy_required",
    "workstation_security": "$([ "$filevault_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
    "device_controls": "$([ "$gatekeeper_status" == "enabled" ] && echo "implemented" || echo "needs_attention")"
  },
  "technical_safeguards": {
    "access_control": "$([ "$gatekeeper_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
    "audit_controls": "basic_logging",
    "integrity": "$([ "$sip_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
    "transmission_security": "$([ "$firewall_status" == "enabled" ] && echo "implemented" || echo "needs_attention")",
    "encryption": "$([ "$filevault_status" == "enabled" ] && echo "implemented" || echo "needs_attention")"
  }
}
EOF
            ;;
    esac
    
    log_action "Compliance report generated: $report_file"
    echo "Compliance report saved to: $report_file"
}

# Automated system monitoring and alerting
monitor_system_continuously() {
    local monitoring_interval="${1:-600}"  # 10 minutes default
    local alert_threshold="${2:-warning}"  # warning level default
    
    log_action "Starting continuous system monitoring (interval: ${monitoring_interval}s, threshold: $alert_threshold)"
    
    while true; do
        # Perform health analysis
        local health_report=$(analyze_system_health "continuous")
        local health_status=$(jq -r '.system_health_analysis.health_status' "$health_report" 2>/dev/null || echo "unknown")
        
        if [[ "$health_status" != "healthy" && "$health_status" != "unknown" ]]; then
            local hostname=$(hostname)
            log_action "SYSTEM ALERT: Health status is $health_status for $hostname"
            
            # Send system notification
            osascript -e "display notification \"System health: $health_status\" with title \"Roundfleet System Monitor\""
            
            # Generate detailed report if critical
            if [[ "$health_status" == "critical" ]]; then
                collect_system_information "comprehensive" "json" "false"
            fi
        fi
        
        # Update device inventory
        manage_device_inventory "update" "monitored"
        
        # Log current status
        log_action "System monitoring check completed - Status: $health_status"
        
        sleep "$monitoring_interval"
    done
}

# Fleet deployment and management
deploy_to_fleet() {
    local deployment_action="$1"
    local fleet_file="$2"
    local deployment_policy="${3:-standard}"
    
    if [[ ! -f "$fleet_file" ]]; then
        log_action "ERROR: Fleet file not found: $fleet_file"
        return 1
    fi
    
    log_action "Deploying system information management to fleet: $deployment_action"
    
    while IFS= read -r host; do
        [[ -z "$host" || "$host" =~ ^#.*$ ]] && continue
        
        echo "Deploying to: $host"
        
        # Deploy system information management to remote host
        ssh "$host" "bash -s" << EOF
#!/bin/bash
# Remote deployment of system information management: $deployment_policy

# Create Roundfleet directories
mkdir -p /etc/roundfleet/{system_information,reports,compliance,audit,system_policies,inventory}

# Collect initial system information
echo "Collecting initial system information on \$(hostname)"

case "$deployment_policy" in
    "comprehensive")
        echo "Deploying comprehensive system monitoring"
        ;;
    "security_focused")
        echo "Deploying security-focused system monitoring"
        ;;
    "compliance_audit")
        echo "Deploying compliance audit configuration"
        ;;
esac

echo "System information management deployed on \$(hostname)"
EOF
        
        if [[ $? -eq 0 ]]; then
            log_action "Successfully deployed to: $host"
        else
            log_action "Failed to deploy to: $host"
        fi
        
    done < "$fleet_file"
    
    log_action "Fleet deployment completed"
}

# Health check and system validation
perform_system_health_check() {
    echo "=== Roundfleet System Information Management Health Check ==="
    
    # Check system_profiler availability
    if command -v system_profiler >/dev/null 2>&1; then
        echo "✓ system_profiler: Available"
    else
        echo "✗ system_profiler: Not available"
    fi
    
    # Check system information accessibility
    local hardware_info=$(system_profiler SPHardwareDataType 2>/dev/null)
    if [[ -n "$hardware_info" ]]; then
        echo "✓ Hardware information: Accessible"
    else
        echo "⚠️  Hardware information: Limited access"
    fi
    
    # Check security status
    local filevault_status=$(fdesetup status)
    if echo "$filevault_status" | grep -q "On"; then
        echo "✓ FileVault: Enabled"
    else
        echo "○ FileVault: Disabled"
    fi
    
    # Check firewall status
    if sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate | grep -q "enabled"; then
        echo "✓ Firewall: Enabled"
    else
        echo "○ Firewall: Disabled"
    fi
    
    # Check Gatekeeper status
    if spctl --status | grep -q "enabled"; then
        echo "✓ Gatekeeper: Enabled"
    else
        echo "○ Gatekeeper: Disabled"
    fi
    
    # Check System Integrity Protection
    if csrutil status | grep -q "enabled"; then
        echo "✓ SIP: Enabled"
    else
        echo "⚠️  SIP: Disabled"
    fi
    
    # Check available storage space
    local available_space=$(df -h / | awk 'NR==2 {print $4}')
    echo "✓ Available storage: $available_space"
    
    # Check system uptime
    local uptime_info=$(uptime)
    echo "✓ System uptime: $uptime_info"
}

# Main execution function
main() {
    create_directories
    
    case "${1:-}" in
        "collect")
            collect_system_information "${2:-comprehensive}" "${3:-json}" "${4:-false}"
            ;;
        "analyze_health")
            analyze_system_health "${2:-standard}"
            ;;
        "inventory")
            manage_device_inventory "${2:-list}" "${3:-default}"
            ;;
        "compliance")
            generate_compliance_report "${2:-nist}"
            ;;
        "monitor")
            monitor_system_continuously "${2:-600}" "${3:-warning}"
            ;;
        "deploy_fleet")
            deploy_to_fleet "${2:-install}" "$3" "${4:-standard}"
            ;;
        "health_check")
            perform_system_health_check
            ;;
        "help"|*)
            echo "Roundfleet Enterprise System Information Management System"
            echo ""
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  collect [policy] [format] [sensitive]    - Collect system information (comprehensive|security_focused|hardware_inventory|software_audit|network_assessment|compliance_report) [json|text] [true|false]"
            echo "  analyze_health [type]                    - Analyze system health (standard|detailed|continuous)"
            echo "  inventory <action> [group]               - Manage device inventory (register|update|list|remove) [group_name]"
            echo "  compliance [framework]                   - Generate compliance report (nist|hipaa|sox|iso27001)"
            echo "  monitor [interval] [threshold]           - Continuous monitoring (interval in seconds) (healthy|warning|critical)"
            echo "  deploy_fleet <action> <fleet_file> [policy] - Deploy to fleet (install|update|remove) [comprehensive|security_focused|compliance_audit]"
            echo "  health_check                             - Perform system health check"
            echo ""
            echo "Examples:"
            echo "  $0 collect comprehensive json false"
            echo "  $0 analyze_health detailed"
            echo "  $0 inventory register production"
            echo "  $0 compliance nist"
            echo "  $0 monitor 300 warning"
            echo "  $0 health_check"
            ;;
    esac
}

# Execute main function
main "$@"

System Information Data Types

The enterprise system supports comprehensive data type collection:

CategoryData TypesUse Case
Hardware OverviewSPHardwareDataType, SPMemoryDataType, SPStorageDataTypeAsset inventory and capacity planning
Software InventorySPSoftwareDataType, SPApplicationsDataType, SPExtensionsDataTypeLicense management and security auditing
Network ConfigurationSPNetworkDataType, SPBluetoothDataType, SPWWANDataTypeNetwork security and connectivity analysis
Security ConfigurationSPFirewallDataType, SPManagedClientDataType, SPConfigurationProfileDataTypeCompliance and security posture assessment
PeripheralsSPUSBDataType, SPThunderboltDataType, SPAudioDataType, SPDisplaysDataTypePeripheral management and security validation

Enterprise Collection Policies

Comprehensive Collection

# Collect all available system information
./sysinfo_manager.sh collect comprehensive json false

# Include sensitive information for detailed analysis
./sysinfo_manager.sh collect comprehensive json true

Security-Focused Collection

# Collect security-relevant information only
./sysinfo_manager.sh collect security_focused json false

# Generate security compliance report
./sysinfo_manager.sh compliance nist

Hardware Inventory

# Collect hardware inventory data
./sysinfo_manager.sh collect hardware_inventory json false

# Register device in enterprise inventory
./sysinfo_manager.sh inventory register production

System Health Monitoring

Health Analysis

# Perform standard health analysis
./sysinfo_manager.sh analyze_health standard

# Detailed health analysis with comprehensive metrics
./sysinfo_manager.sh analyze_health detailed

Continuous Monitoring

# Monitor system health every 10 minutes
./sysinfo_manager.sh monitor 600 warning

# Monitor system health every 5 minutes with critical threshold
./sysinfo_manager.sh monitor 300 critical

Enterprise Device Inventory

Inventory Management

# Register device in production inventory
./sysinfo_manager.sh inventory register production

# Update device information
./sysinfo_manager.sh inventory update production

# List all devices in inventory
./sysinfo_manager.sh inventory list production

# Remove device from inventory
./sysinfo_manager.sh inventory remove production

Compliance and Security Reporting

NIST Cybersecurity Framework

# Generate NIST compliance report
./sysinfo_manager.sh compliance nist

HIPAA Security Rule

# Generate HIPAA compliance report
./sysinfo_manager.sh compliance hipaa

Fleet Deployment Examples

Deploy to Development Fleet

Create a fleet file dev_fleet.txt:

dev-mac-01.company.com
dev-mac-02.company.com
dev-mac-03.company.com
# Deploy comprehensive system monitoring
./sysinfo_manager.sh deploy_fleet install dev_fleet.txt comprehensive

Deploy Security Monitoring

# Deploy security-focused monitoring to production fleet
./sysinfo_manager.sh deploy_fleet install prod_fleet.txt security_focused

Advanced Enterprise Features

Automated Data Collection

The system provides automated data collection capabilities:

  • Scheduled collection with customizable intervals
  • Policy-driven data gathering based on organizational requirements
  • Intelligent filtering to reduce data volume while maintaining completeness
  • Secure transmission of collected data to central repositories

System Health Analytics

Advanced health monitoring includes:

  • Performance metrics analysis and trending
  • Resource utilization monitoring and alerting
  • Security posture assessment and recommendations
  • Predictive maintenance based on system health indicators

Enterprise Integration

Integration capabilities include:

  • LDAP/Active Directory integration for user and device management
  • SIEM integration for security event correlation
  • Asset management system integration
  • Compliance framework alignment and reporting

Important Security Considerations

  • Data sensitivity requires appropriate handling and encryption
  • Access controls must be implemented for sensitive system information
  • Audit logging should track all system information access and collection
  • Network security must protect data transmission between devices
  • Compliance requirements vary by industry and geographic location

Performance and Scalability

The enterprise system is designed for:

  • Large-scale deployment across thousands of devices
  • Efficient data collection with minimal system impact
  • Scalable storage for historical data and trend analysis
  • High availability with redundancy and failover capabilities
  • Performance optimization for various hardware configurations

This comprehensive system transforms basic system information retrieval into an enterprise-grade device management and monitoring platform with advanced analytics, compliance reporting, and fleet-wide management capabilities.

Storage Management on macOS

Monitor and optimize storage across your Roundfleet devices using advanced disk usage analysis, automated cleanup policies, and comprehensive storage management. This tutorial provides enterprise-grade tools for implementing organizational storage policies and fleet-wide storage optimization.

Understanding macOS Storage Management

macOS provides several command-line tools for storage management:

  • du - Directory usage analysis and space consumption
  • df - Disk free space and filesystem information
  • diskutil - Disk utility for advanced disk operations
  • tmutil - Time Machine utility for backup storage
  • Storage Management - GUI storage optimization interface

Basic Storage Operations

Check User Storage Usage

#!/bin/bash

# Check disk usage for all users
echo "=== User Storage Usage ==="
sudo du -hxd1 /Users

echo "Storage usage check completed"

Check Filesystem Usage

#!/bin/bash

# Check overall filesystem usage
echo "=== Filesystem Usage ==="
df -h

# Check specific filesystem
# df -h /dev/disk1s1

echo "Filesystem usage check completed"

Check Current Directory Usage

#!/bin/bash

# Check current directory usage
echo "=== Current Directory Usage ==="
du -sh *

echo "Directory usage check completed"

Enterprise Storage Management System

#!/bin/bash

# Roundfleet Enterprise Storage Management System
# Comprehensive storage monitoring, optimization, and policy management

# 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"

# Create directory structure
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
}

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

# Storage Categories for Enterprise Management
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"
)

# Storage Policies for Different Environments
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"
)

# Disk Space Thresholds for Different Alert Levels
declare -A ALERT_THRESHOLDS=(
    ["critical"]=5     # Less than 5GB free
    ["warning"]=10     # Less than 10GB free
    ["low"]=20         # Less than 20GB free
    ["optimal"]=50     # Less than 50GB free
)

# Comprehensive storage analysis
analyze_storage_comprehensive() {
    local analysis_level="$1"
    local output_file="$STORAGE_DIR/storage_analysis_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting comprehensive storage analysis: $analysis_level"
    
    # Get basic filesystem information
    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/%//')
    
    # Convert to bytes for calculations
    local available_gb=$(df -g / | awk 'NR==2 {print $4}')
    
    # Determine alert level
    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
    
    # Analyze user directories
    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)"
    
    # Remove trailing comma
    user_data="${user_data%,}"
    
    # Analyze large directories
    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
    
    # Analyze system caches and temporary files
    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}"
    
    # Create comprehensive report
    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 "\"Immediate cleanup required - critical storage level\",")
    $([ $alert_level == "warning" ] && echo "\"Storage cleanup recommended\",")
    $([ $cache_size -gt 5 ] && echo "\"Clear application caches ($cache_size GB)\",")
    $([ $trash_size -gt 1 ] && echo "\"Empty trash ($trash_size GB)\",")
    $([ $log_size -gt 2 ] && echo "\"Archive old log files ($log_size GB)\",")
    "\"Regular storage monitoring recommended\""
  ]
}
EOF
    
    log_action "Storage analysis completed. Report: $output_file"
    
    # Alert if critical
    if [[ "$alert_level" == "critical" ]]; then
        log_action "CRITICAL ALERT: Storage space critically low ($available_gb GB remaining)"
        # Send alert notification
        osascript -e "display notification \"Critical storage space: $available_gb GB remaining\" with title \"Roundfleet Storage Alert\""
    fi
    
    echo "$output_file"
}

# Advanced storage cleanup with policies
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 "Starting storage cleanup with policy: $cleanup_policy (dry_run: $dry_run)"
    
    local total_freed=0
    local operations=""
    
    case "$cleanup_policy" in
        "aggressive_cleanup")
            # Clear application caches
            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
            
            # Remove old logs (7 days)
            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
            
            # Empty trash
            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
            
            # Remove old downloads (30 days)
            if [[ "$dry_run" == "false" ]]; then
                local downloads_size_before=$(du -sg ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
                find ~/Downloads -type f -mtime +30 -delete 2>/dev/null
                local downloads_size_after=$(du -sg ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
                local downloads_freed=$((downloads_size_before - downloads_size_after))
                total_freed=$((total_freed + downloads_freed))
                operations="$operations{\"operation\":\"remove_old_downloads\",\"freed_gb\":$downloads_freed},"
            fi
            ;;
            
        "development_optimized")
            # Clear Xcode derived data
            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
            
            # Clear iOS Simulator data
            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
            ;;
            
        "media_optimized")
            # Find and report duplicate files
            if [[ "$dry_run" == "false" ]]; then
                log_action "Scanning for duplicate media files..."
                # This is a placeholder for duplicate detection logic
                operations="$operations{\"operation\":\"duplicate_scan\",\"freed_gb\":0},"
            fi
            
            # Optimize photo library (placeholder)
            log_action "Photo library optimization available through Photos app"
            operations="$operations{\"operation\":\"photo_optimization_recommended\",\"freed_gb\":0},"
            ;;
    esac
    
    # Remove trailing comma
    operations="${operations%,}"
    
    # Create cleanup report
    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 "Cleanup completed. Total space freed: ${total_freed}GB"
    else
        log_action "Dry run completed. Would free approximately: ${total_freed}GB"
    fi
    
    echo "$cleanup_report"
}

# Storage monitoring and alerting
monitor_storage_continuously() {
    local monitoring_interval="${1:-300}"  # 5 minutes default
    local alert_threshold="${2:-10}"       # 10GB default
    
    log_action "Starting continuous storage monitoring (interval: ${monitoring_interval}s, threshold: ${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 "STORAGE ALERT: Only ${available_gb}GB remaining (${usage_percent}% used)"
            
            # Send system notification
            osascript -e "display notification \"Low storage: ${available_gb}GB remaining\" with title \"Roundfleet Storage Monitor\""
            
            # Optionally trigger automatic cleanup
            if [[ $available_gb -lt 5 ]]; then
                log_action "Triggering emergency cleanup..."
                perform_storage_cleanup "aggressive_cleanup" "false"
            fi
        fi
        
        # Log current status
        log_action "Storage status: ${available_gb}GB available (${usage_percent}% used)"
        
        sleep "$monitoring_interval"
    done
}

# Enterprise storage reporting
generate_storage_report() {
    local report_type="$1"
    local report_file="$REPORTS_DIR/storage_enterprise_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Generating enterprise storage report: $report_type"
    
    # Collect comprehensive storage data
    local filesystem_data=$(df -h | grep -v "tmpfs\|devfs" | awk 'NR>1 {print "{\"filesystem\":\""$1"\",\"size\":\""$2"\",\"used\":\""$3"\",\"available\":\""$4"\",\"usage_percent\":\""$5"\"}"}' | tr '\n' ',' | sed 's/,$//')
    
    # Analyze user storage patterns
    local user_analysis=""
    local total_users=0
    local total_user_storage=0
    
    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_gb=$(du -sg "$user_dir" 2>/dev/null | awk '{print $1}' || echo "0")
            ((total_users++))
            total_user_storage=$((total_user_storage + user_size_gb))
            user_analysis="$user_analysis{\"user\":\"$user_name\",\"storage_gb\":$user_size_gb},"
        fi
    done <<< "$(find /Users -maxdepth 1 -type d)"
    
    user_analysis="${user_analysis%,}"
    local avg_user_storage=$((total_user_storage / total_users))
    
    # Application storage analysis
    local app_storage=""
    if [[ -d /Applications ]]; then
        while IFS= read -r app_info; do
            local size=$(echo "$app_info" | awk '{print $1}')
            local app_path=$(echo "$app_info" | awk '{$1=""; print substr($0,2)}')
            local app_name=$(basename "$app_path")
            [[ $size -gt 0 ]] && app_storage="$app_storage{\"application\":\"$app_name\",\"size_gb\":$size},"
        done <<< "$(du -sg /Applications/*.app 2>/dev/null | sort -nr | head -20)"
        app_storage="${app_storage%,}"
    fi
    
    # System health indicators
    local health_indicators=""
    local available_gb=$(df -g / | awk 'NR==2 {print $4}')
    local health_status="healthy"
    
    if [[ $available_gb -lt 5 ]]; then
        health_status="critical"
    elif [[ $available_gb -lt 10 ]]; then
        health_status="warning"
    elif [[ $available_gb -lt 20 ]]; then
        health_status="low"
    fi
    
    health_indicators="{\"status\":\"$health_status\",\"available_gb\":$available_gb,\"recommendation\":\"$([ "$health_status" != "healthy" ] && echo "Cleanup required" || echo "Storage optimal")\"}"
    
    # Create comprehensive enterprise report
    cat > "$report_file" << EOF
{
  "enterprise_storage_report": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "report_type": "$report_type",
    "device_info": {
      "hostname": "$(hostname)",
      "mac_address": "$(ifconfig en0 | grep ether | awk '{print $2}')",
      "serial_number": "$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $4}')"
    }
  },
  "storage_overview": {
    "filesystems": [$filesystem_data],
    "health_status": $health_indicators
  },
  "user_analysis": {
    "total_users": $total_users,
    "total_user_storage_gb": $total_user_storage,
    "average_user_storage_gb": $avg_user_storage,
    "user_breakdown": [$user_analysis]
  },
  "application_analysis": {
    "top_applications": [$app_storage]
  },
  "compliance_info": {
    "data_retention_policy": "enterprise_standard",
    "encryption_status": "$(fdesetup status | grep -q "On" && echo "enabled" || echo "disabled")",
    "backup_status": "$(tmutil status | grep -q "Running" && echo "active" || echo "inactive")"
  },
  "recommendations": [
    $([ "$health_status" == "critical" ] && echo "\"Immediate storage cleanup required\",")
    $([ $total_user_storage -gt 100 ] && echo "\"Consider user storage policies\",")
    $([ $available_gb -lt 20 ] && echo "\"Implement automated cleanup policies\",")
    "\"Regular storage monitoring recommended\""
  ]
}
EOF
    
    log_action "storage report generated: $report_file"
    echo "$report_file"
}

# Storage policy enforcement
enforce_storage_policies() {
    local policy_level="$1"
    
    log_action "Enforcing storage policies: $policy_level"
    
    case "$policy_level" in
        "enterprise_standard")
            # Standard enterprise storage policies
            log_action "Applying enterprise standard storage policies"
            
            # Set up automatic cleanup schedules
            cat > /tmp/roundfleet_storage_cleanup.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.roundfleet.storage.cleanup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>$(realpath "$0") perform_storage_cleanup conservative_cleanup false</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>2</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/var/log/roundfleet_storage_cleanup.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/roundfleet_storage_cleanup.log</string>
</dict>
</plist>
EOF
            sudo mv /tmp/roundfleet_storage_cleanup.plist /Library/LaunchDaemons/
            sudo launchctl load /Library/LaunchDaemons/com.roundfleet.storage.cleanup.plist
            ;;
            
        "development_team")
            # Policies optimized for development teams
            log_action "Applying development team storage policies"
            perform_storage_cleanup "development_optimized" "false"
            ;;
            
        "media_production")
            # Policies for media production environments
            log_action "Applying media production storage policies"
            perform_storage_cleanup "media_optimized" "false"
            ;;
    esac
    
    log_action "Storage policies enforcement completed: $policy_level"
}

# Storage optimization recommendations
generate_optimization_recommendations() {
    local analysis_file="$1"
    local recommendations_file="$REPORTS_DIR/storage_recommendations_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Generating storage optimization recommendations"
    
    # Analyze current storage state
    local available_gb=$(df -g / | awk 'NR==2 {print $4}')
    local usage_percent=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
    
    # Check for common storage issues
    local cache_size=$(du -sg ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
    local downloads_size=$(du -sg ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
    local trash_size=$(du -sg ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
    local log_size=$(sudo du -sg /var/log 2>/dev/null | awk '{print $1}' || echo "0")
    
    # Generate recommendations based on analysis
    local recommendations=""
    local priority="medium"
    
    if [[ $available_gb -lt 10 ]]; then
        priority="high"
        recommendations="$recommendations\"Immediate cleanup required - storage critically low\","
    fi
    
    if [[ $cache_size -gt 5 ]]; then
        recommendations="$recommendations\"Clear application caches (${cache_size}GB potential savings)\","
    fi
    
    if [[ $downloads_size -gt 10 ]]; then
        recommendations="$recommendations\"Review Downloads folder (${downloads_size}GB)\","
    fi
    
    if [[ $trash_size -gt 1 ]]; then
        recommendations="$recommendations\"Empty Trash (${trash_size}GB immediate savings)\","
    fi
    
    if [[ $log_size -gt 5 ]]; then
        recommendations="$recommendations\"Archive old log files (${log_size}GB)\","
    fi
    
    if [[ $usage_percent -gt 80 ]]; then
        recommendations="$recommendations\"Consider external storage or cloud archiving\","
    fi
    
    # Remove trailing comma
    recommendations="${recommendations%,}"
    
    cat > "$recommendations_file" << EOF
{
  "optimization_recommendations": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "priority_level": "$priority",
    "current_status": {
      "available_gb": $available_gb,
      "usage_percent": $usage_percent,
      "storage_health": "$([ $available_gb -gt 20 ] && echo "healthy" || echo "attention_required")"
    },
    "immediate_actions": [$recommendations],
    "long_term_strategies": [
      "Implement automated cleanup policies",
      "Set up storage monitoring alerts",
      "Consider cloud storage integration",
      "Regular storage health assessments"
    ],
    "potential_savings": {
      "caches_gb": $cache_size,
      "downloads_gb": $downloads_size,
      "trash_gb": $trash_size,
      "logs_gb": $log_size,
      "total_potential_gb": $((cache_size + downloads_size + trash_size + log_size))
    }
  }
}
EOF
    
    log_action "Storage optimization recommendations generated: $recommendations_file"
    echo "$recommendations_file"
}

# Fleet storage management
deploy_storage_management_to_fleet() {
    local fleet_file="$1"
    local management_policy="$2"
    
    if [[ ! -f "$fleet_file" ]]; then
        log_action "ERROR: Fleet file not found: $fleet_file"
        return 1
    fi
    
    log_action "Deploying storage management to fleet with policy: $management_policy"
    
    while IFS= read -r host; do
        [[ -z "$host" || "$host" =~ ^#.*$ ]] && continue
        
        echo "Deploying storage management to: $host"
        
        # Deploy storage management script to remote host
        ssh "$host" "bash -s" << EOF
#!/bin/bash
# Remote deployment of storage management: $management_policy

# Create Roundfleet directories
mkdir -p /etc/roundfleet/{storage_management,reports,compliance,audit,storage_policies,cleanup_logs}

# Set up basic storage monitoring
echo "Setting up storage monitoring for policy: $management_policy"

case "$management_policy" in
    "enterprise_standard")
        # Set up enterprise-grade monitoring
        echo "Configuring enterprise storage monitoring"
        ;;
    "development_optimized")
        # Set up development-focused monitoring
        echo "Configuring development storage optimization"
        ;;
    "media_production")
        # Set up media production monitoring
        echo "Configuring media production storage management"
        ;;
esac

echo "Storage management deployment completed on \$(hostname)"
EOF
        
        if [[ $? -eq 0 ]]; then
            log_action "Successfully deployed storage management to: $host"
        else
            log_action "Failed to deploy storage management to: $host"
        fi
        
    done < "$fleet_file"
    
    log_action "Fleet storage management deployment completed"
}

# Health check and system validation
perform_storage_health_check() {
    echo "=== Roundfleet Storage Management Health Check ==="
    
    # Check disk space
    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 -gt 20 ]]; then
        echo "✓ Disk space: Healthy (${available_gb}GB available)"
    elif [[ $available_gb -gt 10 ]]; then
        echo "⚠️  Disk space: Low (${available_gb}GB available)"
    else
        echo "🔴 Disk space: Critical (${available_gb}GB available)"
    fi
    
    # Check for large cache files
    local cache_size=$(du -sg ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
    if [[ $cache_size -gt 5 ]]; then
        echo "⚠️  Large caches detected: ${cache_size}GB"
    else
        echo "✓ Cache size: Normal (${cache_size}GB)"
    fi
    
    # Check trash
    local trash_size=$(du -sg ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
    if [[ $trash_size -gt 1 ]]; then
        echo "○ Trash contains: ${trash_size}GB (can be emptied)"
    else
        echo "✓ Trash: Empty"
    fi
    
    # Check FileVault encryption
    if fdesetup status | grep -q "On"; then
        echo "✓ FileVault: Enabled"
    else
        echo "○ FileVault: Disabled"
    fi
    
    # Check Time Machine
    if tmutil status | grep -q "Running"; then
        echo "✓ Time Machine: Active"
    else
        echo "○ Time Machine: Inactive"
    fi
    
    # Check APFS snapshots
    local snapshots=$(tmutil listlocalsnapshots / | wc -l)
    if [[ $snapshots -gt 10 ]]; then
        echo "⚠️  Many local snapshots: $snapshots (consider cleanup)"
    else
        echo "✓ Local snapshots: $snapshots"
    fi
}

# Main execution function
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}"
            ;;
        "report")
            generate_storage_report "${2:-comprehensive}"
            ;;
        "enforce_policies")
            enforce_storage_policies "${2:-enterprise_standard}"
            ;;
        "recommendations")
            generate_optimization_recommendations "$2"
            ;;
        "deploy_fleet")
            deploy_storage_management_to_fleet "$2" "${3:-enterprise_standard}"
            ;;
        "health_check")
            perform_storage_health_check
            ;;
        "help"|*)
            echo "Roundfleet Enterprise Storage Management System"
            echo ""
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  analyze [level]                     - Analyze storage (basic|standard|detailed|full)"
            echo "  cleanup <policy> [dry_run]          - Perform cleanup (aggressive_cleanup|conservative_cleanup|development_optimized|media_optimized) [true|false]"
            echo "  monitor [interval] [threshold]      - Continuous monitoring (interval in seconds, threshold in GB)"
            echo "  report [type]                       - Generate enterprise report (comprehensive|summary|compliance)"
            echo "  enforce_policies [policy]           - Enforce storage policies (enterprise_standard|development_team|media_production)"
            echo "  recommendations [analysis_file]     - Generate optimization recommendations"
            echo "  deploy_fleet <fleet_file> [policy]  - Deploy to fleet"
            echo "  health_check                        - Perform system health check"
            echo ""
            echo "Examples:"
            echo "  $0 analyze detailed"
            echo "  $0 cleanup aggressive_cleanup false"
            echo "  $0 monitor 600 15"
            echo "  $0 report comprehensive"
            echo "  $0 health_check"
            ;;
    esac
}

# Execute main function
main "$@"

Storage Analysis and Monitoring

The enterprise system provides comprehensive storage analysis:

Analysis LevelScopeDetailsUse Case
BasicOverall disk usageQuick space checkDaily monitoring
StandardUser and system breakdownDetailed usage patternsWeekly reviews
DetailedLarge directories analysisComprehensive inventoryMonthly audits
FullComplete system analysisEnterprise reportingQuarterly assessments

Storage Cleanup Policies

Aggressive Cleanup Policy

# Perform aggressive cleanup to reclaim maximum space
./storage_manager.sh cleanup aggressive_cleanup false

# Dry run to see what would be cleaned
./storage_manager.sh cleanup aggressive_cleanup true

Development-Optimized Cleanup

# Clean development-specific cache and build data
./storage_manager.sh cleanup development_optimized false

Media Production Cleanup

# Optimize storage for media production workflows
./storage_manager.sh cleanup media_optimized false

Enterprise Storage Monitoring

Continuous Monitoring

# Monitor storage every 5 minutes with 10GB threshold
./storage_manager.sh monitor 300 10

# Monitor storage every hour with 20GB threshold
./storage_manager.sh monitor 3600 20

Automated Alerts

The system provides intelligent alerting:

  • Critical Alert - Less than 5GB remaining
  • Warning Alert - Less than 10GB remaining
  • Low Storage - Less than 20GB remaining
  • Optimal - More than 50GB remaining

Storage Policy Management

Enterprise Standard Policy

# Apply enterprise standard storage policies
./storage_manager.sh enforce_policies enterprise_standard

Development Team Policy

# Apply development-focused storage policies
./storage_manager.sh enforce_policies development_team

Media Production Policy

# Apply media production storage policies
./storage_manager.sh enforce_policies media_production

Fleet Deployment Examples

Deploy to Development Fleet

Create a fleet file dev_fleet.txt:

dev-mac-01.company.com
dev-mac-02.company.com
dev-mac-03.company.com
# Deploy development-optimized storage management
./storage_manager.sh deploy_fleet dev_fleet.txt development_team

Deploy to Production Fleet

# Deploy enterprise standard storage management
./storage_manager.sh deploy_fleet prod_fleet.txt enterprise_standard

Advanced Storage Features

Storage Analytics and Reporting

The system provides comprehensive enterprise reporting:

  • Usage patterns across users and applications
  • Cost analysis for storage optimization
  • Compliance reporting for regulatory requirements
  • Trend analysis for capacity planning

Automated Optimization

Advanced optimization features include:

  • Duplicate file detection and removal
  • Cache management with intelligent cleanup
  • Log rotation and archival
  • Backup optimization and verification

Security and Compliance

Enterprise security features:

  • Encrypted storage verification and monitoring
  • Audit trails for all storage operations
  • Data retention policy enforcement
  • Secure deletion for sensitive data

Important Storage Considerations

  • FileVault encryption should be enabled for enterprise security
  • Time Machine backups require adequate external storage
  • APFS snapshots consume storage and should be monitored
  • Application caches can grow large and require regular cleanup
  • User education helps maintain optimal storage usage

Compliance and Governance

The enterprise system supports various compliance frameworks:

  • GDPR Compliance - Data retention and secure deletion
  • HIPAA Requirements - Healthcare data storage security
  • SOX Compliance - Financial data storage controls
  • ISO 27001 - Information security storage management

Performance Optimization

Storage performance optimization includes:

  • SSD health monitoring and optimization
  • APFS optimization for modern file systems
  • Cache management for improved performance
  • Defragmentation recommendations when needed

Testing and Validation

Before enterprise deployment:

  1. Test cleanup policies on non-production systems
  2. Verify monitoring thresholds are appropriate for your environment
  3. Confirm alert mechanisms work correctly
  4. Test recovery procedures for critical storage situations
  5. Validate compliance reporting meets organizational requirements

This comprehensive system transforms basic disk usage commands into an enterprise-grade storage management platform with advanced monitoring, automated optimization, and fleet-wide management capabilities.

Configure Stage Manager on macOS Devices

Stage Manager is a powerful window management feature introduced in macOS Ventura that helps users organize and focus on their work by grouping windows and hiding inactive applications. This tutorial shows you how to manage Stage Manager settings across your Mac fleet using shell scripts.

What is Stage Manager?

Stage Manager is a window management system that:

  • Organizes windows into focused groups on the desktop
  • Reduces visual clutter by hiding inactive applications
  • Improves productivity by allowing users to switch between different work contexts
  • Supports external displays with independent Stage Manager controls
  • Integrates with Mission Control for enhanced window management

Prerequisites and Compatibility

System Requirements

  • macOS 13.0 (Ventura) or later - Stage Manager is not available on earlier versions
  • Supported devices: Mac computers with Apple Silicon (M1, M2, M3, M4) or Intel processors
  • Administrative privileges for script execution

Hardware Compatibility

Stage Manager works best on:

  • MacBook Pro and MacBook Air (2018 or later)
  • iMac (2019 or later)
  • Mac Studio (all models)
  • Mac Pro (2019 or later)
  • Mac Mini (2018 or later)

Basic Stage Manager Management

Enable Stage Manager

#!/bin/bash

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

echo "Roundfleet Stage Manager Enablement"
echo "Current user: $CurrentUser"
echo "Current user UID: $CurrentUserUID"

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

echo "✅ Stage Manager has been enabled for user $CurrentUser"
echo "Changes will take effect after the next login or window manager restart"

Disable Stage Manager

#!/bin/bash

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

echo "Roundfleet Stage Manager Disablement"
echo "Current user: $CurrentUser"
echo "Current user UID: $CurrentUserUID"

# Disable Stage Manager globally
launchctl asuser $CurrentUserUID sudo -iu "$CurrentUser" defaults write com.apple.WindowManager GloballyEnabled -bool false

echo "❌ Stage Manager has been disabled for user $CurrentUser"
echo "Changes will take effect after the next login or window manager restart"

Advanced Stage Manager Configuration

Comprehensive Stage Manager Management Script

#!/bin/bash

# Advanced Stage Manager management for Mac fleet
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"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Function to check macOS version compatibility
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 is compatible with Stage Manager"
        return 0
    else
        echo "❌ macOS $MACOS_VERSION is not compatible with Stage Manager (requires 13.0+)"
        return 1
    fi
}

# Function to get current Stage Manager status
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 "enabled" ;;
        0) echo "disabled" ;;
        *) echo "undefined" ;;
    esac
}

# Function to enable 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 enabled on $DEVICE_NAME for user $CURRENT_USER"
}

# Function to disable 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 disabled on $DEVICE_NAME for user $CURRENT_USER"
}

# Function to configure recent apps visibility
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 "Recent apps visibility enabled"
        echo "✅ Recent applications will be visible on the left side"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool true
        log_message "Recent apps visibility disabled"
        echo "❌ Recent applications will be hidden"
    fi
}

# Function to configure window grouping behavior
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 "Window grouping set to 'All at Once'"
            echo "✅ Window grouping: All at Once"
            ;;
        "one_at_time")
            launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
            log_message "Window grouping set to 'One at a Time'"
            echo "✅ Window grouping: One at a Time"
            ;;
        *)
            echo "❌ Invalid grouping mode. Use 'all_at_once' or 'one_at_time'"
            return 1
            ;;
    esac
}

# Function to restart Window Manager
restart_window_manager() {
    launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" killall WindowManager 2>/dev/null
    sleep 2
    log_message "Window Manager restarted for user $CURRENT_USER"
}

# Function to validate Stage Manager configuration
validate_configuration() {
    local expected_state="$1"
    local current_state=$(get_stage_manager_status)
    
    if [ "$current_state" = "$expected_state" ]; then
        echo "✅ Configuration validation successful: Stage Manager is $expected_state"
        return 0
    else
        echo "❌ Configuration validation failed: Expected $expected_state, got $current_state"
        return 1
    fi
}

# Main execution
echo "Roundfleet Stage Manager Configuration"
echo "==================================="
echo "Device: $DEVICE_NAME"
echo "User: $CURRENT_USER"
echo "macOS Version: $MACOS_VERSION"
echo ""

log_message "Starting Stage Manager configuration on $DEVICE_NAME"

# Check compatibility
if ! check_compatibility; then
    log_message "Stage Manager configuration aborted due to compatibility issues"
    exit 1
fi

# Display current status
echo "Current Stage Manager status: $(get_stage_manager_status)"
echo ""

# Configuration options (uncomment as needed)
# enable_stage_manager
# disable_stage_manager
# configure_recent_apps "true"
# configure_window_grouping "all_at_once"
# restart_window_manager

log_message "Stage Manager configuration completed"

Interactive Stage Manager Configuration

#!/bin/bash

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

# Function to get current Stage Manager status
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 "enabled" ;;
        0) echo "disabled" ;;
        *) echo "not configured" ;;
    esac
}

# Function to get recent apps setting
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 "hidden" ;;
        0) echo "visible" ;;
        *) echo "not configured" ;;
    esac
}

# Function to get window grouping setting
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 "one at a time" ;;
        0) echo "all at once" ;;
        *) echo "not configured" ;;
    esac
}

# Function to display current configuration
display_current_config() {
    echo "Current Stage Manager Configuration:"
    echo "==================================="
    echo "Stage Manager: $(get_stage_manager_status)"
    echo "Recent Apps: $(get_recent_apps_status)"
    echo "Window Grouping: $(get_window_grouping_status)"
    echo ""
}

# Main interactive menu
echo "Roundfleet Stage Manager Interactive Configuration"
echo "==============================================="
echo "Device: $(scutil --get ComputerName)"
echo "User: $CURRENT_USER"
echo "macOS Version: $MACOS_VERSION"
echo ""

# Check compatibility
major_version=$(echo "$MACOS_VERSION" | cut -d. -f1)
if [ "$major_version" -lt 13 ]; then
    echo "❌ Stage Manager requires macOS 13.0 or later"
    echo "Current version: $MACOS_VERSION"
    exit 1
fi

display_current_config

echo "Configuration Options:"
echo "1. Enable Stage Manager"
echo "2. Disable Stage Manager"
echo "3. Show recent applications"
echo "4. Hide recent applications"
echo "5. Set window grouping to 'All at Once'"
echo "6. Set window grouping to 'One at a Time'"
echo "7. Apply recommended settings"
echo "8. Reset to defaults"
echo "9. Display current configuration"
echo "0. Exit"
echo ""

read -p "Enter your choice (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 enabled"
        ;;
    2)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager GloballyEnabled -bool false
        echo "❌ Stage Manager disabled"
        ;;
    3)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool false
        echo "✅ Recent applications will be visible"
        ;;
    4)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AutoHide -bool true
        echo "❌ Recent applications will be hidden"
        ;;
    5)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool false
        echo "✅ Window grouping set to 'All at Once'"
        ;;
    6)
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
        echo "✅ Window grouping set to 'One at a Time'"
        ;;
    7)
        # Apply recommended enterprise settings
        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 "✅ Applied recommended enterprise settings"
        ;;
    8)
        # Reset to system defaults
        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 "✅ Reset to system defaults"
        ;;
    9)
        display_current_config
        ;;
    0)
        echo "Exiting..."
        exit 0
        ;;
    *)
        echo "Invalid choice. Please try again."
        ;;
esac

echo ""
echo "Configuration updated. Changes may require logout/login to take full effect."
echo "You can verify the changes in System Settings > Desktop & Dock > Stage Manager."

Enterprise Deployment Scripts

Bulk Stage Manager Configuration

#!/bin/bash

# Enterprise Stage Manager deployment script
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"

# Configuration settings
STAGE_MANAGER_ENABLED=true
RECENT_APPS_VISIBLE=true
WINDOW_GROUPING_MODE="all_at_once"  # Options: "all_at_once" or "one_at_time"
RESTART_WINDOW_MANAGER=true

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Function to check macOS compatibility
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 is compatible with Stage Manager"
        return 0
    else
        log_message "macOS $macos_version is not compatible with Stage Manager"
        return 1
    fi
}

# Function to get device information
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 "Device: $device_name"
    echo "Serial: $device_serial"
    echo "Hardware: $hardware_model"
    echo "macOS: $macos_version"
    echo "User: $current_user"
}

# Function to deploy Stage Manager configuration
deploy_stage_manager_config() {
    local current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local current_user_uid=$(id -u "$current_user")
    
    # Enable/disable 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 enabled for user $current_user"
        echo "✅ Stage Manager enabled"
    else
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager GloballyEnabled -bool false
        log_message "Stage Manager disabled for user $current_user"
        echo "❌ Stage Manager disabled"
    fi
    
    # Configure recent apps visibility
    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 "Recent apps visibility enabled"
        echo "✅ Recent apps will be visible"
    else
        launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AutoHide -bool true
        log_message "Recent apps visibility disabled"
        echo "❌ Recent apps will be hidden"
    fi
    
    # Configure window grouping behavior
    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 "Window grouping set to 'All at Once'"
            echo "✅ Window grouping: All at Once"
            ;;
        "one_at_time")
            launchctl asuser $current_user_uid sudo -iu "$current_user" defaults write com.apple.WindowManager AppWindowGroupingBehavior -bool true
            log_message "Window grouping set to 'One at a Time'"
            echo "✅ Window grouping: One at a Time"
            ;;
    esac
    
    # Restart Window Manager if requested
    if [ "$RESTART_WINDOW_MANAGER" = true ]; then
        launchctl asuser $current_user_uid sudo -iu "$current_user" killall WindowManager 2>/dev/null
        sleep 2
        log_message "Window Manager restarted"
        echo "🔄 Window Manager restarted"
    fi
}

# Function to validate deployment
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
    
    # Validate Stage Manager status
    if [ "$STAGE_MANAGER_ENABLED" = true ] && [ "$stage_manager_status" = "1" ]; then
        echo "✅ Stage Manager validation: PASSED"
    elif [ "$STAGE_MANAGER_ENABLED" = false ] && [ "$stage_manager_status" = "0" ]; then
        echo "✅ Stage Manager validation: PASSED"
    else
        echo "❌ Stage Manager validation: FAILED"
        validation_success=false
    fi
    
    # Validate recent apps setting
    if [ "$RECENT_APPS_VISIBLE" = true ] && [ "$recent_apps_status" = "0" ]; then
        echo "✅ Recent apps validation: PASSED"
    elif [ "$RECENT_APPS_VISIBLE" = false ] && [ "$recent_apps_status" = "1" ]; then
        echo "✅ Recent apps validation: PASSED"
    else
        echo "❌ Recent apps validation: FAILED"
        validation_success=false
    fi
    
    if [ "$validation_success" = true ]; then
        log_message "Deployment validation successful"
        return 0
    else
        log_message "Deployment validation failed"
        return 1
    fi
}

# Main deployment process
echo "$COMPANY_NAME Stage Manager Deployment" > "$REPORT_FILE"
echo "========================================" >> "$REPORT_FILE"
echo "Date: $DEPLOYMENT_DATE" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

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

log_message "Starting Stage Manager deployment"
echo "Starting deployment..." >> "$REPORT_FILE"

# Check macOS compatibility
if ! check_macos_compatibility; then
    echo "Status: FAILED - Incompatible macOS version" >> "$REPORT_FILE"
    log_message "Deployment aborted due to macOS compatibility"
    exit 1
fi

# Deploy configuration
deploy_stage_manager_config

# Validate deployment
if validate_deployment; then
    echo "Status: SUCCESS" >> "$REPORT_FILE"
else
    echo "Status: FAILED" >> "$REPORT_FILE"
fi

log_message "Deployment completed"
echo "Deployment completed. Report saved to: $REPORT_FILE"
cat "$REPORT_FILE"

Stage Manager Monitoring and Reporting

#!/bin/bash

# Stage Manager monitoring and reporting script
CENTRAL_SERVER="your-roundfleet-server.com"
DEVICE_ID=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
REPORT_FILE="/tmp/stage_manager_report_${DEVICE_ID}.json"

# Function to create JSON report
create_json_report() {
    local device_name=$(scutil --get ComputerName)
    local device_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local device_user_uid=$(id -u "$device_user")
    local os_version=$(sw_vers -productVersion)
    local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local hardware_model=$(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)
    
    # Get Stage Manager settings
    local stage_manager_enabled=$(launchctl asuser $device_user_uid sudo -iu "$device_user" defaults read com.apple.WindowManager GloballyEnabled 2>/dev/null)
    local recent_apps_hidden=$(launchctl asuser $device_user_uid sudo -iu "$device_user" defaults read com.apple.WindowManager AutoHide 2>/dev/null)
    local window_grouping=$(launchctl asuser $device_user_uid sudo -iu "$device_user" defaults read com.apple.WindowManager AppWindowGroupingBehavior 2>/dev/null)
    
    # Check if Stage Manager is supported
    local major_version=$(echo "$os_version" | cut -d. -f1)
    local stage_manager_supported=$([ "$major_version" -ge 13 ] && echo "true" || echo "false")
    
    cat > "$REPORT_FILE" << EOF
{
  "device_info": {
    "device_id": "$DEVICE_ID",
    "device_name": "$device_name",
    "hardware_model": "$hardware_model",
    "user": "$device_user",
    "os_version": "$os_version",
    "timestamp": "$timestamp"
  },
  "stage_manager": {
    "supported": $stage_manager_supported,
    "enabled": $([ "$stage_manager_enabled" = "1" ] && echo "true" || echo "false"),
    "configured": $([ -n "$stage_manager_enabled" ] && echo "true" || echo "false"),
    "recent_apps_hidden": $([ "$recent_apps_hidden" = "1" ] && echo "true" || echo "false"),
    "window_grouping_mode": "$([ "$window_grouping" = "1" ] && echo "one_at_time" || echo "all_at_once")"
  },
  "window_manager": {
    "process_running": $(pgrep -x "WindowManager" > /dev/null && echo "true" || echo "false"),
    "last_restart": "$(ps -p $(pgrep -x "WindowManager") -o lstart= 2>/dev/null | xargs)"
  }
}
EOF
}

# Function to collect usage statistics
collect_usage_stats() {
    local device_user=$(ls -l /dev/console | awk '/ / { print $3 }')
    local device_user_uid=$(id -u "$device_user")
    
    # Check if Stage Manager is currently active
    local stage_manager_active=$(launchctl asuser $device_user_uid sudo -iu "$device_user" defaults read com.apple.WindowManager GloballyEnabled 2>/dev/null)
    
    if [ "$stage_manager_active" = "1" ]; then
        echo "Stage Manager is currently active"
        
        # Get window count (approximation)
        local window_count=$(launchctl asuser $device_user_uid sudo -iu "$device_user" osascript -e 'tell application "System Events" to count windows of every application process' 2>/dev/null)
        echo "Current window count: $window_count"
        
        # Check if external displays are connected
        local display_count=$(system_profiler SPDisplaysDataType | grep -c "Display Type:")
        echo "Connected displays: $display_count"
    else
        echo "Stage Manager is not active"
    fi
}

# Main execution
echo "Roundfleet Stage Manager Monitoring"
echo "================================="
echo "Device ID: $DEVICE_ID"

# Create monitoring report
create_json_report

# Collect usage statistics
collect_usage_stats

echo "Report generated: $REPORT_FILE"
echo "Stage Manager monitoring completed"

# Display report summary
echo ""
echo "Report Summary:"
echo "==============="
cat "$REPORT_FILE" | grep -E '"supported|enabled|configured"' | sed 's/[",]//g' | sed 's/^[ ]*//'

# Optional: Send to central server
# curl -X POST -H "Content-Type: application/json" -d @"$REPORT_FILE" "https://$CENTRAL_SERVER/api/stage-manager-reports"

Best Practices for Stage Manager Management

1. User Training and Adoption

  • Provide comprehensive training on Stage Manager features
  • Create user guides and documentation
  • Demonstrate productivity benefits
  • Offer personalized configurations based on user roles

2. Configuration Standards

  • Define organizational standards for Stage Manager settings
  • Create different profiles for different user types
  • Document approved configurations
  • Implement change management processes

3. Performance Considerations

  • Monitor system performance impact
  • Consider hardware capabilities when enabling Stage Manager
  • Test configurations on different device types
  • Provide rollback options

4. Integration with Other Tools

  • Coordinate with existing window management tools
  • Consider impact on screen sharing and remote access
  • Test with business applications
  • Ensure compatibility with accessibility features

Troubleshooting Common Issues

Issue: Stage Manager Not Available

# Check macOS version
macos_version=$(sw_vers -productVersion)
echo "macOS version: $macos_version"

# Check if running on compatible hardware
hardware_model=$(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)
echo "Hardware model: $hardware_model"

# Verify system requirements
if [[ "$macos_version" < "13.0" ]]; then
    echo "❌ Stage Manager requires macOS 13.0 or later"
fi

Issue: Changes Not Taking Effect

# Restart Window Manager
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

# Verify process restart
if pgrep -x "WindowManager" > /dev/null; then
    echo "✅ Window Manager restarted successfully"
else
    echo "❌ Window Manager failed to restart"
fi

Issue: Permission Denied

# Check user permissions
current_user=$(ls -l /dev/console | awk '/ / { print $3 }')
echo "Current user: $current_user"

# Verify user context
id "$current_user"

# Check if user has necessary permissions
if groups "$current_user" | grep -q "admin"; then
    echo "✅ User has admin privileges"
else
    echo "❌ User does not have admin privileges"
fi

Issue: Settings Not Persisting

# Check preferences file
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 "✅ Preferences file exists"
    ls -la "$plist_file"
else
    echo "❌ Preferences file not found"
fi

# Force preferences sync
defaults synchronize

Stage Manager Feature Deep Dive

Understanding Stage Manager Components

Stage Manager consists of several key components:

  1. Window Groups: Collections of related windows that appear together
  2. Stage: The main working area where active window groups are displayed
  3. Recent Applications: Sidebar showing recently used applications
  4. External Display Support: Independent Stage Manager operation on external displays

Advanced Configuration Options

#!/bin/bash

# Advanced Stage Manager configuration options
CURRENT_USER=$(ls -l /dev/console | awk '/ / { print $3 }')
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configure Stage Manager for external displays
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 "✅ External display Stage Manager enabled"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager StandardStageStripShowsFullDesktop -bool false
        echo "❌ External display Stage Manager disabled"
    fi
}

# Configure Stage Manager animation speed
configure_animation_speed() {
    local speed="$1"  # Values: 0.1 to 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 "✅ Animation speed set to $speed"
    else
        echo "❌ Invalid animation speed. Use values between 0.1 and 1.0"
    fi
}

# Configure Stage Manager hotkeys
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 "✅ Stage Manager hotkeys enabled"
    else
        launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" defaults write com.apple.WindowManager EnableHotKeys -bool false
        echo "❌ Stage Manager hotkeys disabled"
    fi
}

# Example usage
# configure_external_display_stage_manager "true"
# configure_animation_speed "0.5"
# configure_hotkeys "true"

Conclusion

Stage Manager is a powerful productivity feature that can significantly improve window management workflows when properly configured. This comprehensive guide provides:

  • Basic enable/disable functionality for quick deployment
  • Advanced configuration options for customized user experiences
  • Enterprise deployment scripts for large-scale management
  • Monitoring and reporting tools for ongoing management
  • Troubleshooting guides for common issues

Regular implementation of Stage Manager management practices will help ensure your Mac fleet provides an optimal user experience while maintaining organizational standards and productivity goals.

For maximum effectiveness, consider integrating Stage Manager configuration with your existing Mac fleet management tools and user training programs.

Managing Spotlight Indexing on macOS Devices

Spotlight is macOS's powerful system-wide search feature that helps users quickly locate files, documents, applications, emails, and more across their system. While Spotlight provides excellent search capabilities, its continuous background indexing can sometimes impact system performance, particularly on older hardware or resource-constrained environments. This comprehensive guide provides methods to manage Spotlight indexing effectively.

Understanding Spotlight and Its Impact

Spotlight uses a sophisticated indexing system that continuously scans and catalogs content on your Mac to provide instant search results. This indexing process involves:

  • File content analysis: Reading and indexing text within documents
  • Metadata extraction: Cataloging file properties, creation dates, and tags
  • Application indexing: Tracking installed applications and their data
  • Email and message indexing: Indexing Mail, Messages, and other communication apps
  • Real-time updates: Monitoring file system changes to keep the index current

Why Manage Spotlight Indexing?

There are several scenarios where managing Spotlight indexing becomes necessary:

  • Performance optimization: Reducing CPU and disk usage on resource-limited systems
  • Privacy concerns: Preventing indexing of sensitive files and directories
  • Storage management: Saving disk space used by index files
  • Troubleshooting: Resolving search issues or corrupted indexes
  • Enterprise deployment: Standardizing search behavior across managed devices
  • Development environments: Preventing indexing of build directories and temporary files

Prerequisites

Before managing Spotlight indexing, ensure you have:

  • Administrative privileges on the Mac
  • Terminal or SSH access
  • Understanding of the impact on search functionality
  • Backup of important data (recommended)

Basic Spotlight Management Commands

Understanding mdutil

The mdutil command is the primary tool for managing Spotlight indexing:

# Check indexing status
mdutil -s /

# Enable indexing for a volume
mdutil -i on /

# Disable indexing for a volume
mdutil -i off /

# Erase and rebuild index
mdutil -E /

# Get help
mdutil -h

Checking Current Indexing Status

Before making changes, check the current indexing status:

#!/bin/bash

# Check Spotlight indexing status for all volumes
echo "Spotlight Indexing Status Report"
echo "==============================="
echo "Date: $(date)"
echo ""

# Get all mounted volumes
volumes=$(df -h | grep "^/dev" | awk '{print $9}')

echo "Volume Indexing Status:"
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 "Active indexing processes:"
ps aux | grep -i mds | grep -v grep

Disabling Spotlight Indexing

Basic Disable Script

Simple script to disable Spotlight indexing on the main volume:

#!/bin/bash

# Disable Spotlight indexing on the root volume
echo "Disabling Spotlight indexing..."

if sudo mdutil -i off /; then
    echo "✓ Spotlight indexing disabled successfully"
    
    # Verify the change
    status=$(mdutil -s / | grep "Indexing enabled")
    echo "Current status: $status"
else
    echo "✗ Failed to disable Spotlight indexing"
    exit 1
fi

echo "Note: Search functionality will be limited until indexing is re-enabled"

Advanced Disable Script with Logging

More comprehensive script with logging and verification:

#!/bin/bash

# Advanced Spotlight disable script with logging
LOG_FILE="/var/log/spotlight_management.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Function to log messages
log_message() {
    echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
}

# Function to disable indexing for a volume
disable_indexing() {
    local volume=$1
    
    log_message "Attempting to disable indexing for volume: $volume"
    
    # Check if volume exists
    if [ ! -d "$volume" ]; then
        log_message "ERROR: Volume $volume does not exist"
        return 1
    fi
    
    # Check current status
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    log_message "Current status for $volume: $current_status"
    
    # Disable indexing
    if sudo mdutil -i off "$volume"; then
        log_message "SUCCESS: Indexing disabled for $volume"
        
        # Verify the change
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        log_message "New status for $volume: $new_status"
        
        return 0
    else
        log_message "ERROR: Failed to disable indexing for $volume"
        return 1
    fi
}

# Main execution
log_message "Starting Spotlight indexing disable process"

# Disable for root volume
if disable_indexing "/"; then
    log_message "Root volume indexing disabled successfully"
else
    log_message "Failed to disable root volume indexing"
    exit 1
fi

# Optional: Disable for other volumes
# Uncomment the following lines to disable for additional volumes
# disable_indexing "/Volumes/ExternalDrive"
# disable_indexing "/Users"

log_message "Spotlight indexing disable process completed"
echo "Process completed. Check log at: $LOG_FILE"

Batch Disable for Multiple Volumes

Script to disable indexing on multiple volumes:

#!/bin/bash

# Batch disable Spotlight indexing for multiple volumes
VOLUMES=(
    "/"
    "/Users"
    "/Applications"
    # Add more volumes as needed
)

echo "Batch Spotlight Indexing Disable"
echo "================================"
echo "Date: $(date)"
echo ""

successful=0
failed=0

for volume in "${VOLUMES[@]}"; do
    echo "Processing volume: $volume"
    
    if [ -d "$volume" ]; then
        if sudo mdutil -i off "$volume" 2>/dev/null; then
            echo "  ✓ Successfully disabled indexing for $volume"
            ((successful++))
        else
            echo "  ✗ Failed to disable indexing for $volume"
            ((failed++))
        fi
    else
        echo "  ⚠ Volume $volume does not exist, skipping"
    fi
done

echo ""
echo "Summary:"
echo "--------"
echo "Successfully disabled: $successful volumes"
echo "Failed: $failed volumes"

if [ $failed -gt 0 ]; then
    echo "Some operations failed. Check individual volume status manually."
    exit 1
fi

Removing Spotlight Index Files

Basic Cleanup Script

After disabling indexing, remove existing index files to free up space:

#!/bin/bash

# Remove Spotlight index files
echo "Removing Spotlight index files..."

# Remove .Spotlight-V100 directories (modern macOS)
if sudo rm -rf /.Spotlight-V100; then
    echo "✓ Removed .Spotlight-V100 directory"
else
    echo "⚠ No .Spotlight-V100 directory found or removal failed"
fi

# Remove legacy .Spotlight directories
if sudo rm -rf /.Spotlight*; then
    echo "✓ Removed legacy Spotlight directories"
else
    echo "⚠ No legacy Spotlight directories found"
fi

# Calculate space freed
echo "Spotlight index cleanup completed"

Advanced Cleanup with Size Calculation

More detailed cleanup script that shows space savings:

#!/bin/bash

# Advanced Spotlight index cleanup with size reporting
echo "Spotlight Index Cleanup Utility"
echo "==============================="
echo "Date: $(date)"
echo ""

# Function to get directory size
get_size() {
    local dir=$1
    if [ -d "$dir" ]; then
        du -sh "$dir" 2>/dev/null | cut -f1
    else
        echo "0B"
    fi
}

# Function to remove spotlight directories
cleanup_spotlight_dirs() {
    local base_path=$1
    local total_size=0
    
    echo "Cleaning up Spotlight directories in: $base_path"
    
    # Find all Spotlight directories
    spotlight_dirs=$(find "$base_path" -name ".Spotlight*" -type d 2>/dev/null)
    
    if [ -z "$spotlight_dirs" ]; then
        echo "  No Spotlight directories found"
        return 0
    fi
    
    for dir in $spotlight_dirs; do
        size=$(get_size "$dir")
        echo "  Found: $dir ($size)"
        
        if sudo rm -rf "$dir"; then
            echo "    ✓ Removed successfully"
        else
            echo "    ✗ Failed to remove"
        fi
    done
}

# Clean up common locations
cleanup_spotlight_dirs "/"
cleanup_spotlight_dirs "/Users"

# Clean up on external volumes if any
for volume in /Volumes/*; do
    if [ -d "$volume" ]; then
        echo ""
        cleanup_spotlight_dirs "$volume"
    fi
done

echo ""
echo "Spotlight index cleanup completed"
echo "Run 'df -h' to see updated disk usage"

Enabling Spotlight Indexing

Basic Enable Script

Simple script to re-enable Spotlight indexing:

#!/bin/bash

# Enable Spotlight indexing on the root volume
echo "Enabling Spotlight indexing..."

if sudo mdutil -i on /; then
    echo "✓ Spotlight indexing enabled successfully"
    
    # Verify the change
    status=$(mdutil -s / | grep "Indexing enabled")
    echo "Current status: $status"
    
    echo ""
    echo "Note: Indexing will begin automatically and may take some time to complete"
    echo "You can monitor progress using Spotlight search"
else
    echo "✗ Failed to enable Spotlight indexing"
    exit 1
fi

Advanced Enable with Progress Monitoring

Script that enables indexing and provides progress monitoring:

#!/bin/bash

# Advanced Spotlight enable script with progress monitoring
LOG_FILE="/var/log/spotlight_management.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Function to log messages
log_message() {
    echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
}

# Function to monitor indexing progress
monitor_indexing() {
    local volume=$1
    local timeout=60  # Monitor for 60 seconds
    local elapsed=0
    
    echo "Monitoring indexing progress for $volume..."
    
    while [ $elapsed -lt $timeout ]; do
        # Check if indexing is in progress
        if ps aux | grep -v grep | grep -q "mds_stores\|mdworker"; then
            echo "  Indexing in progress... (${elapsed}s elapsed)"
        else
            echo "  Indexing may have completed or paused"
            break
        fi
        
        sleep 5
        elapsed=$((elapsed + 5))
    done
    
    if [ $elapsed -ge $timeout ]; then
        echo "  Monitoring timeout reached. Indexing may still be in progress."
    fi
}

# Function to enable indexing for a volume
enable_indexing() {
    local volume=$1
    
    log_message "Attempting to enable indexing for volume: $volume"
    
    # Check if volume exists
    if [ ! -d "$volume" ]; then
        log_message "ERROR: Volume $volume does not exist"
        return 1
    fi
    
    # Check current status
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    log_message "Current status for $volume: $current_status"
    
    # Enable indexing
    if sudo mdutil -i on "$volume"; then
        log_message "SUCCESS: Indexing enabled for $volume"
        
        # Verify the change
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        log_message "New status for $volume: $new_status"
        
        # Monitor initial progress
        monitor_indexing "$volume"
        
        return 0
    else
        log_message "ERROR: Failed to enable indexing for $volume"
        return 1
    fi
}

# Main execution
log_message "Starting Spotlight indexing enable process"

# Enable for root volume
if enable_indexing "/"; then
    log_message "Root volume indexing enabled successfully"
else
    log_message "Failed to enable root volume indexing"
    exit 1
fi

log_message "Spotlight indexing enable process completed"
echo "Process completed. Check log at: $LOG_FILE"

Rebuilding Spotlight Index

Basic Rebuild Script

Script to completely rebuild the Spotlight index:

#!/bin/bash

# Rebuild Spotlight index
echo "Rebuilding Spotlight index..."
echo "Warning: This will erase the current index and rebuild from scratch"
echo ""

read -p "Continue? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
    echo "Operation cancelled"
    exit 0
fi

echo "Starting index rebuild..."

if sudo mdutil -E /; then
    echo "✓ Index rebuild initiated successfully"
    
    # Show status
    status=$(mdutil -s /)
    echo "Current status: $status"
    
    echo ""
    echo "The index rebuild process has started and will continue in the background"
    echo "This may take several hours depending on the amount of data"
    echo "You can monitor progress using Activity Monitor (look for mds_stores and mdworker processes)"
else
    echo "✗ Failed to initiate index rebuild"
    exit 1
fi

Advanced Rebuild with Selective Volumes

Script to rebuild indexes for specific volumes:

#!/bin/bash

# Advanced Spotlight index rebuild script
VOLUMES=(
    "/"
    "/Users"
    # Add specific volumes or use discovery
)

AUTO_DISCOVER=${1:-false}

echo "Spotlight Index Rebuild Utility"
echo "==============================="
echo "Date: $(date)"
echo ""

# Function to discover mounted volumes
discover_volumes() {
    echo "Discovering mounted volumes..."
    
    # Get all mounted HFS+/APFS volumes
    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 "Discovered volumes:"
    for vol in "${discovered_volumes[@]}"; do
        echo "  - $vol"
    done
    
    VOLUMES=("${discovered_volumes[@]}")
}

# Function to rebuild index for a volume
rebuild_index() {
    local volume=$1
    
    echo "Rebuilding index for: $volume"
    
    # Check if volume exists and is mounted
    if [ ! -d "$volume" ]; then
        echo "  ✗ Volume $volume does not exist or is not mounted"
        return 1
    fi
    
    # Show current status
    current_status=$(mdutil -s "$volume" 2>/dev/null)
    echo "  Current status: $current_status"
    
    # Rebuild index
    if sudo mdutil -E "$volume"; then
        echo "  ✓ Index rebuild initiated for $volume"
        
        # Show new status
        new_status=$(mdutil -s "$volume" 2>/dev/null)
        echo "  New status: $new_status"
        
        return 0
    else
        echo "  ✗ Failed to rebuild index for $volume"
        return 1
    fi
}

# Auto-discover volumes if requested
if [ "$AUTO_DISCOVER" = "true" ]; then
    discover_volumes
fi

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

echo ""
read -p "Proceed with rebuilding indexes? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
    echo "Operation cancelled"
    exit 0
fi

echo ""
echo "Starting index rebuild process..."
echo ""

successful=0
failed=0

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

echo "Rebuild Summary:"
echo "---------------"
echo "Successfully initiated: $successful volumes"
echo "Failed: $failed volumes"
echo ""
echo "Note: Index rebuilding will continue in the background"
echo "Monitor progress with: ps aux | grep mds"

Advanced Spotlight Management

Selective Directory Exclusion

Script to exclude specific directories from indexing:

#!/bin/bash

# Exclude specific directories from Spotlight indexing
EXCLUDE_DIRS=(
    "/tmp"
    "/var/tmp"
    "/private/tmp"
    "/Users/Shared/Build"
    # Add more directories as needed
)

echo "Spotlight Directory Exclusion Manager"
echo "===================================="
echo ""

# Function to add directory to exclusion list
exclude_directory() {
    local dir_path=$1
    
    echo "Excluding directory: $dir_path"
    
    # Check if directory exists
    if [ ! -d "$dir_path" ]; then
        echo "  ⚠ Directory does not exist: $dir_path"
        return 1
    fi
    
    # Add to Spotlight privacy list using defaults
    if sudo defaults write /System/Library/CoreServices/Search.bundle/Contents/Resources/SpotlightExclusions.plist Exclusions -array-add "$dir_path"; then
        echo "  ✓ Added to exclusion list"
        return 0
    else
        echo "  ✗ Failed to add to exclusion list"
        return 1
    fi
}

# Function to show current exclusions
show_exclusions() {
    echo "Current Spotlight exclusions:"
    echo "----------------------------"
    
    # Read from system preferences
    if defaults read /System/Library/CoreServices/Search.bundle/Contents/Resources/SpotlightExclusions.plist Exclusions 2>/dev/null; then
        echo ""
    else
        echo "No exclusions found or unable to read exclusions list"
    fi
}

# Show current exclusions
show_exclusions

echo ""
echo "Adding new exclusions..."

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

echo ""
echo "Exclusion process completed"
echo "Restart Spotlight for changes to take effect:"
echo "sudo killall mds && sudo mdutil -E /"

Performance Monitoring Script

Script to monitor Spotlight's impact on system performance:

#!/bin/bash

# Spotlight Performance Monitor
DURATION=${1:-60}  # Monitor for 60 seconds by default
INTERVAL=5

echo "Spotlight Performance Monitor"
echo "============================"
echo "Monitoring duration: ${DURATION} seconds"
echo "Sample interval: ${INTERVAL} seconds"
echo ""

# Function to get Spotlight process stats
get_spotlight_stats() {
    local timestamp=$(date '+%H:%M:%S')
    
    # Get mds processes
    mds_stats=$(ps aux | grep -E "mds|mdworker" | grep -v grep | awk '{
        cpu += $3; 
        mem += $4; 
        count++
    } END {
        printf "Processes: %d, CPU: %.1f%%, Memory: %.1f%%", count, cpu, mem
    }')
    
    # Get disk activity (if available)
    disk_activity=$(iostat -c 1 2>/dev/null | tail -1 | awk '{print "Disk: " $4 "% utilization"}' || echo "Disk: N/A")
    
    echo "[$timestamp] $mds_stats, $disk_activity"
}

# Header
echo "Time     | Spotlight Stats"
echo "---------|------------------------------------------------"

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

echo ""
echo "Monitoring completed"

# Show summary
echo ""
echo "Final Process Summary:"
echo "---------------------"
ps aux | grep -E "mds|mdworker" | grep -v grep | head -10

Automation and Scheduling

Automated Maintenance Script

Script for scheduled Spotlight maintenance:

#!/bin/bash

# Automated Spotlight maintenance script
# Can be run via cron or launchd

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

# Default configuration
REBUILD_INTERVAL=30  # days
CLEANUP_TEMP=true
MONITOR_PERFORMANCE=true

# Function to log with timestamp
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Load configuration if exists
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
    log_message "Configuration loaded from $CONFIG_FILE"
fi

# Function to check if rebuild is needed
needs_rebuild() {
    local index_age_file="/var/db/.spotlight_last_rebuild"
    
    if [ ! -f "$index_age_file" ]; then
        return 0  # No record, assume rebuild needed
    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 "Index age: $age_days days, rebuild needed"
        return 0
    else
        log_message "Index age: $age_days days, rebuild not needed"
        return 1
    fi
}

# Function to perform rebuild
perform_rebuild() {
    log_message "Starting scheduled index rebuild"
    
    if sudo mdutil -E /; then
        log_message "Index rebuild initiated successfully"
        echo "$(date +%s)" | sudo tee /var/db/.spotlight_last_rebuild > /dev/null
        return 0
    else
        log_message "Index rebuild failed"
        return 1
    fi
}

# Function to cleanup temporary files
cleanup_temp_files() {
    if [ "$CLEANUP_TEMP" = true ]; then
        log_message "Cleaning up temporary Spotlight files"
        
        # Remove temporary index files
        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 "Temporary file cleanup completed"
    fi
}

# Function to check performance
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 "WARNING: High Spotlight CPU usage detected: ${mds_cpu}%"
        else
            log_message "Spotlight performance normal: ${mds_cpu:-0}% CPU"
        fi
    fi
}

# Main maintenance routine
log_message "Starting automated Spotlight maintenance"

check_performance
cleanup_temp_files

if needs_rebuild; then
    perform_rebuild
fi

log_message "Automated Spotlight maintenance completed"

Best Practices and Recommendations

1. Performance Considerations

  • Monitor system resources before disabling indexing
  • Consider partial exclusions instead of complete disable
  • Schedule maintenance during off-hours
  • Test changes on non-production systems first

2. Security and Privacy

  • Exclude sensitive directories from indexing
  • Regularly review and update exclusion lists
  • Consider the security implications of search functionality
  • Document all changes for compliance purposes

3. Enterprise Management

  • Standardize Spotlight policies across devices
  • Use configuration management tools for deployment
  • Implement monitoring and alerting for index issues
  • Maintain documentation of all customizations

4. Troubleshooting Guidelines

  • Always check system logs when issues occur
  • Test individual commands before running complex scripts
  • Keep backups of important data before major changes
  • Document the steps taken for future reference

Troubleshooting Common Issues

Index Corruption

#!/bin/bash

# Fix corrupted Spotlight index
echo "Fixing corrupted Spotlight index..."

# Stop indexing
sudo mdutil -i off /

# Remove corrupted index
sudo rm -rf /.Spotlight-V100

# Re-enable and rebuild
sudo mdutil -i on /
sudo mdutil -E /

echo "Index repair initiated"

High CPU Usage

#!/bin/bash

# Address high Spotlight CPU usage
echo "Addressing high Spotlight CPU usage..."

# Check current processes
echo "Current Spotlight processes:"
ps aux | grep -E "mds|mdworker" | grep -v grep

# Temporarily throttle indexing
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
sleep 5
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist

echo "Spotlight services restarted"

Conclusion

Effective Spotlight management is crucial for maintaining optimal macOS performance while preserving search functionality where needed. The scripts and techniques provided in this guide offer comprehensive solutions for various Spotlight management scenarios.

Key takeaways:

  • Understand the impact of indexing on system performance
  • Use appropriate scripts for your specific use case
  • Implement proper monitoring and maintenance procedures
  • Always test changes in a controlled environment
  • Document all modifications for future reference

Remember that disabling Spotlight indexing will significantly impact search functionality, so carefully consider the trade-offs before implementing these changes across your Mac fleet.

Sleep and Power Management for macOS

Implement enterprise-grade sleep and power management across your Roundfleet deployment with automated power policies, energy optimization, compliance monitoring, and comprehensive fleet-wide management. This tutorial provides solutions for maintaining optimal power efficiency while ensuring security and operational requirements are met.

Understanding macOS Power Management

macOS provides several power management tools and mechanisms:

  • pmset - Primary power management settings tool
  • caffeinate - Prevent system sleep for specific operations
  • systemsetup - System-wide power configuration
  • Energy Saver - GUI power management interface
  • Power Assertions - Application-level sleep prevention

Basic Power Management Operations

Configure System Sleep Timer

#!/bin/bash

# Set system sleep timer to 15 minutes
sudo pmset sleep 15

Configure Display Sleep Timer

#!/bin/bash

# Set display sleep timer to 15 minutes
sudo pmset displaysleep 15

Schedule Wake Events

#!/bin/bash

# Schedule wake every day at 9:00 AM
sudo pmset repeat wakeorpoweron MTWRFSU 9:00:00

Prevent Sleep for Specific Period

#!/bin/bash

# Prevent system sleep for 300 seconds
caffeinate -u -t 300

Check System Sleep Settings

#!/bin/bash

# Check current sleep idle time
sudo systemsetup -getcomputersleep

Disable System Sleep

#!/bin/bash

# Turn off system sleep
sudo systemsetup -setcomputersleep Never

Enable Restart on Freeze

#!/bin/bash

# Restart automatically on system freeze
systemsetup -setrestartfreeze on

Enterprise Power Management System

Comprehensive Power Management Tool

#!/bin/bash

# Roundfleet Enterprise Sleep and Power Management Tool
# Advanced power policies and energy optimization

# 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"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$POLICIES_DIR" "$(dirname "$AUDIT_LOG")"

# Default power management policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Enterprise Power Management Policy
# Version: 2.0

# Power Policy Enforcement
ENFORCE_POWER_POLICIES=true
AUTO_APPLY_POLICIES=true
POWER_PROFILE="corporate_standard"
ENERGY_OPTIMIZATION=true
COMPLIANCE_MONITORING=true

# Sleep Settings (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

# Wake and Power Events
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

# Business Hours Configuration
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
BUSINESS_DAYS="MTWRF"
WEEKEND_POWER_PROFILE="energy_saver"
AFTER_HOURS_POWER_PROFILE="security_focused"

# Security and Maintenance
SECURE_VIRTUAL_MEMORY=true
DESTROY_FILEVAULT_KEYS_ON_STANDBY=true
HIBERNATE_MODE=3
STANDBY_DELAY=10800
AUTOPOWEROFF_ENABLED=true
AUTOPOWEROFF_DELAY=14400

# Energy and Performance
PROCESSOR_SPEED_REDUCTION=false
REDUCE_BRIGHTNESS_BATTERY=true
DISABLE_POWER_BUTTON_SLEEP=false
PREVENT_SLEEP_DURING_PRESENTATIONS=true
THERMAL_MANAGEMENT=true

# Monitoring and Reporting
POWER_EVENT_LOGGING=true
ENERGY_USAGE_MONITORING=true
BATTERY_HEALTH_MONITORING=true
POWER_ASSERTION_TRACKING=true
AUTOMATED_REPORTING=true

# Compliance Settings
REGULATORY_COMPLIANCE="ENERGY_STAR"
CARBON_FOOTPRINT_TRACKING=true
SUSTAINABILITY_REPORTING=true
POWER_AUDIT_TRAILS=true
EOF

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

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

# Audit logging function
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"
}

# Get current power settings
get_power_status() {
    echo "=== Current Power Management Status ==="
    
    # System-wide power settings
    echo "System Power Settings:"
    pmset -g 2>/dev/null || echo "  Power settings unavailable"
    
    echo -e "\nCurrent Power Source:"
    pmset -g ps 2>/dev/null | head -1
    
    echo -e "\nSleep Timers:"
    echo "  System Sleep (AC): $(pmset -g | grep -E '^\s*sleep\s' | awk '{print $2}') minutes"
    echo "  Display Sleep (AC): $(pmset -g | grep -E '^\s*displaysleep\s' | awk '{print $2}') minutes"
    echo "  Disk Sleep (AC): $(pmset -g | grep -E '^\s*disksleep\s' | awk '{print $2}') minutes"
    
    echo -e "\nPower Assertions:"
    pmset -g assertions 2>/dev/null | grep -E "(PreventUserIdleSystemSleep|PreventUserIdleDisplaySleep)" | head -5
    
    echo -e "\nThermal State:"
    pmset -g thermstate 2>/dev/null | head -3
    
    echo -e "\nBattery Information:"
    if system_profiler SPPowerDataType 2>/dev/null | grep -q "Battery Information"; then
        system_profiler SPPowerDataType | grep -A 10 "Battery Information" | head -10
    else
        echo "  No battery information available (Desktop Mac)"
    fi
    
    return 0
}

# Apply enterprise power profile
apply_power_profile() {
    local profile="${1:-$POWER_PROFILE}"
    
    echo "=== Applying Enterprise Power Profile: $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 "Unknown power profile: $profile"
            echo "Using corporate_standard profile as fallback"
            apply_corporate_standard_profile
            ;;
    esac
    
    # Apply common security settings
    apply_security_settings
    
    # Configure scheduled events
    configure_scheduled_events
    
    echo "✅ Power profile '$profile' applied successfully"
    log_action "Power profile applied: $profile"
    audit_log "POWER_PROFILE" "APPLIED" "Profile: $profile"
    
    return 0
}

# Corporate standard power profile
apply_corporate_standard_profile() {
    echo "=== Configuring Corporate Standard Profile ==="
    
    # AC Power settings
    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
    
    # Battery settings (if 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
    
    # Wake settings
    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
    
    # Restart settings
    if [[ "$AUTOMATIC_RESTART_ON_POWER_LOSS" == "true" ]]; then
        sudo pmset -a autorestart 1 2>/dev/null
    fi
    
    if [[ "$AUTOMATIC_RESTART_ON_FREEZE" == "true" ]]; then
        sudo systemsetup -setrestartfreeze on 2>/dev/null
    fi
    
    echo "Corporate standard profile configured"
    log_action "Corporate standard power profile applied"
}

# Energy saver profile
apply_energy_saver_profile() {
    echo "=== Configuring Energy Saver Profile ==="
    
    # Aggressive power saving
    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
    
    # Enable power-saving features
    sudo pmset -a reducebright 1 2>/dev/null
    sudo pmset -a lessbright 1 2>/dev/null
    
    echo "Energy saver profile configured"
    log_action "Energy saver power profile applied"
}

# High performance profile
apply_high_performance_profile() {
    echo "=== Configuring High Performance Profile ==="
    
    # Minimal sleep settings
    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
    
    # Disable power-saving features
    sudo pmset -a reducebright 0 2>/dev/null
    sudo pmset -a lessbright 0 2>/dev/null
    
    echo "High performance profile configured"
    log_action "High performance power profile applied"
}

# Security focused profile
apply_security_focused_profile() {
    echo "=== Configuring Security Focused Profile ==="
    
    # Short sleep timers for security
    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
    
    # Enhanced security settings
    sudo pmset -a destroyfvkeyonstandby 1 2>/dev/null
    sudo pmset -a hibernatemode 25 2>/dev/null
    
    echo "Security focused profile configured"
    log_action "Security focused power profile applied"
}

# Presentation mode profile
apply_presentation_mode_profile() {
    echo "=== Configuring Presentation Mode Profile ==="
    
    # Prevent sleep during presentations
    sudo pmset -c sleep 0 2>/dev/null
    sudo pmset -c displaysleep 0 2>/dev/null
    
    # Keep system active
    sudo pmset -a lidwake 1 2>/dev/null
    sudo pmset -a acwake 1 2>/dev/null
    
    echo "Presentation mode profile configured"
    log_action "Presentation mode power profile applied"
}

# Kiosk mode profile
apply_kiosk_mode_profile() {
    echo "=== Configuring Kiosk Mode Profile ==="
    
    # Never sleep settings for kiosk devices
    sudo pmset -c sleep 0 2>/dev/null
    sudo pmset -c displaysleep 0 2>/dev/null
    sudo pmset -c disksleep 0 2>/dev/null
    
    # Ensure system stays active
    sudo pmset -a womp 1 2>/dev/null
    sudo pmset -a autorestart 1 2>/dev/null
    
    echo "Kiosk mode profile configured"
    log_action "Kiosk mode power profile applied"
}

# Apply security-specific power settings
apply_security_settings() {
    echo "=== Applying Security Power Settings ==="
    
    if [[ "$SECURE_VIRTUAL_MEMORY" == "true" ]]; then
        sudo pmset -a securevm 1 2>/dev/null
        echo "✅ Secure virtual memory enabled"
    fi
    
    if [[ "$DESTROY_FILEVAULT_KEYS_ON_STANDBY" == "true" ]]; then
        sudo pmset -a destroyfvkeyonstandby 1 2>/dev/null
        echo "✅ FileVault key destruction on standby enabled"
    fi
    
    # Configure hibernation mode
    sudo pmset -a hibernatemode "$HIBERNATE_MODE" 2>/dev/null
    echo "✅ Hibernation mode set to $HIBERNATE_MODE"
    
    # Configure standby and autopoweroff
    sudo pmset -a standbydelay "$STANDBY_DELAY" 2>/dev/null
    
    if [[ "$AUTOPOWEROFF_ENABLED" == "true" ]]; then
        sudo pmset -a autopoweroff 1 2>/dev/null
        sudo pmset -a autopoweroffdelay "$AUTOPOWEROFF_DELAY" 2>/dev/null
        echo "✅ Auto power off enabled"
    fi
    
    log_action "Security power settings applied"
}

# Configure scheduled wake/sleep events
configure_scheduled_events() {
    echo "=== Configuring Scheduled Power Events ==="
    
    # Clear existing scheduled events
    sudo pmset repeat cancel 2>/dev/null
    
    if [[ "$SCHEDULED_WAKE_ENABLED" == "true" ]]; then
        # Schedule wake for business hours
        sudo pmset repeat wakeorpoweron "$BUSINESS_DAYS" "$BUSINESS_HOURS_START:00" 2>/dev/null
        echo "✅ Scheduled wake configured for business hours"
        log_action "Scheduled wake configured: $BUSINESS_DAYS at $BUSINESS_HOURS_START"
    fi
    
    if [[ "$SCHEDULED_SLEEP_ENABLED" == "true" ]]; then
        # Schedule sleep after business hours
        local sleep_time="${BUSINESS_HOURS_END}:30:00"
        sudo pmset repeat sleep "$BUSINESS_DAYS" "$sleep_time" 2>/dev/null
        echo "✅ Scheduled sleep configured for after hours"
        log_action "Scheduled sleep configured: $BUSINESS_DAYS at $sleep_time"
    fi
}

# Monitor power events and assertions
monitor_power_events() {
    echo "=== Starting Power Event Monitoring ==="
    
    local monitor_duration="${1:-3600}"  # Default 1 hour
    local end_time=$(($(date +%s) + monitor_duration))
    
    echo "Monitoring power events for $((monitor_duration/60)) minutes..."
    echo "Press Ctrl+C to stop monitoring"
    
    while [[ $(date +%s) -lt $end_time ]]; do
        # Check power assertions
        local assertion_count
        assertion_count=$(pmset -g assertions 2>/dev/null | grep -c "PreventUserIdleSystemSleep\|PreventUserIdleDisplaySleep" || echo 0)
        
        if [[ $assertion_count -gt 0 ]]; then
            echo "$(date '+%H:%M:%S') - Active power assertions: $assertion_count"
            pmset -g assertions 2>/dev/null | grep -E "(PreventUserIdleSystemSleep|PreventUserIdleDisplaySleep)" | head -3
        fi
        
        # Check thermal state
        local thermal_state
        thermal_state=$(pmset -g thermstate 2>/dev/null | grep -o "Normal\|Fair\|Serious\|Critical" | head -1)
        
        if [[ "$thermal_state" != "Normal" && -n "$thermal_state" ]]; then
            echo "$(date '+%H:%M:%S') - ⚠️  Thermal state: $thermal_state"
            log_action "Thermal warning: $thermal_state"
        fi
        
        # Check power source changes
        local current_power_source
        current_power_source=$(pmset -g ps 2>/dev/null | head -1)
        
        if [[ -f "/tmp/roundfleet_last_power_source" ]]; then
            local last_power_source
            last_power_source=$(cat "/tmp/roundfleet_last_power_source")
            
            if [[ "$current_power_source" != "$last_power_source" ]]; then
                echo "$(date '+%H:%M:%S') - 🔌 Power source changed: $current_power_source"
                log_action "Power source change: $current_power_source"
                audit_log "POWER_SOURCE_CHANGE" "DETECTED" "$current_power_source"
                
                # Auto-adjust power profile based on power source
                auto_adjust_power_profile
            fi
        fi
        
        echo "$current_power_source" > "/tmp/roundfleet_last_power_source"
        
        sleep 30
    done
    
    echo "Power monitoring completed"
}

# Auto-adjust power profile based on conditions
auto_adjust_power_profile() {
    local current_hour
    current_hour=$(date +%H)
    
    local current_power_source
    current_power_source=$(pmset -g ps 2>/dev/null | head -1)
    
    echo "=== Auto-adjusting Power Profile ==="
    
    # Determine appropriate profile
    local new_profile=""
    
    if echo "$current_power_source" | grep -q "Battery Power"; then
        new_profile="energy_saver"
        echo "On battery power - switching to energy saver profile"
    elif [[ $current_hour -ge 18 || $current_hour -lt 9 ]]; then
        new_profile="$AFTER_HOURS_POWER_PROFILE"
        echo "After hours - switching to $new_profile profile"
    else
        new_profile="$POWER_PROFILE"
        echo "Business hours - switching to $new_profile profile"
    fi
    
    if [[ -n "$new_profile" ]]; then
        apply_power_profile "$new_profile"
        log_action "Auto-adjusted power profile to: $new_profile"
    fi
}

# Check power management compliance
check_power_compliance() {
    echo "=== Power Management Compliance Check ==="
    
    local compliance_issues=()
    local compliance_score=100
    
    # Check if power management is properly configured
    local current_settings
    current_settings=$(pmset -g 2>/dev/null)
    
    if [[ -z "$current_settings" ]]; then
        compliance_issues+=("Unable to read power management settings")
        compliance_score=$((compliance_score - 50))
    fi
    
    # Check sleep timers
    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+=("System sleep disabled (security risk)")
        compliance_score=$((compliance_score - 20))
    fi
    
    # Check display sleep
    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+=("Display sleep disabled (energy waste)")
        compliance_score=$((compliance_score - 15))
    fi
    
    # Check security settings
    local hibernatemode
    hibernatemode=$(echo "$current_settings" | grep -E '^\s*hibernatemode\s' | awk '{print $2}')
    
    if [[ "$hibernatemode" == "0" ]] && [[ "$DESTROY_FILEVAULT_KEYS_ON_STANDBY" == "true" ]]; then
        compliance_issues+=("Hibernation disabled but FileVault key destruction enabled")
        compliance_score=$((compliance_score - 10))
    fi
    
    # Check thermal management
    local thermal_state
    thermal_state=$(pmset -g thermstate 2>/dev/null | grep -o "Normal\|Fair\|Serious\|Critical" | head -1)
    
    if [[ "$thermal_state" == "Serious" || "$thermal_state" == "Critical" ]]; then
        compliance_issues+=("Thermal management issue: $thermal_state")
        compliance_score=$((compliance_score - 25))
    fi
    
    # Report compliance status
    echo "Compliance Score: $compliance_score/100"
    
    if [[ ${#compliance_issues[@]} -eq 0 ]]; then
        echo "✅ Power management configuration is compliant"
        audit_log "COMPLIANCE_CHECK" "PASSED" "Score: $compliance_score/100"
        return 0
    else
        echo "❌ Compliance issues found:"
        printf '  - %s\n' "${compliance_issues[@]}"
        audit_log "COMPLIANCE_CHECK" "FAILED" "Issues: ${#compliance_issues[@]} Score: $compliance_score/100"
        
        # Auto-remediation if enabled
        if [[ "$AUTO_APPLY_POLICIES" == "true" ]]; then
            echo "🔧 Auto-remediation enabled, applying correct power profile..."
            apply_power_profile "$POWER_PROFILE"
        fi
        
        return 1
    fi
}

# Generate power management report
generate_power_report() {
    local report_file="$POLICIES_DIR/power_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Power Management Report ==="
    
    # Get current power information
    local power_source=""
    local battery_percentage=""
    local thermal_state=""
    local power_assertions=""
    
    if command -v pmset >/dev/null; then
        power_source=$(pmset -g ps 2>/dev/null | head -1 | sed 's/.*from //' | sed 's/;.*//')
        battery_percentage=$(pmset -g ps 2>/dev/null | grep -o '[0-9]*%' | head -1 | sed 's/%//')
        thermal_state=$(pmset -g thermstate 2>/dev/null | grep -o "Normal\|Fair\|Serious\|Critical" | head -1)
        power_assertions=$(pmset -g assertions 2>/dev/null | grep -c "PreventUserIdleSystemSleep\|PreventUserIdleDisplaySleep" || echo 0)
    fi
    
    # Get energy usage data
    local uptime_seconds
    uptime_seconds=$(uptime | awk '{print $3}' | cut -d',' -f1 | cut -d':' -f2)
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "power_management",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "os_version": "$(sw_vers -productVersion)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "model": "$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F: '{print $2}' | xargs)"
  },
  "power_status": {
    "power_source": "$power_source",
    "battery_percentage": $([ -n "$battery_percentage" ] && echo "$battery_percentage" || echo "null"),
    "thermal_state": "${thermal_state:-Normal}",
    "active_power_assertions": $power_assertions
  },
  "power_settings": {
    "current_profile": "$POWER_PROFILE",
    "system_sleep_ac": "$SYSTEM_SLEEP_AC",
    "display_sleep_ac": "$DISPLAY_SLEEP_AC",
    "wake_on_lan": $WAKE_ON_LAN,
    "auto_restart_on_power_loss": $AUTOMATIC_RESTART_ON_POWER_LOSS
  },
  "energy_optimization": {
    "energy_optimization_enabled": $ENERGY_OPTIMIZATION,
    "reduce_brightness_battery": $REDUCE_BRIGHTNESS_BATTERY,
    "thermal_management": $THERMAL_MANAGEMENT
  },
  "compliance_status": {
    "policy_compliant": $(check_power_compliance >/dev/null 2>&1 && echo true || echo false),
    "auto_apply_policies": $AUTO_APPLY_POLICIES,
    "regulatory_compliance": "$REGULATORY_COMPLIANCE"
  },
  "sustainability": {
    "carbon_footprint_tracking": $CARBON_FOOTPRINT_TRACKING,
    "energy_star_compliant": $([ "$REGULATORY_COMPLIANCE" == "ENERGY_STAR" ] && echo true || echo false)
  }
}
EOF
    
    echo "Power management report saved to: $report_file"
    log_action "Power management report generated: $report_file"
}

# Prevent system sleep for critical operations
prevent_sleep_for_operation() {
    local operation_name="$1"
    local duration_seconds="$2"
    local prevent_display="${3:-false}"
    
    echo "=== Preventing Sleep for Operation: $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 "Preventing system sleep for $operation_name..."
    log_action "Sleep prevention started for operation: $operation_name (duration: ${duration_seconds:-indefinite}s)"
    
    # Run caffeinate in background and return PID
    caffeinate $caffeinate_options &
    local caffeinate_pid=$!
    
    echo "Sleep prevention active (PID: $caffeinate_pid)"
    echo "$caffeinate_pid" > "/tmp/roundfleet_caffeinate_$operation_name.pid"
    
    audit_log "SLEEP_PREVENTION" "STARTED" "Operation: $operation_name PID: $caffeinate_pid"
    
    return 0
}

# Stop sleep prevention for operation
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 "Sleep prevention stopped for $operation_name (PID: $caffeinate_pid)"
            log_action "Sleep prevention stopped for operation: $operation_name"
            audit_log "SLEEP_PREVENTION" "STOPPED" "Operation: $operation_name PID: $caffeinate_pid"
        else
            echo "Sleep prevention process not found for $operation_name"
        fi
        
        rm -f "$pid_file"
    else
        echo "No active sleep prevention found for $operation_name"
    fi
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Power Management Tool Started ==="
    
    case "${1:-status}" in
        "status")
            get_power_status
            ;;
        "profile")
            apply_power_profile "$2"
            ;;
        "monitor")
            monitor_power_events "$2"
            ;;
        "compliance")
            check_power_compliance
            ;;
        "report")
            generate_power_report
            ;;
        "prevent-sleep")
            prevent_sleep_for_operation "$2" "$3" "$4"
            ;;
        "allow-sleep")
            stop_sleep_prevention "$2"
            ;;
        "auto-adjust")
            auto_adjust_power_profile
            ;;
        "schedule")
            configure_scheduled_events
            ;;
        *)
            echo "Roundfleet Enterprise Power Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  status                        - Show current power management status"
            echo "  profile [name]                - Apply specific power profile"
            echo "  monitor [duration]            - Monitor power events (duration in seconds)"
            echo "  compliance                    - Check power management compliance"
            echo "  report                        - Generate power management report"
            echo "  prevent-sleep [name] [duration] [display] - Prevent sleep for operation"
            echo "  allow-sleep [name]            - Stop sleep prevention for operation"
            echo "  auto-adjust                   - Auto-adjust power profile based on conditions"
            echo "  schedule                      - Configure scheduled power events"
            echo ""
            echo "Power Profiles:"
            echo "  corporate_standard            - Standard corporate power management (default)"
            echo "  energy_saver                  - Maximum energy efficiency"
            echo "  high_performance              - Performance-focused settings"
            echo "  security_focused              - Security-optimized power management"
            echo "  presentation_mode             - Prevent sleep during presentations"
            echo "  kiosk_mode                    - Always-on for kiosk devices"
            ;;
    esac
    
    log_action "=== Power management operation completed ==="
}

# Execute main function
main "$@"

## Advanced Power Management Features

### Business Hours Power Automation

```bash
#!/bin/bash

# Automated business hours power management
setup_business_hours_automation() {
    echo "=== Setting Up Business Hours Power Automation ==="
    
    # Create business hours power management script
    local automation_script="/Library/Roundfleet/Scripts/business_hours_power.sh"
    mkdir -p "$(dirname "$automation_script")"
    
    cat > "$automation_script" << 'EOF'
#!/bin/bash

# Determine current time and apply appropriate power profile
current_hour=$(date +%H)
current_day=$(date +%u)  # 1=Monday, 7=Sunday

# Business hours: Monday-Friday 9AM-6PM
if [[ $current_day -le 5 ]] && [[ $current_hour -ge 9 ]] && [[ $current_hour -lt 18 ]]; then
    # Business hours
    /Library/Roundfleet/Scripts/power_management.sh profile corporate_standard
elif [[ $current_day -gt 5 ]]; then
    # Weekend
    /Library/Roundfleet/Scripts/power_management.sh profile energy_saver
else
    # After hours
    /Library/Roundfleet/Scripts/power_management.sh profile security_focused
fi
EOF
    
    chmod +x "$automation_script"
    
    # Create launch daemon for automation
    local launch_daemon="/Library/LaunchDaemons/com.roundfleet.power.automation.plist"
    
    cat > "$launch_daemon" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.roundfleet.power.automation</string>
    <key>ProgramArguments</key>
    <array>
        <string>$automation_script</string>
    </array>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>9</integer>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
        <dict>
            <key>Hour</key>
            <integer>18</integer>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF
    
    # Load the launch daemon
    sudo launchctl load "$launch_daemon" 2>/dev/null
    
    echo "✅ Business hours power automation configured"
    log_action "Business hours power automation setup completed"
}

# Battery optimization for laptops
optimize_battery_performance() {
    echo "=== Optimizing Battery Performance ==="
    
    # Check if device has a battery
    if ! system_profiler SPPowerDataType 2>/dev/null | grep -q "Battery Information"; then
        echo "No battery detected - skipping battery optimization"
        return 0
    fi
    
    # Get current battery information
    local battery_condition
    battery_condition=$(system_profiler SPPowerDataType | grep "Condition" | awk -F: '{print $2}' | xargs)
    
    local cycle_count
    cycle_count=$(system_profiler SPPowerDataType | grep "Cycle Count" | awk -F: '{print $2}' | xargs)
    
    echo "Battery Condition: $battery_condition"
    echo "Cycle Count: $cycle_count"
    
    # Apply battery-specific optimizations
    if [[ "$battery_condition" == "Replace Soon" || "$battery_condition" == "Replace Now" ]]; then
        echo "⚠️  Battery needs replacement - applying conservative settings"
        sudo pmset -b sleep 5 2>/dev/null
        sudo pmset -b displaysleep 2 2>/dev/null
        sudo pmset -b reducebright 1 2>/dev/null
        
        log_action "BATTERY WARNING: $battery_condition - Conservative settings applied"
        audit_log "BATTERY_WARNING" "DETECTED" "Condition: $battery_condition Cycles: $cycle_count"
    else
        echo "✅ Battery condition normal - applying standard optimization"
        sudo pmset -b sleep "$SYSTEM_SLEEP_BATTERY" 2>/dev/null
        sudo pmset -b displaysleep "$DISPLAY_SLEEP_BATTERY" 2>/dev/null
    fi
    
    # Enable optimized battery charging
    sudo pmset -a optimizedcharging 1 2>/dev/null
    
    echo "Battery optimization completed"
    log_action "Battery performance optimization applied"
}

# Thermal management
monitor_thermal_state() {
    echo "=== Thermal State Monitoring ==="
    
    local thermal_log="/var/log/roundfleet_thermal.log"
    local monitoring_duration="${1:-300}"  # Default 5 minutes
    
    echo "Monitoring thermal state for $((monitoring_duration/60)) minutes..."
    
    local end_time=$(($(date +%s) + monitoring_duration))
    
    while [[ $(date +%s) -lt $end_time ]]; do
        local thermal_state
        thermal_state=$(pmset -g thermstate 2>/dev/null | grep -o "Normal\|Fair\|Serious\|Critical" | head -1)
        
        local cpu_temp=""
        if command -v powermetrics >/dev/null; then
            cpu_temp=$(sudo powermetrics -n 1 -s cpu_power 2>/dev/null | grep "CPU die temperature" | awk '{print $4}' | head -1)
        fi
        
        local timestamp
        timestamp=$(date '+%Y-%m-%d %H:%M:%S')
        
        echo "$timestamp - Thermal: $thermal_state CPU: ${cpu_temp:-N/A}°C" | tee -a "$thermal_log"
        
        case "$thermal_state" in
            "Serious"|"Critical")
                echo "🚨 THERMAL ALERT: $thermal_state - Taking protective action"
                # Reduce performance to cool down
                sudo pmset -a reducebright 1 2>/dev/null
                # Log critical thermal event
                log_action "THERMAL ALERT: $thermal_state detected - protective measures activated"
                audit_log "THERMAL_ALERT" "CRITICAL" "State: $thermal_state CPU: ${cpu_temp:-N/A}°C"
                ;;
            "Fair")
                echo "⚠️  Thermal warning: $thermal_state"
                log_action "Thermal warning: $thermal_state"
                ;;
        esac
        
        sleep 10
    done
    
    echo "Thermal monitoring completed"
}

## Important Configuration Notes

### macOS Power Management Architecture

- **Power Management Unit (PMU)** - Hardware-level power control
- **IOPMrootDomain** - Kernel power management
- **PowerManagement.framework** - User-space power APIs
- **pmset** - Command-line power management tool
- **Energy Saver** - System Preferences power interface

### Enterprise Integration Points

- **MDM Configuration Profiles** - Deploy power policies centrally
- **Energy Monitoring Systems** - Integration with facility management
- **Carbon Footprint Tracking** - Environmental compliance reporting
- **Business Intelligence** - Power usage analytics and optimization

### Best Practices for Enterprise Power Management

1. **Energy Efficiency Strategy**
   - Implement tiered power profiles based on usage patterns
   - Monitor and optimize energy consumption across the fleet
   - Align with corporate sustainability initiatives
   - Track cost savings from power management policies

2. **Security Considerations**
   - Enable FileVault key destruction on standby for sensitive data
   - Configure appropriate hibernation modes for security
   - Implement secure sleep modes for unattended devices
   - Balance security requirements with operational needs

3. **Performance Optimization**
   - Use high-performance profiles for resource-intensive tasks
   - Implement presentation modes for meeting scenarios
   - Configure thermal management for sustained workloads
   - Monitor battery health and optimize charging patterns

4. **Compliance and Reporting**
   - Generate energy usage reports for regulatory compliance
   - Track power management policy adherence
   - Document power optimization initiatives
   - Monitor environmental impact metrics

Remember to test power management configurations thoroughly in your environment before fleet-wide deployment to ensure they meet your organization's operational, security, and energy efficiency requirements. 

Shutdown and Reboot Management for macOS

Implement enterprise-grade shutdown and reboot management across your Roundfleet deployment with automated maintenance scheduling, graceful shutdown procedures, security validation, and comprehensive fleet-wide power management. This tutorial provides solutions for maintaining operational continuity while ensuring secure and efficient system power operations.

Understanding macOS Shutdown and Reboot Management

macOS provides several power control mechanisms and tools:

  • shutdown - Primary command-line tool for system power control
  • reboot - Alternative reboot command
  • halt - System halt without power off
  • Apple Menu - GUI shutdown interface
  • Power Button - Hardware-level power control

Basic Shutdown Operations

Instant Shutdown

#!/bin/bash

# Shutdown Mac instantly
sudo shutdown -h now

Scheduled Reboot

#!/bin/bash

# Reboot Mac in 5 minutes
sudo shutdown -r +5

Shutdown at Specific Time

#!/bin/bash

# Shutdown at specific time: October 18, 16:11:00 2022
sudo shutdown -h 2210181611

Reboot with Warning Message

#!/bin/bash

# Reboot with warning message
sudo shutdown -r +2 "the system will restart in 2 minutes"

Display Sleep and Lock

#!/bin/bash

# Lock device and turn off display
sudo shutdown -s

Enterprise Shutdown and Reboot Management System

Comprehensive Power Management Tool

#!/bin/bash

# Roundfleet Enterprise Shutdown and Reboot Management Tool
# Advanced power control and maintenance scheduling

# 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"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$SCHEDULES_DIR" "$(dirname "$AUDIT_LOG")"

# Default shutdown management policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Enterprise Shutdown and Reboot Management Policy
# Version: 2.0

# Shutdown Policy Enforcement
ENFORCE_SHUTDOWN_POLICIES=true
GRACEFUL_SHUTDOWN_ENABLED=true
SAVE_WORK_BEFORE_SHUTDOWN=true
FORCE_SHUTDOWN_TIMEOUT=300
WARNING_NOTIFICATION_TIME=300

# Security and Safety
REQUIRE_ADMIN_APPROVAL=false
VALIDATE_USER_SESSIONS=true
CHECK_RUNNING_PROCESSES=true
BACKUP_BEFORE_SHUTDOWN=false
ENCRYPTION_KEY_PROTECTION=true

# Maintenance Windows
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

# Business Hours Protection
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
PREVENT_SHUTDOWN_BUSINESS_HOURS=true
EMERGENCY_SHUTDOWN_OVERRIDE=true
CRITICAL_SYSTEM_PROTECTION=true

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

# Automatic Scheduling
AUTO_REBOOT_ENABLED=true
AUTO_REBOOT_FREQUENCY="weekly"
AUTO_REBOOT_DAY="sunday"
AUTO_REBOOT_TIME="03:00"
PATCH_REBOOT_REQUIRED=true

# Compliance and Audit
AUDIT_ALL_POWER_OPERATIONS=true
COMPLIANCE_REPORTING=true
UPTIME_TRACKING=true
MAINTENANCE_DOCUMENTATION=true
CHANGE_MANAGEMENT_INTEGRATION=true

# Recovery and Failsafe
AUTOMATIC_RECOVERY_ENABLED=true
BOOT_VALIDATION_REQUIRED=true
ROLLBACK_ON_FAILURE=true
EMERGENCY_CONTACT_INFO="IT Support: +1-555-0123"
EOF

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

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

# Audit logging function
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"
}

# Check if shutdown is allowed
check_shutdown_allowed() {
    local operation="$1"
    local force="${2:-false}"
    
    echo "=== Validating Shutdown Authorization ==="
    
    # Check business hours protection
    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 "❌ Shutdown blocked: Currently in business hours ($BUSINESS_HOURS_START - $BUSINESS_HOURS_END)"
            log_action "SHUTDOWN BLOCKED: Business hours protection active"
            audit_log "SHUTDOWN_BLOCKED" "BUSINESS_HOURS" "Operation: $operation Time: $(date '+%H:%M')"
            return 1
        fi
    fi
    
    # Check for active user sessions
    if [[ "$VALIDATE_USER_SESSIONS" == "true" ]]; then
        local active_users
        active_users=$(who | wc -l)
        
        if [[ $active_users -gt 0 && "$force" != "true" ]]; then
            echo "⚠️  Warning: $active_users active user session(s) detected"
            log_action "WARNING: Active user sessions during $operation"
            
            if [[ "$GRACEFUL_SHUTDOWN_ENABLED" != "true" ]]; then
                echo "❌ Shutdown blocked: Active users and graceful shutdown disabled"
                audit_log "SHUTDOWN_BLOCKED" "ACTIVE_USERS" "Users: $active_users Operation: $operation"
                return 1
            fi
        fi
    fi
    
    # Check for critical running processes
    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 "⚠️  Critical process running: $process"
                
                if [[ "$force" != "true" ]]; then
                    echo "❌ Shutdown blocked: Critical process $process is running"
                    log_action "SHUTDOWN BLOCKED: Critical process $process running"
                    audit_log "SHUTDOWN_BLOCKED" "CRITICAL_PROCESS" "Process: $process Operation: $operation"
                    return 1
                else
                    echo "🚨 Force shutdown: Will terminate critical process $process"
                    log_action "FORCE SHUTDOWN: Terminating critical process $process"
                fi
            fi
        done
    fi
    
    # Admin approval check
    if [[ "$REQUIRE_ADMIN_APPROVAL" == "true" && "$force" != "true" ]]; then
        echo "❌ Shutdown blocked: Admin approval required"
        log_action "SHUTDOWN BLOCKED: Admin approval required"
        audit_log "SHUTDOWN_BLOCKED" "ADMIN_APPROVAL" "Operation: $operation"
        return 1
    fi
    
    echo "✅ Shutdown authorization validated"
    audit_log "SHUTDOWN_AUTHORIZED" "APPROVED" "Operation: $operation"
    return 0
}

# Send notification before shutdown
send_shutdown_notification() {
    local operation="$1"
    local delay_minutes="$2"
    local message="$3"
    
    echo "=== Sending Shutdown Notifications ==="
    
    local notification_title="Roundfleet System $operation Notification"
    local notification_message="${message:-System $operation scheduled in $delay_minutes minutes}"
    
    # User notification
    if [[ "$USER_NOTIFICATION_ENABLED" == "true" ]]; then
        # Display notification to all logged-in users
        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 sent to user: $user"
            fi
        done
        
        # Terminal notification
        wall "$notification_title: $notification_message" 2>/dev/null || true
    fi
    
    # Admin notification
    if [[ "$ADMIN_NOTIFICATION_ENABLED" == "true" ]]; then
        log_action "ADMIN NOTIFICATION: $notification_title - $notification_message"
    fi
    
    # Slack notification
    if [[ -n "$SLACK_WEBHOOK_URL" ]]; then
        local slack_payload="{\"text\":\"🖥️ *$(hostname)*: $notification_title\\n$notification_message\"}"
        curl -s -X POST -H 'Content-type: application/json' --data "$slack_payload" "$SLACK_WEBHOOK_URL" >/dev/null 2>&1 || true
        echo "📢 Slack notification sent"
    fi
    
    log_action "Shutdown notifications sent for $operation (delay: $delay_minutes minutes)"
}

# Graceful shutdown with user session handling
graceful_shutdown() {
    local operation="$1"
    local delay_minutes="$2"
    local message="$3"
    
    echo "=== Initiating Graceful $operation ==="
    
    # Send initial notification
    send_shutdown_notification "$operation" "$delay_minutes" "$message"
    
    # Save user work if enabled
    if [[ "$SAVE_WORK_BEFORE_SHUTDOWN" == "true" ]]; then
        echo "💾 Attempting to save user work..."
        
        # Try to save work in common applications
        local save_commands=(
            "osascript -e 'tell application \"System Events\" to keystroke \"s\" using command down'"
            "pkill -USR1 TextEdit"  # Signal TextEdit to save
        )
        
        for cmd in "${save_commands[@]}"; do
            eval "$cmd" 2>/dev/null || true
        done
        
        log_action "User work save attempted before $operation"
    fi
    
    # Create backup if enabled
    if [[ "$BACKUP_BEFORE_SHUTDOWN" == "true" ]]; then
        echo "💾 Creating system backup before $operation..."
        create_pre_shutdown_backup
    fi
    
    # FileVault key protection
    if [[ "$ENCRYPTION_KEY_PROTECTION" == "true" ]]; then
        echo "🔐 Ensuring FileVault key security..."
        sudo pmset -a destroyfvkeyonstandby 1 2>/dev/null || true
        log_action "FileVault key protection enabled before $operation"
    fi
    
    # Wait for delay period with countdown
    if [[ $delay_minutes -gt 0 ]]; then
        echo "⏱️  Waiting $delay_minutes minutes before $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
            # Send reminder notifications at specific intervals
            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" "Final warning: System $operation in $remaining_minutes minute(s)"
                    else
                        send_shutdown_notification "$operation" "0" "Final warning: System $operation in $remaining_seconds seconds"
                    fi
                    break
                fi
            done
            
            sleep 1
            remaining_seconds=$((remaining_seconds - 1))
        done
    fi
    
    echo "✅ Graceful $operation preparation completed"
    log_action "Graceful $operation preparation completed"
}

# Create pre-shutdown backup
create_pre_shutdown_backup() {
    echo "=== Creating Pre-Shutdown Backup ==="
    
    local backup_dir="/Library/Roundfleet/Backups"
    local backup_file="$backup_dir/pre_shutdown_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    mkdir -p "$backup_dir"
    
    # Backup critical system configurations
    local backup_paths=(
        "/etc"
        "/Library/Preferences"
        "/System/Library/LaunchDaemons"
        "/Library/LaunchDaemons"
        "/usr/local/etc"
    )
    
    echo "Creating backup of critical system files..."
    tar -czf "$backup_file" "${backup_paths[@]}" 2>/dev/null || true
    
    if [[ -f "$backup_file" ]]; then
        echo "✅ Pre-shutdown backup created: $backup_file"
        log_action "Pre-shutdown backup created: $backup_file"
    else
        echo "⚠️  Pre-shutdown backup creation failed"
        log_action "WARNING: Pre-shutdown backup creation failed"
    fi
}

# Enterprise shutdown with comprehensive validation
enterprise_shutdown() {
    local delay="${1:-now}"
    local message="$2"
    local force="${3:-false}"
    
    echo "=== Enterprise Shutdown Initiated ==="
    
    # Validate shutdown authorization
    if ! check_shutdown_allowed "shutdown" "$force"; then
        return 1
    fi
    
    # Parse delay
    local delay_minutes=0
    if [[ "$delay" != "now" ]]; then
        if [[ "$delay" =~ ^\+([0-9]+)$ ]]; then
            delay_minutes="${BASH_REMATCH[1]}"
        else
            echo "❌ Invalid delay format. Use 'now' or '+minutes'"
            return 1
        fi
    fi
    
    # Graceful shutdown if enabled
    if [[ "$GRACEFUL_SHUTDOWN_ENABLED" == "true" ]]; then
        graceful_shutdown "shutdown" "$delay_minutes" "$message"
    fi
    
    # Log shutdown action
    log_action "ENTERPRISE SHUTDOWN: Executing shutdown with delay: $delay"
    audit_log "SHUTDOWN" "INITIATED" "Delay: $delay Message: ${message:-None} Force: $force"
    
    # Execute shutdown
    if [[ "$delay" == "now" ]]; then
        echo "🔌 Executing immediate shutdown..."
        sudo shutdown -h now "$message"
    else
        echo "🔌 Scheduling shutdown in $delay_minutes minutes..."
        sudo shutdown -h +"$delay_minutes" "$message"
    fi
    
    audit_log "SHUTDOWN" "EXECUTED" "Command completed successfully"
    return 0
}

# Enterprise reboot with comprehensive validation
enterprise_reboot() {
    local delay="${1:-now}"
    local message="$2"
    local force="${3:-false}"
    
    echo "=== Enterprise Reboot Initiated ==="
    
    # Validate reboot authorization
    if ! check_shutdown_allowed "reboot" "$force"; then
        return 1
    fi
    
    # Parse delay
    local delay_minutes=0
    if [[ "$delay" != "now" ]]; then
        if [[ "$delay" =~ ^\+([0-9]+)$ ]]; then
            delay_minutes="${BASH_REMATCH[1]}"
        else
            echo "❌ Invalid delay format. Use 'now' or '+minutes'"
            return 1
        fi
    fi
    
    # Graceful reboot if enabled
    if [[ "$GRACEFUL_SHUTDOWN_ENABLED" == "true" ]]; then
        graceful_shutdown "reboot" "$delay_minutes" "$message"
    fi
    
    # Log reboot action
    log_action "ENTERPRISE REBOOT: Executing reboot with delay: $delay"
    audit_log "REBOOT" "INITIATED" "Delay: $delay Message: ${message:-None} Force: $force"
    
    # Execute reboot
    if [[ "$delay" == "now" ]]; then
        echo "🔄 Executing immediate reboot..."
        sudo shutdown -r now "$message"
    else
        echo "🔄 Scheduling reboot in $delay_minutes minutes..."
        sudo shutdown -r +"$delay_minutes" "$message"
    fi
    
    audit_log "REBOOT" "EXECUTED" "Command completed successfully"
    return 0
}

# Schedule maintenance reboot
schedule_maintenance_reboot() {
    local schedule_time="$1"
    local reason="$2"
    
    echo "=== Scheduling Maintenance Reboot ==="
    
    if [[ -z "$schedule_time" ]]; then
        echo "❌ Schedule time required (format: YYMMDDHHMM)"
        return 1
    fi
    
    # Validate schedule time format
    if [[ ! "$schedule_time" =~ ^[0-9]{10}$ ]]; then
        echo "❌ Invalid schedule time format. Use YYMMDDHHMM"
        return 1
    fi
    
    # Check if scheduled time is in maintenance window
    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 "⚠️  Warning: Scheduled time outside maintenance window ($MAINTENANCE_START_TIME - $MAINTENANCE_END_TIME)"
        fi
    fi
    
    # Schedule the reboot
    local message="Scheduled maintenance reboot: ${reason:-System maintenance}"
    
    log_action "MAINTENANCE REBOOT SCHEDULED: Time: $schedule_time Reason: ${reason:-System maintenance}"
    audit_log "MAINTENANCE_SCHEDULED" "CREATED" "Time: $schedule_time Reason: ${reason:-System maintenance}"
    
    echo "🗓️  Scheduling maintenance reboot..."
    sudo shutdown -r "$schedule_time" "$message"
    
    echo "✅ Maintenance reboot scheduled for $(date -j -f "%Y%m%d%H%M" "20$schedule_time" "+%Y-%m-%d %H:%M")"
    
    # Create maintenance record
    local maintenance_file="$SCHEDULES_DIR/maintenance_$(date +%Y%m%d_%H%M%S).json"
    cat > "$maintenance_file" << EOF
{
  "type": "maintenance_reboot",
  "scheduled_time": "$schedule_time",
  "reason": "${reason:-System maintenance}",
  "created_by": "$(whoami)",
  "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device": "$(hostname)"
}
EOF
    
    log_action "Maintenance record created: $maintenance_file"
    return 0
}

# Cancel scheduled shutdown/reboot
cancel_scheduled_operation() {
    echo "=== Cancelling Scheduled Operations ==="
    
    # Get list of scheduled operations
    local scheduled_ops
    scheduled_ops=$(ps aux | grep "shutdown" | grep -v grep | wc -l)
    
    if [[ $scheduled_ops -eq 0 ]]; then
        echo "ℹ️  No scheduled shutdown/reboot operations found"
        return 0
    fi
    
    # Cancel shutdown operations
    if sudo pkill -f "shutdown"; then
        echo "✅ Scheduled shutdown/reboot operations cancelled"
        log_action "Scheduled shutdown/reboot operations cancelled"
        audit_log "SCHEDULE_CANCELLED" "SUCCESS" "Operations cancelled by $(whoami)"
        
        # Notify users of cancellation
        send_shutdown_notification "cancellation" "0" "Scheduled system operation has been cancelled"
    else
        echo "❌ Failed to cancel scheduled operations"
        log_action "FAILED: Could not cancel scheduled operations"
        audit_log "SCHEDULE_CANCELLED" "FAILED" "Cancellation attempt by $(whoami)"
        return 1
    fi
    
    return 0
}

# Emergency shutdown (bypasses all checks)
emergency_shutdown() {
    local reason="$1"
    
    echo "🚨 EMERGENCY SHUTDOWN INITIATED 🚨"
    
    if [[ -z "$reason" ]]; then
        echo "❌ Emergency reason required"
        return 1
    fi
    
    log_action "EMERGENCY SHUTDOWN: Reason: $reason"
    audit_log "EMERGENCY_SHUTDOWN" "INITIATED" "Reason: $reason User: $(whoami)"
    
    # Send emergency notification
    send_shutdown_notification "EMERGENCY SHUTDOWN" "0" "EMERGENCY: System shutdown initiated - $reason"
    
    # Emergency contact notification
    if [[ -n "$EMERGENCY_CONTACT_INFO" ]]; then
        echo "📞 Emergency contact: $EMERGENCY_CONTACT_INFO"
        log_action "Emergency contact info: $EMERGENCY_CONTACT_INFO"
    fi
    
    # Force immediate shutdown
    echo "🔌 Executing emergency shutdown (force)..."
    sudo shutdown -h now "EMERGENCY SHUTDOWN: $reason"
    
    audit_log "EMERGENCY_SHUTDOWN" "EXECUTED" "Immediate shutdown completed"
}

# Check system status for shutdown readiness
check_system_status() {
    echo "=== System Status Check ==="
    
    local status_issues=()
    local status_warnings=()
    
    # Check uptime
    local uptime_seconds
    uptime_seconds=$(uptime | awk '{print $3}' | cut -d',' -f1)
    echo "System Uptime: $uptime_seconds"
    
    # Check load average
    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+=("High system load: $load_average")
    fi
    
    # Check disk space
    local disk_usage
    disk_usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
    if [[ $disk_usage -gt 90 ]]; then
        status_warnings+=("Low disk space: ${disk_usage}% used")
    fi
    
    # Check memory usage
    local memory_pressure
    memory_pressure=$(memory_pressure 2>/dev/null | grep "System-wide memory free percentage" | awk '{print $5}' | sed 's/%//' || echo "unknown")
    if [[ "$memory_pressure" != "unknown" && $memory_pressure -lt 10 ]]; then
        status_warnings+=("Low memory: ${memory_pressure}% free")
    fi
    
    # Check for pending updates
    if softwareupdate -l 2>/dev/null | grep -q "Software Update found"; then
        status_warnings+=("Pending software updates available")
    fi
    
    # Check network connectivity
    if ! ping -c 1 8.8.8.8 >/dev/null 2>&1; then
        status_warnings+=("Network connectivity issue detected")
    fi
    
    # Report status
    if [[ ${#status_issues[@]} -eq 0 && ${#status_warnings[@]} -eq 0 ]]; then
        echo "✅ System status: Ready for shutdown/reboot"
        return 0
    else
        if [[ ${#status_issues[@]} -gt 0 ]]; then
            echo "❌ System status issues:"
            printf '  - %s\n' "${status_issues[@]}"
        fi
        
        if [[ ${#status_warnings[@]} -gt 0 ]]; then
            echo "⚠️  System status warnings:"
            printf '  - %s\n' "${status_warnings[@]}"
        fi
        
        return 1
    fi
}

# Generate shutdown management report
generate_shutdown_report() {
    local report_file="$SCHEDULES_DIR/shutdown_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Shutdown Management Report ==="
    
    # Get system information
    local last_boot
    last_boot=$(who -b | awk '{print $3 " " $4}')
    
    local uptime_info
    uptime_info=$(uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}')
    
    # Count recent operations from audit log
    local recent_shutdowns=0
    local recent_reboots=0
    local recent_cancellations=0
    
    if [[ -f "$AUDIT_LOG" ]]; then
        recent_shutdowns=$(grep -c "ACTION:SHUTDOWN" "$AUDIT_LOG" 2>/dev/null || echo 0)
        recent_reboots=$(grep -c "ACTION:REBOOT" "$AUDIT_LOG" 2>/dev/null || echo 0)
        recent_cancellations=$(grep -c "ACTION:SCHEDULE_CANCELLED" "$AUDIT_LOG" 2>/dev/null || echo 0)
    fi
    
    # Check for scheduled operations
    local scheduled_operations=0
    scheduled_operations=$(ps aux | grep -c "shutdown" | grep -v grep || echo 0)
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "shutdown_management",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "os_version": "$(sw_vers -productVersion)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
  },
  "system_status": {
    "last_boot": "$last_boot",
    "uptime": "$uptime_info",
    "scheduled_operations": $scheduled_operations,
    "system_ready": $(check_system_status >/dev/null 2>&1 && echo true || echo false)
  },
  "operation_history": {
    "total_shutdowns": $recent_shutdowns,
    "total_reboots": $recent_reboots,
    "cancelled_operations": $recent_cancellations
  },
  "policy_configuration": {
    "graceful_shutdown_enabled": $GRACEFUL_SHUTDOWN_ENABLED,
    "business_hours_protection": $PREVENT_SHUTDOWN_BUSINESS_HOURS,
    "maintenance_window_enabled": $MAINTENANCE_WINDOW_ENABLED,
    "auto_reboot_enabled": $AUTO_REBOOT_ENABLED
  },
  "compliance_status": {
    "audit_enabled": $AUDIT_ALL_POWER_OPERATIONS,
    "user_notification_enabled": $USER_NOTIFICATION_ENABLED,
    "backup_before_shutdown": $BACKUP_BEFORE_SHUTDOWN
  }
}
EOF
    
    echo "Shutdown management report saved to: $report_file"
    log_action "Shutdown management report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Shutdown Management Tool Started ==="
    
    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
            ;;
        "report")
            generate_shutdown_report
            ;;
        *)
            echo "Roundfleet Enterprise Shutdown and Reboot Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  shutdown [delay] [message] [force]  - Shutdown system with optional delay"
            echo "  reboot [delay] [message] [force]    - Reboot system with optional delay"
            echo "  schedule [time] [reason]            - Schedule maintenance reboot (YYMMDDHHMM)"
            echo "  cancel                              - Cancel scheduled operations"
            echo "  emergency [reason]                  - Emergency shutdown (bypasses checks)"
            echo "  status                              - Check system status for shutdown readiness"
            echo "  report                              - Generate shutdown management report"
            echo ""
            echo "Delay Formats:"
            echo "  now                                 - Immediate operation"
            echo "  +minutes                            - Delay in minutes (e.g., +5)"
            echo ""
            echo "Examples:"
            echo "  $0 shutdown now                     - Immediate shutdown"
            echo "  $0 reboot +10 \"System maintenance\" - Reboot in 10 minutes with message"
            echo "  $0 schedule 2501020300 \"Patch Tuesday\" - Schedule reboot Jan 2, 3:00 AM"
            echo "  $0 emergency \"Security incident\"   - Emergency shutdown"
            ;;
    esac
    
    log_action "=== Shutdown management operation completed ==="
}

# Execute main function
main "$@"

## Advanced Shutdown Management Features

### Automated Maintenance Scheduling

```bash
#!/bin/bash

# Automated maintenance window management
setup_maintenance_automation() {
    echo "=== Setting Up Maintenance Automation ==="
    
    # Create maintenance automation script
    local automation_script="/Library/Roundfleet/Scripts/maintenance_automation.sh"
    mkdir -p "$(dirname "$automation_script")"
    
    cat > "$automation_script" << 'EOF'
#!/bin/bash

# Check if we're in maintenance window
current_time=$(date +%H%M)
current_day=$(date +%u)  # 1=Monday, 7=Sunday

maintenance_start=$(echo "$MAINTENANCE_START_TIME" | tr -d ':')
maintenance_end=$(echo "$MAINTENANCE_END_TIME" | tr -d ':')

# Check if current time is in maintenance window
if [[ $current_time -ge $maintenance_start && $current_time -le $maintenance_end ]]; then
    # Check if it's a maintenance day
    if echo "$MAINTENANCE_DAYS" | grep -q "$(date +%a | cut -c1)"; then
        # Check if reboot is needed
        if [[ "$AUTO_REBOOT_ENABLED" == "true" ]]; then
            # Check uptime - reboot if system has been up more than 7 days
            uptime_days=$(uptime | awk '{print $3}' | cut -d',' -f1)
            if [[ $uptime_days -gt 7 ]]; then
                echo "System uptime exceeds 7 days - initiating maintenance reboot"
                /Library/Roundfleet/Scripts/shutdown_management.sh reboot +5 "Automated maintenance reboot"
            fi
        fi
    fi
fi
EOF
    
    chmod +x "$automation_script"
    
    # Create launch daemon for maintenance automation
    local launch_daemon="/Library/LaunchDaemons/com.roundfleet.maintenance.plist"
    
    cat > "$launch_daemon" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.roundfleet.maintenance</string>
    <key>ProgramArguments</key>
    <array>
        <string>$automation_script</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>2</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    # Load the launch daemon
    sudo launchctl load "$launch_daemon" 2>/dev/null
    
    echo "✅ Maintenance automation configured"
    log_action "Maintenance automation setup completed"
}

# Patch management integration
check_patch_reboot_required() {
    echo "=== Checking Patch Reboot Requirements ==="
    
    # Check for pending updates requiring reboot
    local pending_updates
    pending_updates=$(softwareupdate -l 2>/dev/null | grep -i "restart\|reboot" | wc -l)
    
    if [[ $pending_updates -gt 0 ]]; then
        echo "⚠️  $pending_updates update(s) require system reboot"
        log_action "Patch reboot required: $pending_updates updates pending"
        
        if [[ "$PATCH_REBOOT_REQUIRED" == "true" ]]; then
            echo "🔄 Scheduling patch reboot for next maintenance window"
            
            # Calculate next maintenance window
            local next_maintenance
            next_maintenance=$(date -v+1d "+%y%m%d${MAINTENANCE_START_TIME/:/}")
            
            schedule_maintenance_reboot "$next_maintenance" "Patch installation reboot"
        fi
        
        return 1
    else
        echo "✅ No patches requiring reboot"
        return 0
    fi
}

# Disaster recovery shutdown
disaster_recovery_shutdown() {
    local disaster_type="$1"
    local severity="$2"
    
    echo "🚨 DISASTER RECOVERY SHUTDOWN 🚨"
    echo "Disaster Type: $disaster_type"
    echo "Severity: $severity"
    
    log_action "DISASTER RECOVERY: Type: $disaster_type Severity: $severity"
    audit_log "DISASTER_RECOVERY" "INITIATED" "Type: $disaster_type Severity: $severity"
    
    # Send emergency notifications
    send_shutdown_notification "DISASTER RECOVERY SHUTDOWN" "0" "Emergency shutdown due to $disaster_type ($severity)"
    
    # Create disaster recovery record
    local disaster_file="$SCHEDULES_DIR/disaster_recovery_$(date +%Y%m%d_%H%M%S).json"
    cat > "$disaster_file" << EOF
{
  "type": "disaster_recovery",
  "disaster_type": "$disaster_type",
  "severity": "$severity",
  "initiated_by": "$(whoami)",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device": "$(hostname)",
  "emergency_contact": "$EMERGENCY_CONTACT_INFO"
}
EOF
    
    # Execute immediate shutdown
    sudo shutdown -h now "DISASTER RECOVERY: $disaster_type ($severity)"
}

## Important Configuration Notes

### macOS Shutdown Command Options

- **`-h`** - Halt the system (shutdown)
- **`-r`** - Restart the system (reboot)
- **`-s`** - Sleep the system (display off + lock)
- **Time formats** - `now`, `+minutes`, `YYMMDDHHMM`
- **Warning messages** - Additional text displayed to users

### Enterprise Integration Points

- **Change Management Systems** - Integration with ITSM platforms
- **Monitoring Systems** - Real-time shutdown event tracking
- **Backup Solutions** - Pre-shutdown backup automation
- **Security Frameworks** - Compliance with shutdown policies

### Best Practices for Enterprise Shutdown Management

1. **Operational Continuity**
   - Implement graceful shutdown procedures with user notifications
   - Validate system readiness before shutdown operations
   - Maintain emergency override capabilities for critical situations
   - Schedule maintenance operations during designated windows

2. **Security and Compliance**
   - Enable comprehensive audit logging for all power operations
   - Implement FileVault key protection during shutdown
   - Validate user sessions and running processes before shutdown
   - Maintain compliance with regulatory shutdown requirements

3. **Change Management**
   - Require approval for non-scheduled shutdown operations
   - Document all maintenance-related shutdowns
   - Integrate with ITSM platforms for change tracking
   - Maintain emergency contact information for critical situations

4. **User Experience**
   - Provide adequate warning before shutdown operations
   - Attempt to save user work before system shutdown
   - Send notifications through multiple channels (GUI, email, Slack)
   - Allow cancellation of scheduled operations when appropriate

### Troubleshooting Common Issues

- **Permission errors** - Ensure admin privileges for shutdown commands
- **Scheduled operation conflicts** - Check for existing scheduled shutdowns
- **Network notification failures** - Verify webhook URLs and network connectivity
- **Backup failures** - Check disk space and backup destination availability
- **Maintenance window violations** - Review business hours and maintenance schedules

Remember to test shutdown procedures thoroughly in a controlled environment before implementing across your entire Roundfleet to ensure business continuity and data protection. 

Sharing User Management on macOS

Manage sharing-only user accounts across your Roundfleet devices using advanced dscl commands. This tutorial covers user creation, security policies, bulk deployment, and enterprise user lifecycle management.

Understanding macOS User Management

macOS uses Directory Service command line utility (dscl) for user management:

  • dscl - Directory Service command line utility
  • Local Directory - /var/db/dslocal/nodes/Default
  • User Records - Stored in /Users/ path
  • Sharing-only Users - Limited access accounts for file sharing

Basic Sharing User Creation

Simple Sharing User

#!/bin/bash

# Create a basic sharing-only user account
USERNAME="SharingUser"
DISPLAY_NAME="Sharing Account"
PASSWORD="SecurePass123"
USER_ID="550"

# Create the user
sudo dscl . create /Users/"$USERNAME"

# Set display name
sudo dscl . create /Users/"$USERNAME" RealName "$DISPLAY_NAME"

# Set password
sudo dscl . passwd /Users/"$USERNAME" "$PASSWORD"

# Set unique ID
sudo dscl . create /Users/"$USERNAME" UniqueID "$USER_ID"

# Set group ID (staff group)
sudo dscl . create /Users/"$USERNAME" PrimaryGroupID 20

# Deny shell access
sudo dscl . create /Users/"$USERNAME" UserShell /usr/bin/false

# No home directory
sudo dscl . create /Users/"$USERNAME" NFSHomeDirectory /dev/null

echo "Sharing user '$USERNAME' created successfully"

Enhanced Sharing User with Options

#!/bin/bash

# Enhanced sharing user creation with additional options
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 "Creating sharing user: $username"
    
    # Create user
    sudo dscl . create /Users/"$username"
    
    # Set display name
    sudo dscl . create /Users/"$username" RealName "$display_name"
    
    # Set password
    sudo dscl . passwd /Users/"$username" "$password"
    
    # Set password hint (optional)
    if [[ -n "$hint" ]]; then
        sudo dscl . create /Users/"$username" hint "$hint"
    fi
    
    # Set profile picture (optional)
    if [[ -n "$picture_path" && -f "$picture_path" ]]; then
        sudo dscl . create /Users/"$username" picture "$picture_path"
    fi
    
    # Set unique ID
    sudo dscl . create /Users/"$username" UniqueID "$user_id"
    
    # Set group ID
    sudo dscl . create /Users/"$username" PrimaryGroupID 20
    
    # Deny shell access
    sudo dscl . create /Users/"$username" UserShell /usr/bin/false
    
    # No home directory
    sudo dscl . create /Users/"$username" NFSHomeDirectory /dev/null
    
    echo "✅ Sharing user '$username' created successfully"
    return 0
}

# Usage examples
create_sharing_user "FileShare" "File Sharing Account" "FilePass123" "File access only" "" "551"
create_sharing_user "GuestAccess" "Guest User" "GuestPass456" "Temporary access" "/System/Library/User Pictures/Animals/Butterfly.tif" "552"

Enterprise User Categories

User Type Classifications

#!/bin/bash

# Enterprise user categories with specific configurations
declare -A USER_CATEGORIES=(
    ["sharing_standard"]="Standard file sharing access"
    ["sharing_secure"]="High-security sharing with restrictions"
    ["guest_temporary"]="Temporary guest access with expiration"
    ["service_account"]="Service accounts for applications"
    ["departmental_shared"]="Department-specific shared accounts"
    ["external_partner"]="External partner limited access"
    ["kiosk_public"]="Public kiosk access accounts"
)

# Security policies for each category
declare -A SECURITY_POLICIES=(
    ["sharing_standard"]="password_policy:standard,audit_level:basic,session_timeout:8h"
    ["sharing_secure"]="password_policy:strong,audit_level:comprehensive,session_timeout:2h,mfa_required:true"
    ["guest_temporary"]="password_policy:basic,audit_level:full,session_timeout:1h,auto_expire:24h"
    ["service_account"]="password_policy:service,audit_level:system,no_interactive:true"
    ["departmental_shared"]="password_policy:department,audit_level:department,group_restrictions:true"
    ["external_partner"]="password_policy:external,audit_level:full,network_restrictions:true"
    ["kiosk_public"]="password_policy:public,audit_level:minimal,session_timeout:30m,reset_on_logout:true"
)

# Access control definitions
declare -A ACCESS_CONTROLS=(
    ["sharing_standard"]="file_sharing:read_write,print_access:yes,network_access:local"
    ["sharing_secure"]="file_sharing:read_only,print_access:restricted,network_access:vpn_only"
    ["guest_temporary"]="file_sharing:guest_folder,print_access:no,network_access:guest_wifi"
    ["service_account"]="file_sharing:service_dirs,print_access:no,network_access:service_ports"
    ["departmental_shared"]="file_sharing:department_dirs,print_access:department,network_access:department_vlan"
    ["external_partner"]="file_sharing:partner_dirs,print_access:no,network_access:partner_dmz"
    ["kiosk_public"]="file_sharing:public_docs,print_access:public,network_access:public_wifi"
)

print_user_categories() {
    echo "=== Available User Categories ==="
    for category in "${!USER_CATEGORIES[@]}"; do
        echo "Category: $category"
        echo "  Description: ${USER_CATEGORIES[$category]}"
        echo "  Security: ${SECURITY_POLICIES[$category]}"
        echo "  Access: ${ACCESS_CONTROLS[$category]}"
        echo ""
    done
}

# Display available categories
print_user_categories

User Management Policies

Password Policy Engine

#!/bin/bash

# Password policy definitions for different user types
generate_password_policy() {
    local policy_type="$1"
    
    case "$policy_type" in
        "standard")
            echo "min_length:8,complexity:medium,expiry:90d,history:5"
            ;;
        "strong")
            echo "min_length:12,complexity:high,expiry:60d,history:10,special_chars:required"
            ;;
        "basic")
            echo "min_length:6,complexity:low,expiry:never,history:3"
            ;;
        "service")
            echo "min_length:16,complexity:high,expiry:180d,history:20,machine_generated:true"
            ;;
        "department")
            echo "min_length:10,complexity:medium,expiry:120d,history:8,department_prefix:required"
            ;;
        "external")
            echo "min_length:14,complexity:high,expiry:30d,history:15,external_validation:required"
            ;;
        "public")
            echo "min_length:4,complexity:none,expiry:daily,history:1,auto_reset:true"
            ;;
        *)
            echo "min_length:8,complexity:medium,expiry:90d,history:5"
            ;;
    esac
}

# Generate secure password based on policy
generate_secure_password() {
    local policy="$1"
    local length
    local complexity
    
    # Parse policy
    length=$(echo "$policy" | grep -o 'min_length:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexity:[a-z]*' | cut -d: -f2)
    
    case "$complexity" in
        "high")
            # High complexity: uppercase, lowercase, numbers, special characters
            openssl rand -base64 $((length * 2)) | tr -d "=+/" | cut -c1-"$length" | sed 's/./&@1A/4'
            ;;
        "medium")
            # Medium complexity: uppercase, lowercase, numbers
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
        "low")
            # Low complexity: alphanumeric
            openssl rand -hex "$((length/2))" | cut -c1-"$length"
            ;;
        *)
            # Default medium complexity
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
    esac
}

# Validate password against policy
validate_password() {
    local password="$1"
    local policy="$2"
    local min_length complexity
    
    min_length=$(echo "$policy" | grep -o 'min_length:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexity:[a-z]*' | cut -d: -f2)
    
    # Check length
    if [[ ${#password} -lt $min_length ]]; then
        echo "❌ Password too short (minimum $min_length characters)"
        return 1
    fi
    
    # Check complexity
    case "$complexity" in
        "high")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] && "$password" =~ [^A-Za-z0-9] ]]; then
                echo "❌ Password must contain uppercase, lowercase, numbers, and special characters"
                return 1
            fi
            ;;
        "medium")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] ]]; then
                echo "❌ Password must contain uppercase, lowercase, and numbers"
                return 1
            fi
            ;;
    esac
    
    echo "✅ Password meets policy requirements"
    return 0
}

Enterprise User Deployment Profiles

Deployment Configuration Templates

#!/bin/bash

# Enterprise deployment profiles for different organizational needs
declare -A DEPLOYMENT_PROFILES=(
    ["corporate_standard"]="Standard corporate deployment with basic security"
    ["high_security_finance"]="High-security deployment for financial departments"
    ["guest_access_lobby"]="Guest access deployment for lobby/public areas"
    ["partner_collaboration"]="External partner collaboration deployment"
    ["kiosk_public_library"]="Public kiosk deployment for libraries/public spaces"
    ["research_development"]="Research and development team deployment"
    ["executive_secure"]="Executive-level secure deployment"
)

# Profile-specific configurations
get_deployment_config() {
    local profile="$1"
    
    case "$profile" in
        "corporate_standard")
            cat << EOF
{
    "user_category": "sharing_standard",
    "password_policy": "standard",
    "access_level": "department_files",
    "session_timeout": "8h",
    "audit_level": "basic",
    "group_membership": ["staff", "file_sharing"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false
    },
    "monitoring": {
        "login_tracking": true,
        "file_access_log": true,
        "failed_attempts": 5
    }
}
EOF
            ;;
        "high_security_finance")
            cat << EOF
{
    "user_category": "sharing_secure",
    "password_policy": "strong",
    "access_level": "finance_restricted",
    "session_timeout": "2h",
    "audit_level": "comprehensive",
    "group_membership": ["finance", "secure_sharing"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false,
        "network_access": "finance_vlan_only",
        "time_restrictions": "business_hours"
    },
    "security": {
        "mfa_required": true,
        "encryption": "aes256",
        "key_rotation": "monthly"
    },
    "monitoring": {
        "real_time_alerts": true,
        "login_tracking": true,
        "file_access_log": true,
        "failed_attempts": 3,
        "compliance_reporting": "sox_hipaa"
    }
}
EOF
            ;;
        "guest_access_lobby")
            cat << EOF
{
    "user_category": "guest_temporary",
    "password_policy": "basic",
    "access_level": "guest_resources",
    "session_timeout": "1h",
    "audit_level": "full",
    "group_membership": ["guest", "public_access"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false,
        "internet_access": "guest_wifi_only",
        "file_upload": false
    },
    "automation": {
        "auto_expire": "24h",
        "auto_cleanup": true,
        "reset_on_logout": true
    },
    "monitoring": {
        "session_recording": true,
        "login_tracking": true,
        "activity_log": true,
        "failed_attempts": 3
    }
}
EOF
            ;;
        *)
            echo "Unknown deployment profile: $profile"
            return 1
            ;;
    esac
}

# Apply deployment profile
apply_deployment_profile() {
    local profile="$1"
    local config_file="/tmp/deployment_config.json"
    
    echo "Applying deployment profile: $profile"
    
    # Get configuration
    get_deployment_config "$profile" > "$config_file"
    
    if [[ ! -f "$config_file" ]]; then
        echo "❌ Failed to generate configuration for profile: $profile"
        return 1
    fi
    
    echo "✅ Deployment configuration ready"
    echo "Configuration saved to: $config_file"
    
    # Parse and display key settings
    echo "=== Profile Summary ==="
    echo "User Category: $(jq -r '.user_category' "$config_file")"
    echo "Password Policy: $(jq -r '.password_policy' "$config_file")"
    echo "Access Level: $(jq -r '.access_level' "$config_file")"
    echo "Session Timeout: $(jq -r '.session_timeout' "$config_file")"
    echo "Audit Level: $(jq -r '.audit_level' "$config_file")"
    
    return 0
}

Enterprise User Management System

#!/bin/bash

# Roundfleet Enterprise User Management System
# Comprehensive sharing user creation and management

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

# Create required directories
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
}

# Logging functions
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') [ERROR] $1" | tee -a "$LOG_FILE" >&2
}

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

# User ID management
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"
}

# Comprehensive user creation function
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 "Starting user creation: $username (Category: $user_category, Profile: $deployment_profile)"
    
    # Validate inputs
    if [[ -z "$username" || -z "$display_name" || -z "$user_category" ]]; then
        log_error "Missing required parameters for user creation"
        return 1
    fi
    
    # Check if user already exists
    if dscl . read /Users/"$username" &>/dev/null; then
        log_error "User $username already exists"
        return 1
    fi
    
    # Get deployment configuration
    local config_file="/tmp/user_config_${username}.json"
    get_deployment_config "$deployment_profile" > "$config_file"
    
    # Parse configuration
    local password_policy
    password_policy=$(jq -r '.password_policy' "$config_file")
    
    # Get next available user ID
    local user_id
    user_id=$(get_next_user_id 550)
    
    # Generate secure password
    local policy_details
    policy_details=$(generate_password_policy "$password_policy")
    local password
    password=$(generate_secure_password "$policy_details")
    
    # Create user metadata
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    cat > "$metadata_file" << EOF
{
    "username": "$username",
    "display_name": "$display_name",
    "user_category": "$user_category",
    "deployment_profile": "$deployment_profile",
    "department": "$department",
    "user_id": $user_id,
    "created_date": "$(date -Iseconds)",
    "created_by": "$(whoami)",
    "expiry_date": "$expiry_date",
    "password_policy": "$password_policy",
    "status": "active"
}
EOF
    
    # Create the user
    log_action "Creating user record for $username"
    sudo dscl . create /Users/"$username" || {
        log_error "Failed to create user record for $username"
        return 1
    }
    
    # Set basic properties
    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
    
    # Add custom attributes
    sudo dscl . create /Users/"$username" Comment "Roundfleet managed user - $user_category"
    sudo dscl . create /Users/"$username" Keywords "roundfleet,$user_category,$deployment_profile,$department"
    
    # Set expiry date if provided
    if [[ -n "$expiry_date" ]]; then
        sudo dscl . create /Users/"$username" ExpiryDate "$expiry_date"
    fi
    
    # Apply group memberships
    local groups
    groups=$(jq -r '.group_membership[]' "$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 "Group $group does not exist, skipping"
            }
        fi
    done <<< "$groups"
    
    # Store secure password (encrypted)
    echo "$password" | openssl enc -aes-256-cbc -pbkdf2 -k "roundfleet_$(hostname)" -out "$CONFIG_DIR/${username}_password.enc"
    
    # Create backup
    create_user_backup "$username"
    
    # Audit logging
    audit_log "User created: $username (UID: $user_id, Category: $user_category, Profile: $deployment_profile)"
    
    log_action "✅ User $username created successfully (UID: $user_id)"
    
    # Return password for initial communication (in production, use secure delivery)
    echo "CREATED_USER_INFO:$username:$password:$user_id"
    
    return 0
}

# Bulk user creation
bulk_create_users() {
    local csv_file="$1"
    local created_count=0
    local failed_count=0
    
    if [[ ! -f "$csv_file" ]]; then
        log_error "CSV file not found: $csv_file"
        return 1
    fi
    
    log_action "Starting bulk user creation from: $csv_file"
    
    # Process CSV file (skip header)
    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 "Bulk creation completed. Created: $created_count, Failed: $failed_count"
    
    # Generate report
    generate_user_report "bulk_creation_$(date +%Y%m%d_%H%M%S)"
}

# User management functions
list_enterprise_users() {
    echo "=== Roundfleet Managed Users ==="
    echo "Username | Display Name | Category | Status | Created"
    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 '.username' "$metadata_file")
            display_name=$(jq -r '.display_name' "$metadata_file")
            category=$(jq -r '.user_category' "$metadata_file")
            status=$(jq -r '.status' "$metadata_file")
            created_date=$(jq -r '.created_date' "$metadata_file" | cut -d'T' -f1)
            
            printf "%-8s | %-12s | %-8s | %-6s | %s\n" "$username" "$display_name" "$category" "$status" "$created_date"
        fi
    done
}

# User removal with cleanup
remove_enterprise_user() {
    local username="$1"
    local backup_before_removal="$2"
    
    log_action "Starting removal of user: $username"
    
    # Check if user exists
    if ! dscl . read /Users/"$username" &>/dev/null; then
        log_error "User $username does not exist"
        return 1
    fi
    
    # Create backup before removal
    if [[ "$backup_before_removal" == "true" ]]; then
        create_user_backup "$username"
    fi
    
    # Remove user from system
    sudo dscl . delete /Users/"$username" || {
        log_error "Failed to remove user $username from system"
        return 1
    }
    
    # Update metadata
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    if [[ -f "$metadata_file" ]]; then
        jq '.status = "deleted" | .deleted_date = now | .deleted_by = "'"$(whoami)"'"' "$metadata_file" > "${metadata_file}.tmp" && mv "${metadata_file}.tmp" "$metadata_file"
    fi
    
    # Audit logging
    audit_log "User removed: $username by $(whoami)"
    
    log_action "✅ User $username removed successfully"
    return 0
}

# User backup and restore
create_user_backup() {
    local username="$1"
    local backup_file="$BACKUP_DIR/${username}_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    log_action "Creating backup for user: $username"
    
    # Export user record
    sudo dscl . read /Users/"$username" > "$backup_file"
    
    # Backup metadata
    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 "✅ User backup created: $backup_file"
}

# System health monitoring
monitor_user_system() {
    echo "=== User System Health Check ==="
    
    # Check for expired users
    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 '.expiry_date' "$metadata_file")
            username=$(jq -r '.username' "$metadata_file")
            
            if [[ "$expiry_date" != "null" && "$expiry_date" != "" ]]; then
                if [[ $(date -d "$expiry_date" +%s 2>/dev/null) -lt $(date +%s) ]]; then
                    echo "⚠️  Expired user: $username (expired: $expiry_date)"
                    ((expired_users++))
                fi
            fi
        fi
    done
    
    # Check for orphaned user records
    local system_users
    system_users=$(dscl . list /Users | grep -E "^(Sharing|Guest|Service|External)" || true)
    local orphaned_users=0
    
    while IFS= read -r user; do
        if [[ -n "$user" && ! -f "$CONFIG_DIR/${user}_metadata.json" ]]; then
            echo "⚠️  Orphaned user (no metadata): $user"
            ((orphaned_users++))
        fi
    done <<< "$system_users"
    
    # Summary
    echo ""
    echo "Health Summary:"
    echo "  Expired users: $expired_users"
    echo "  Orphaned users: $orphaned_users"
    
    if [[ $expired_users -eq 0 && $orphaned_users -eq 0 ]]; then
        echo "✅ User system is healthy"
    else
        echo "⚠️  User system requires attention"
    fi
}

# Generate comprehensive reports
generate_user_report() {
    local report_name="$1"
    local report_file="$REPORTS_DIR/${report_name}.json"
    
    log_action "Generating user report: $report_name"
    
    # Collect user statistics
    local total_users active_users inactive_users
    total_users=$(find "$CONFIG_DIR" -name "*_metadata.json" | wc -l)
    active_users=$(grep -l '"status": "active"' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | wc -l)
    inactive_users=$((total_users - active_users))
    
    # Category breakdown
    local categories
    categories=$(jq -r '.user_category' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | sort | uniq -c | awk '{print "{\"category\": \"" $2 "\", \"count\": " $1 "}"}' | jq -s '.')
    
    # Generate report
    cat > "$report_file" << EOF
{
    "report_name": "$report_name",
    "generated_date": "$(date -Iseconds)",
    "generated_by": "$(whoami)",
    "hostname": "$(hostname)",
    "statistics": {
        "total_users": $total_users,
        "active_users": $active_users,
        "inactive_users": $inactive_users
    },
    "category_breakdown": $categories,
    "system_info": {
        "roundfleet_version": "2025.07.07",
        "os_version": "$(sw_vers -productVersion)",
        "hostname": "$(hostname)"
    }
}
EOF
    
    log_action "✅ Report generated: $report_file"
    echo "Report saved to: $report_file"
}

# Fleet deployment functions
deploy_to_fleet() {
    local fleet_config="$1"
    local user_config="$2"
    
    log_action "Starting fleet deployment"
    
    if [[ ! -f "$fleet_config" ]]; then
        log_error "Fleet configuration file not found: $fleet_config"
        return 1
    fi
    
    if [[ ! -f "$user_config" ]]; then
        log_error "User configuration file not found: $user_config"
        return 1
    fi
    
    # Read fleet configuration
    local hosts
    hosts=$(jq -r '.hosts[]' "$fleet_config")
    
    # Deploy to each host
    while IFS= read -r host; do
        if [[ -n "$host" ]]; then
            log_action "Deploying to host: $host"
            
            # Copy user management script and configuration
            scp "$0" "$user_config" "root@${host}:/tmp/" || {
                log_error "Failed to copy files to $host"
                continue
            }
            
            # Execute deployment on remote host
            ssh "root@${host}" "chmod +x /tmp/$(basename "$0") && /tmp/$(basename "$0") deploy_from_config /tmp/$(basename "$user_config")" || {
                log_error "Failed to execute deployment on $host"
                continue
            }
            
            log_action "✅ Deployment completed on: $host"
        fi
    done <<< "$hosts"
    
    log_action "Fleet deployment completed"
}

# Main function with command routing
main() {
    local command="$1"
    shift
    
    # Initialize
    create_directories
    
    case "$command" in
        "create")
            create_enterprise_user "$@"
            ;;
        "bulk_create")
            bulk_create_users "$@"
            ;;
        "list")
            list_enterprise_users
            ;;
        "remove")
            remove_enterprise_user "$@"
            ;;
        "backup")
            create_user_backup "$@"
            ;;
        "monitor")
            monitor_user_system
            ;;
        "report")
            generate_user_report "$@"
            ;;
        "deploy_fleet")
            deploy_to_fleet "$@"
            ;;
        "show_categories")
            print_user_categories
            ;;
        "show_policies")
            for policy in standard strong basic service department external public; do
                echo "Policy: $policy"
                echo "  $(generate_password_policy "$policy")"
                echo ""
            done
            ;;
        *)
            echo "Roundfleet Enterprise User Management System"
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  create <username> <display_name> <category> <profile> [department] [expiry]"
            echo "  bulk_create <csv_file>"
            echo "  list"
            echo "  remove <username> [backup_before_removal]"
            echo "  backup <username>"
            echo "  monitor"
            echo "  report <report_name>"
            echo "  deploy_fleet <fleet_config> <user_config>"
            echo "  show_categories"
            echo "  show_policies"
            echo ""
            echo "Examples:"
            echo "  $0 create FileShare 'File Sharing Account' sharing_standard corporate_standard IT"
            echo "  $0 bulk_create users.csv"
            echo "  $0 list"
            echo "  $0 monitor"
            echo "  $0 report monthly_audit"
            ;;
    esac
}

# Execute main function with all arguments
main "$@"

Fleet Deployment Example

CSV Template for Bulk Creation

username,display_name,category,profile,department,expiry
FileShare01,File Sharing Account 1,sharing_standard,corporate_standard,IT,
GuestLobby,Guest Lobby Access,guest_temporary,guest_access_lobby,Reception,2025-12-31
PartnerExt,External Partner Access,sharing_secure,partner_collaboration,Legal,2025-09-30
KioskLib,Library Kiosk Account,kiosk_public,kiosk_public_library,Public,
FinanceShare,Finance Shared Account,sharing_secure,high_security_finance,Finance,
DevTeam,Development Team Share,sharing_standard,research_development,Engineering,

Fleet Configuration Example

{
    "fleet_name": "Roundfleet Corporate",
    "deployment_date": "2025-07-07",
    "hosts": [
        "mac-office-01.company.com",
        "mac-office-02.company.com",
        "mac-conference-01.company.com"
    ],
    "deployment_profile": "corporate_standard",
    "security_policy": "enterprise_standard",
    "monitoring": {
        "enabled": true,
        "reporting_interval": "daily",
        "alert_threshold": "high"
    }
}

Security Considerations

User Account Security

  • No Shell Access - Sharing users cannot access command line
  • No Home Directory - Prevents file storage in user directories
  • Limited Group Membership - Restricts system access
  • Password Policies - Enforces strong password requirements
  • Audit Logging - Tracks all user management activities

Enterprise Compliance

  • SOX Compliance - Financial user access controls
  • HIPAA Compliance - Healthcare data protection
  • NIST Framework - Security control implementation
  • ISO 27001 - Information security management

Troubleshooting Guide

Common Issues

User Creation Fails

  • Check if user ID is already in use
  • Verify administrative privileges
  • Ensure directory services are running

Authentication Problems

  • Verify password policy compliance
  • Check user account status
  • Review audit logs for failed attempts

Permission Errors

  • Confirm group memberships
  • Check file sharing permissions
  • Verify security policy application

Diagnostic Commands

# Check user existence
dscl . read /Users/username

# List all users
dscl . list /Users

# Check user groups
groups username

# View user properties
id username

Important Notes

  • Test thoroughly before fleet deployment
  • Backup user data before making changes
  • Monitor audit logs for security events
  • Update policies based on security requirements
  • Document changes for compliance auditing
  • Use secure password delivery methods in production

Run Setup Assistant on macOS Devices at Next Reboot

This comprehensive guide demonstrates how to trigger macOS Setup Assistant on the next device reboot, enabling device reconfiguration, user onboarding, and enterprise deployment workflows.

Overview

The Setup Assistant is macOS's built-in configuration wizard that guides users through initial device setup. It can be triggered manually for various enterprise scenarios:

  • Device reconfiguration: Reset devices to factory-like state while preserving data
  • User onboarding: Streamline new employee device setup
  • Mass deployment: Standardize device configuration across organizations
  • Troubleshooting: Reset system configurations without full device wipe
  • Compliance: Ensure devices meet organizational setup requirements

Basic Setup Assistant Trigger

Simple Setup Assistant Script

Create a basic script to trigger Setup Assistant on next reboot:

#!/bin/bash

# Basic Setup Assistant trigger script
# Usage: ./trigger_setup_assistant.sh

trigger_setup_assistant() {
    # Check if running as root
    if [ "$(id -u)" != "0" ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Check if .AppleSetupDone file exists
    if [ ! -f "/private/var/db/.AppleSetupDone" ]; then
        echo "Setup Assistant marker file not found. Setup Assistant may already be scheduled to run."
        exit 0
    fi
    
    # Remove .AppleSetupDone file
    sudo rm /private/var/db/.AppleSetupDone
    
    if [ $? -eq 0 ]; then
        echo "Setup Assistant will run on the next reboot."
        echo "Please restart the device to begin Setup Assistant."
    else
        echo "Error: Failed to remove Setup Assistant marker file."
        exit 1
    fi
}

# Execute function
trigger_setup_assistant

Enhanced Setup Assistant with Validation

#!/bin/bash

# Enhanced Setup Assistant trigger with validation and logging
# Usage: ./enhanced_setup_assistant.sh

enhanced_setup_assistant() {
    local log_file="/var/log/roundfleet_setup_assistant.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local setup_done_file="/private/var/db/.AppleSetupDone"
    local computer_name=$(scutil --get ComputerName)
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Create log directory if it doesn't exist
    mkdir -p /var/log
    
    # Log the operation start
    echo "[$timestamp] Starting Setup Assistant trigger on $computer_name" >> "$log_file"
    
    # Check macOS version compatibility
    local os_version=$(sw_vers -productVersion)
    local major_version=$(echo "$os_version" | cut -d. -f1)
    
    if [ "$major_version" -ge 14 ]; then
        echo "[$timestamp] WARNING: macOS $os_version detected. Setup Assistant trigger may not work on macOS 14+" >> "$log_file"
        echo "Warning: This script is supported on macOS versions below 14. Current version: $os_version"
        read -p "Do you want to continue anyway? (y/N): " continue_anyway
        if [ "$continue_anyway" != "y" ] && [ "$continue_anyway" != "Y" ]; then
            echo "[$timestamp] Operation cancelled by user due to version compatibility" >> "$log_file"
            echo "Operation cancelled."
            exit 0
        fi
    fi
    
    # Check if Setup Assistant marker file exists
    if [ ! -f "$setup_done_file" ]; then
        echo "[$timestamp] Setup Assistant marker file not found at $setup_done_file" >> "$log_file"
        echo "Setup Assistant marker file not found. Setup Assistant may already be scheduled to run."
        echo "File location: $setup_done_file"
        exit 0
    fi
    
    # Get file information before removal
    local file_info=$(ls -la "$setup_done_file" 2>/dev/null)
    echo "[$timestamp] Current marker file info: $file_info" >> "$log_file"
    
    # Create backup of marker file
    local backup_dir="/var/backups/roundfleet"
    mkdir -p "$backup_dir"
    cp "$setup_done_file" "$backup_dir/.AppleSetupDone.backup.$(date +%Y%m%d_%H%M%S)" 2>/dev/null
    
    # Remove .AppleSetupDone file
    rm "$setup_done_file"
    
    # Verify removal
    if [ ! -f "$setup_done_file" ]; then
        echo "[$timestamp] Setup Assistant marker file removed successfully" >> "$log_file"
        echo "Setup Assistant has been configured to run on the next reboot."
        echo ""
        echo "Device Information:"
        echo "  Computer Name: $computer_name"
        echo "  macOS Version: $os_version"
        echo "  Timestamp: $timestamp"
        echo ""
        echo "Next Steps:"
        echo "  1. Restart the device to begin Setup Assistant"
        echo "  2. Follow the on-screen prompts to configure the device"
        echo "  3. Setup Assistant will guide through language, region, accounts, and other settings"
        echo ""
        echo "Note: All existing user data and applications will remain intact."
    else
        echo "[$timestamp] ERROR: Failed to remove Setup Assistant marker file" >> "$log_file"
        echo "Error: Failed to remove Setup Assistant marker file."
        echo "Please check permissions and try again."
        exit 1
    fi
}

# Execute enhanced setup
enhanced_setup_assistant

Advanced Setup Assistant Management

Conditional Setup Assistant Trigger

#!/bin/bash

# Conditional Setup Assistant trigger with multiple scenarios
# Usage: ./conditional_setup_assistant.sh [scenario]

conditional_setup_assistant() {
    local scenario=${1:-"default"}
    local log_file="/var/log/roundfleet_setup_assistant.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    echo "[$timestamp] Conditional Setup Assistant trigger - Scenario: $scenario" >> "$log_file"
    
    case $scenario in
        "new_employee")
            trigger_new_employee_setup
            ;;
        "device_refresh")
            trigger_device_refresh_setup
            ;;
        "compliance_reset")
            trigger_compliance_reset
            ;;
        "troubleshooting")
            trigger_troubleshooting_setup
            ;;
        "mass_deployment")
            trigger_mass_deployment_setup
            ;;
        "default")
            trigger_default_setup
            ;;
        *)
            echo "Unknown scenario: $scenario"
            echo "Available scenarios: new_employee, device_refresh, compliance_reset, troubleshooting, mass_deployment, default"
            exit 1
            ;;
    esac
}

trigger_new_employee_setup() {
    echo "Configuring Setup Assistant for new employee onboarding..."
    
    # Remove Setup Assistant marker
    rm -f /private/var/db/.AppleSetupDone
    
    # Clear previous user data (optional)
    echo "[$timestamp] New employee setup - Setup Assistant configured" >> "$log_file"
    
    cat << 'EOF'
Setup Assistant configured for new employee onboarding.

The following will be presented to the user:
• Language and region selection
• Wi-Fi network configuration
• Apple ID sign-in
• User account creation
• Privacy and security settings
• Touch ID setup (if available)
• Desktop appearance preferences

Please restart the device and provide to the new employee.
EOF
}

trigger_device_refresh_setup() {
    echo "Configuring Setup Assistant for device refresh..."
    
    # Check if user data should be preserved
    local user_dirs=$(ls /Users | grep -v "Shared" | grep -v "Guest" | head -5)
    if [ -n "$user_dirs" ]; then
        echo "Existing user accounts detected:"
        echo "$user_dirs"
        echo ""
        read -p "Preserve existing user data? (Y/n): " preserve_data
        
        if [ "$preserve_data" = "n" ] || [ "$preserve_data" = "N" ]; then
            echo "Warning: This will remove user data during refresh."
            read -p "Are you sure? (y/N): " confirm
            if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
                echo "Operation cancelled."
                return 1
            fi
        fi
    fi
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Device refresh setup - Setup Assistant configured" >> "$log_file"
    
    echo "Setup Assistant configured for device refresh."
    echo "Restart the device to begin reconfiguration process."
}

trigger_compliance_reset() {
    echo "Configuring Setup Assistant for compliance reset..."
    
    # Log compliance reset
    echo "[$timestamp] Compliance reset initiated - Setup Assistant triggered" >> "$log_file"
    
    # Remove Setup Assistant marker
    rm -f /private/var/db/.AppleSetupDone
    
    # Additional compliance-related cleanup (customize as needed)
    # rm -f /Library/Preferences/com.apple.loginwindow.plist
    
    cat << 'EOF'
Setup Assistant configured for compliance reset.

This will ensure the device meets organizational compliance requirements:
• Force re-acceptance of terms and policies
• Verify user account configurations
• Confirm security settings
• Update privacy preferences
• Validate organizational settings

Restart the device to begin compliance verification.
EOF
}

trigger_troubleshooting_setup() {
    echo "Configuring Setup Assistant for troubleshooting..."
    
    # Create troubleshooting report
    local troubleshoot_report="/tmp/troubleshoot_report_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$troubleshoot_report" << EOF
Roundfleet Troubleshooting Report
Generated: $(date)
Device: $(scutil --get ComputerName)
macOS Version: $(sw_vers -productVersion)

Issues that Setup Assistant may resolve:
• User account configuration problems
• System preference corruption
• Network configuration issues
• Apple ID authentication problems
• Privacy setting inconsistencies

Setup Assistant will be triggered on next reboot.
EOF
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Troubleshooting setup - Setup Assistant configured" >> "$log_file"
    
    echo "Setup Assistant configured for troubleshooting."
    echo "Troubleshooting report saved to: $troubleshoot_report"
    echo "Restart the device to begin setup process."
}

trigger_mass_deployment_setup() {
    echo "Configuring Setup Assistant for mass deployment..."
    
    # Get device serial number for tracking
    local serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    
    # Log deployment
    echo "[$timestamp] Mass deployment setup - Device: $serial_number" >> "$log_file"
    
    rm -f /private/var/db/.AppleSetupDone
    
    cat << EOF
Setup Assistant configured for mass deployment.

Device Serial: $serial_number
Deployment Date: $(date)

Standardized setup will include:
• Language: English (US)
• Region: United States
• Network: Enterprise Wi-Fi
• Account: Standard user account
• Security: Corporate security policies
• Applications: Standard corporate apps

Device is ready for deployment. Restart to begin setup.
EOF
}

trigger_default_setup() {
    echo "Configuring Setup Assistant with default settings..."
    
    rm -f /private/var/db/.AppleSetupDone
    echo "[$timestamp] Default setup - Setup Assistant configured" >> "$log_file"
    
    echo "Setup Assistant configured with default settings."
    echo "Restart the device to begin setup process."
}

# Main execution
if [ $# -eq 0 ]; then
    echo "Usage: $0 [scenario]"
    echo "Available scenarios:"
    echo "  new_employee    - Configure for new employee onboarding"
    echo "  device_refresh  - Configure for device refresh/reconfiguration"
    echo "  compliance_reset - Configure for compliance verification"
    echo "  troubleshooting - Configure for troubleshooting purposes"
    echo "  mass_deployment - Configure for mass deployment"
    echo "  default         - Configure with default settings"
    echo ""
    conditional_setup_assistant "default"
else
    conditional_setup_assistant "$1"
fi

Enterprise Setup Assistant Manager

#!/bin/bash

# Enterprise Setup Assistant Manager with configuration profiles
# Usage: ./enterprise_setup_manager.sh

enterprise_setup_manager() {
    local config_file="/etc/roundfleet/setup_assistant_config.conf"
    local log_file="/var/log/roundfleet_setup_assistant.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Create configuration directory
    mkdir -p /etc/roundfleet
    
    # Load or create configuration
    if [ -f "$config_file" ]; then
        source "$config_file"
    else
        create_enterprise_config
        source "$config_file"
    fi
    
    echo "[$timestamp] Enterprise Setup Assistant Manager started" >> "$log_file"
    
    # Display configuration menu
    display_enterprise_menu
}

create_enterprise_config() {
    cat > "/etc/roundfleet/setup_assistant_config.conf" << 'EOF'
# Roundfleet Enterprise Setup Assistant Configuration

# Organization Information
ORGANIZATION_NAME="Roundfleet Organization"
IT_CONTACT_EMAIL="[email protected]"
IT_CONTACT_PHONE="1-800-ROUNDFLEET"

# Default Configuration
DEFAULT_LANGUAGE="English"
DEFAULT_REGION="United States"
REQUIRE_APPLE_ID="false"
ENABLE_LOCATION_SERVICES="false"
ENABLE_SIRI="false"
REQUIRE_TERMS_ACCEPTANCE="true"

# Security Settings
REQUIRE_STRONG_PASSWORD="true"
ENABLE_FILEVAULT="true"
REQUIRE_TOUCH_ID="true"

# Deployment Settings
DEPLOYMENT_MODE="enterprise"
SKIP_OPTIONAL_STEPS="true"
AUTO_CONFIGURE_NETWORK="true"
EOF
    
    echo "configuration created at /etc/roundfleet/setup_assistant_config.conf"
}

display_enterprise_menu() {
    while true; do
        clear
        echo "======================================="
        echo "Roundfleet Enterprise Setup Assistant"
        echo "======================================="
        echo ""
        echo "Organization: $ORGANIZATION_NAME"
        echo "Contact: $IT_CONTACT_EMAIL"
        echo ""
        echo "Available Actions:"
        echo "1. Trigger Setup Assistant (Single Device)"
        echo "2. Prepare Mass Deployment"
        echo "3. Configure Setup Assistant Options"
        echo "4. View Setup Assistant Status"
        echo "5. Generate Deployment Report"
        echo "6. Backup/Restore Setup State"
        echo "7. View Configuration"
        echo "8. Exit"
        echo ""
        read -p "Select an option (1-8): " choice
        
        case $choice in
            1)
                trigger_single_device_setup
                ;;
            2)
                prepare_mass_deployment
                ;;
            3)
                configure_setup_options
                ;;
            4)
                view_setup_status
                ;;
            5)
                generate_deployment_report
                ;;
            6)
                backup_restore_setup
                ;;
            7)
                view_configuration
                ;;
            8)
                echo "Exiting Enterprise Setup Assistant Manager."
                exit 0
                ;;
            *)
                echo "Invalid option. Please try again."
                ;;
        esac
        
        echo ""
        read -p "Press Enter to continue..."
    done
}

trigger_single_device_setup() {
    echo "======================================="
    echo "Trigger Setup Assistant - Single Device"
    echo "======================================="
    
    local device_name=$(scutil --get ComputerName)
    local serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    
    echo "Device: $device_name"
    echo "Serial: $serial_number"
    echo ""
    
    read -p "Confirm triggering Setup Assistant on this device? (y/N): " confirm
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        # Remove Setup Assistant marker
        if rm -f /private/var/db/.AppleSetupDone; then
            echo "[$timestamp] Single device setup triggered - $device_name ($serial_number)" >> "$log_file"
            echo "Setup Assistant configured successfully."
            echo "Please restart the device to begin setup."
        else
            echo "Error: Failed to configure Setup Assistant."
        fi
    else
        echo "Operation cancelled."
    fi
}

prepare_mass_deployment() {
    echo "======================================="
    echo "Prepare Mass Deployment"
    echo "======================================="
    
    read -p "Enter number of devices for deployment: " device_count
    read -p "Enter deployment batch name: " batch_name
    
    local deployment_dir="/var/roundfleet/deployments/$batch_name"
    mkdir -p "$deployment_dir"
    
    # Create deployment package
    cat > "$deployment_dir/deploy_setup_assistant.sh" << 'EOF'
#!/bin/bash
# Roundfleet Mass Deployment Setup Assistant Trigger
# Auto-generated deployment script

# Check if running as root
if [ "$EUID" -ne 0 ]; then
    echo "Error: This script must be run as root"
    exit 1
fi

# Remove Setup Assistant marker
rm -f /private/var/db/.AppleSetupDone

# Log deployment
echo "$(date '+%Y-%m-%d %H:%M:%S') - Mass deployment setup triggered on $(scutil --get ComputerName)" >> /var/log/roundfleet_mass_deployment.log

echo "Setup Assistant configured for mass deployment."
echo "Restart device to begin setup process."
EOF
    
    chmod +x "$deployment_dir/deploy_setup_assistant.sh"
    
    # Create deployment manifest
    cat > "$deployment_dir/deployment_manifest.txt" << EOF
Roundfleet Mass Deployment Manifest
Batch Name: $batch_name
Device Count: $device_count
Created: $(date)
Organization: $ORGANIZATION_NAME

Deployment Instructions:
1. Copy deploy_setup_assistant.sh to each device
2. Run script as root on each device
3. Restart devices to begin Setup Assistant
4. Follow standard setup procedures

Contact: $IT_CONTACT_EMAIL
EOF
    
    echo "Mass deployment package created at: $deployment_dir"
    echo "Deployment script: $deployment_dir/deploy_setup_assistant.sh"
    echo "Manifest: $deployment_dir/deployment_manifest.txt"
}

configure_setup_options() {
    echo "======================================="
    echo "Configure Setup Assistant Options"
    echo "======================================="
    
    echo "Current Configuration:"
    echo "  Language: $DEFAULT_LANGUAGE"
    echo "  Region: $DEFAULT_REGION"
    echo "  Require Apple ID: $REQUIRE_APPLE_ID"
    echo "  Enable Location Services: $ENABLE_LOCATION_SERVICES"
    echo "  Enable Siri: $ENABLE_SIRI"
    echo ""
    
    read -p "Modify configuration? (y/N): " modify
    if [ "$modify" = "y" ] || [ "$modify" = "Y" ]; then
        echo "Configuration modification would require additional setup..."
        echo "Please edit: /etc/roundfleet/setup_assistant_config.conf"
    fi
}

view_setup_status() {
    echo "======================================="
    echo "Setup Assistant Status"
    echo "======================================="
    
    local setup_done_file="/private/var/db/.AppleSetupDone"
    local device_name=$(scutil --get ComputerName)
    local os_version=$(sw_vers -productVersion)
    
    echo "Device: $device_name"
    echo "macOS Version: $os_version"
    echo "Timestamp: $(date)"
    echo ""
    
    if [ -f "$setup_done_file" ]; then
        echo "Status: Setup Assistant COMPLETED"
        echo "File: $setup_done_file exists"
        echo "Modified: $(stat -f "%Sm" "$setup_done_file")"
        echo ""
        echo "Setup Assistant will NOT run on next reboot."
    else
        echo "Status: Setup Assistant SCHEDULED"
        echo "File: $setup_done_file does not exist"
        echo ""
        echo "Setup Assistant WILL run on next reboot."
    fi
}

generate_deployment_report() {
    echo "======================================="
    echo "Generate Deployment Report"
    echo "======================================="
    
    local report_file="/tmp/roundfleet_setup_report_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$report_file" << EOF
Roundfleet Setup Assistant Deployment Report
Generated: $(date)
Organization: $ORGANIZATION_NAME

Device Information:
  Computer Name: $(scutil --get ComputerName)
  Serial Number: $(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
  macOS Version: $(sw_vers -productVersion)
  Hardware Model: $(system_profiler SPHardwareDataType | grep "Model Name" | cut -d: -f2 | xargs)

Setup Assistant Status:
EOF
    
    if [ -f "/private/var/db/.AppleSetupDone" ]; then
        echo "  Status: Completed" >> "$report_file"
        echo "  Last Run: $(stat -f "%Sm" "/private/var/db/.AppleSetupDone")" >> "$report_file"
    else
        echo "  Status: Scheduled for next reboot" >> "$report_file"
    fi
    
    cat >> "$report_file" << EOF

Configuration:
  Default Language: $DEFAULT_LANGUAGE
  Default Region: $DEFAULT_REGION
  Deployment Mode: $DEPLOYMENT_MODE
  Contact: $IT_CONTACT_EMAIL

Recent Log Entries:
EOF
    
    if [ -f "/var/log/roundfleet_setup_assistant.log" ]; then
        tail -10 "/var/log/roundfleet_setup_assistant.log" >> "$report_file"
    else
        echo "  No log entries found" >> "$report_file"
    fi
    
    echo "Deployment report generated: $report_file"
}

backup_restore_setup() {
    echo "======================================="
    echo "Backup/Restore Setup State"
    echo "======================================="
    
    echo "1. Backup current Setup Assistant state"
    echo "2. Restore Setup Assistant state"
    echo ""
    read -p "Select option (1-2): " backup_option
    
    case $backup_option in
        1)
            backup_setup_state
            ;;
        2)
            restore_setup_state
            ;;
        *)
            echo "Invalid option."
            ;;
    esac
}

backup_setup_state() {
    local backup_dir="/var/backups/roundfleet"
    local timestamp=$(date +%Y%m%d_%H%M%S)
    
    mkdir -p "$backup_dir"
    
    if [ -f "/private/var/db/.AppleSetupDone" ]; then
        cp "/private/var/db/.AppleSetupDone" "$backup_dir/.AppleSetupDone.backup.$timestamp"
        echo "Setup Assistant state backed up to: $backup_dir/.AppleSetupDone.backup.$timestamp"
    else
        echo "No Setup Assistant state to backup (file does not exist)."
    fi
}

restore_setup_state() {
    local backup_dir="/var/backups/roundfleet"
    
    if [ -d "$backup_dir" ]; then
        echo "Available backups:"
        ls -la "$backup_dir"/.AppleSetupDone.backup.* 2>/dev/null || echo "No backups found."
        echo ""
        read -p "Enter backup filename to restore: " backup_file
        
        if [ -f "$backup_dir/$backup_file" ]; then
            cp "$backup_dir/$backup_file" "/private/var/db/.AppleSetupDone"
            echo "Setup Assistant state restored from: $backup_file"
        else
            echo "Backup file not found."
        fi
    else
        echo "No backup directory found."
    fi
}

view_configuration() {
    echo "======================================="
    echo "Current Configuration"
    echo "======================================="
    
    if [ -f "/etc/roundfleet/setup_assistant_config.conf" ]; then
        cat "/etc/roundfleet/setup_assistant_config.conf"
    else
        echo "No configuration file found."
    fi
}

# Execute enterprise manager
enterprise_setup_manager

Setup Assistant Automation and Monitoring

Automated Setup Assistant Deployment

#!/bin/bash

# Automated Setup Assistant deployment with scheduling
# Usage: ./automated_setup_deployment.sh

automated_setup_deployment() {
    local config_file="/etc/roundfleet/automated_deployment.conf"
    local log_file="/var/log/roundfleet_automated_setup.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Create configuration if it doesn't exist
    if [ ! -f "$config_file" ]; then
        create_automation_config
    fi
    
    source "$config_file"
    
    echo "[$timestamp] Automated Setup Assistant deployment started" >> "$log_file"
    
    # Check deployment conditions
    check_deployment_conditions
    
    # Execute deployment based on configuration
    execute_automated_deployment
}

create_automation_config() {
    mkdir -p /etc/roundfleet
    
    cat > "/etc/roundfleet/automated_deployment.conf" << 'EOF'
# Roundfleet Automated Setup Assistant Deployment Configuration

# Deployment Schedule
ENABLE_SCHEDULED_DEPLOYMENT="false"
DEPLOYMENT_TIME="02:00"  # 24-hour format
DEPLOYMENT_DAYS="Mon,Wed,Fri"

# Deployment Conditions
CHECK_USER_ACTIVITY="true"
IDLE_TIME_THRESHOLD="3600"  # seconds
REQUIRE_AC_POWER="true"
MIN_BATTERY_LEVEL="50"

# Notification Settings
NOTIFY_USERS="true"
NOTIFICATION_LEAD_TIME="300"  # 5 minutes
ALLOW_USER_POSTPONE="true"
MAX_POSTPONE_COUNT="3"

# Deployment Scope
TARGET_DEVICES="all"  # all, specific_models, specific_serials
EXCLUDE_CRITICAL_HOURS="true"
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="17:00"

# Rollback Settings
ENABLE_AUTOMATIC_ROLLBACK="true"
ROLLBACK_ON_ERROR="true"
BACKUP_BEFORE_DEPLOYMENT="true"
EOF
    
    echo "Automation configuration created at /etc/roundfleet/automated_deployment.conf"
}

check_deployment_conditions() {
    local current_time=$(date +%H:%M)
    local current_day=$(date +%a)
    local battery_level=$(pmset -g batt | grep -o '[0-9]*%' | sed 's/%//')
    local ac_power=$(pmset -g batt | grep -c "AC Power")
    
    echo "[$timestamp] Checking deployment conditions" >> "$log_file"
    
    # Check if deployment is enabled
    if [ "$ENABLE_SCHEDULED_DEPLOYMENT" != "true" ]; then
        echo "[$timestamp] Scheduled deployment is disabled" >> "$log_file"
        echo "Scheduled deployment is disabled."
        return 1
    fi
    
    # Check deployment time
    if [ "$current_time" != "$DEPLOYMENT_TIME" ]; then
        echo "[$timestamp] Not deployment time (current: $current_time, scheduled: $DEPLOYMENT_TIME)" >> "$log_file"
        return 1
    fi
    
    # Check deployment day
    if [[ "$DEPLOYMENT_DAYS" != *"$current_day"* ]]; then
        echo "[$timestamp] Not deployment day (current: $current_day, scheduled: $DEPLOYMENT_DAYS)" >> "$log_file"
        return 1
    fi
    
    # Check business hours
    if [ "$EXCLUDE_CRITICAL_HOURS" = "true" ]; then
        if [[ "$current_time" > "$BUSINESS_HOURS_START" && "$current_time" < "$BUSINESS_HOURS_END" ]]; then
            echo "[$timestamp] Deployment blocked during business hours" >> "$log_file"
            return 1
        fi
    fi
    
    # Check power requirements
    if [ "$REQUIRE_AC_POWER" = "true" ] && [ "$ac_power" -eq 0 ]; then
        echo "[$timestamp] AC power required but not available" >> "$log_file"
        return 1
    fi
    
    # Check battery level
    if [ -n "$battery_level" ] && [ "$battery_level" -lt "$MIN_BATTERY_LEVEL" ]; then
        echo "[$timestamp] Battery level too low ($battery_level% < $MIN_BATTERY_LEVEL%)" >> "$log_file"
        return 1
    fi
    
    # Check user activity
    if [ "$CHECK_USER_ACTIVITY" = "true" ]; then
        local idle_time=$(ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print $3/1000000000; exit}')
        if [ "$(echo "$idle_time < $IDLE_TIME_THRESHOLD" | bc)" -eq 1 ]; then
            echo "[$timestamp] User activity detected (idle: ${idle_time}s < ${IDLE_TIME_THRESHOLD}s)" >> "$log_file"
            return 1
        fi
    fi
    
    echo "[$timestamp] All deployment conditions met" >> "$log_file"
    return 0
}

execute_automated_deployment() {
    echo "[$timestamp] Executing automated Setup Assistant deployment" >> "$log_file"
    
    # Send user notification if enabled
    if [ "$NOTIFY_USERS" = "true" ]; then
        send_user_notification
    fi
    
    # Create backup if enabled
    if [ "$BACKUP_BEFORE_DEPLOYMENT" = "true" ]; then
        create_deployment_backup
    fi
    
    # Trigger Setup Assistant
    if rm -f /private/var/db/.AppleSetupDone; then
        echo "[$timestamp] Setup Assistant triggered successfully via automation" >> "$log_file"
        
        # Schedule automatic reboot if configured
        if [ -n "$AUTO_REBOOT_DELAY" ]; then
            echo "[$timestamp] Scheduling automatic reboot in $AUTO_REBOOT_DELAY minutes" >> "$log_file"
            at "now + $AUTO_REBOOT_DELAY minutes" << 'EOF'
/sbin/reboot
EOF
        fi
        
        # Send completion notification
        send_completion_notification
        
    else
        echo "[$timestamp] ERROR: Failed to trigger Setup Assistant" >> "$log_file"
        
        # Execute rollback if enabled
        if [ "$ROLLBACK_ON_ERROR" = "true" ]; then
            execute_rollback
        fi
    fi
}

send_user_notification() {
    local notification_title="Roundfleet Setup Assistant"
    local notification_message="Setup Assistant will be triggered in $NOTIFICATION_LEAD_TIME seconds. Please save your work."
    
    # Use osascript to display notification
    osascript -e "display notification \"$notification_message\" with title \"$notification_title\" sound name \"Glass\""
    
    # Wait for lead time
    sleep "$NOTIFICATION_LEAD_TIME"
}

create_deployment_backup() {
    local backup_dir="/var/backups/roundfleet/automated"
    local backup_timestamp=$(date +%Y%m%d_%H%M%S)
    
    mkdir -p "$backup_dir"
    
    if [ -f "/private/var/db/.AppleSetupDone" ]; then
        cp "/private/var/db/.AppleSetupDone" "$backup_dir/.AppleSetupDone.auto_backup.$backup_timestamp"
        echo "[$timestamp] Backup created: .AppleSetupDone.auto_backup.$backup_timestamp" >> "$log_file"
    fi
}

send_completion_notification() {
    local notification_title="Roundfleet Setup Assistant"
    local notification_message="Setup Assistant has been configured. Device will restart shortly."
    
    osascript -e "display notification \"$notification_message\" with title \"$notification_title\" sound name \"Glass\""
}

execute_rollback() {
    echo "[$timestamp] Executing rollback due to deployment error" >> "$log_file"
    
    local latest_backup=$(ls -t /var/backups/roundfleet/automated/.AppleSetupDone.auto_backup.* 2>/dev/null | head -1)
    
    if [ -n "$latest_backup" ]; then
        cp "$latest_backup" "/private/var/db/.AppleSetupDone"
        echo "[$timestamp] Rollback completed using backup: $(basename "$latest_backup")" >> "$log_file"
    else
        echo "[$timestamp] No backup available for rollback" >> "$log_file"
    fi
}

# Execute automated deployment
automated_setup_deployment

Troubleshooting and Best Practices

Common Issues and Solutions

1. macOS Version Compatibility

# Check macOS version before execution
os_version=$(sw_vers -productVersion)
major_version=$(echo "$os_version" | cut -d. -f1)

if [ "$major_version" -ge 14 ]; then
    echo "Warning: This script may not work on macOS 14 or later"
    echo "Current version: $os_version"
fi

2. Permission Issues

# Ensure script runs with proper privileges
if [ "$EUID" -ne 0 ]; then
    echo "Error: This script must be run as root"
    echo "Please use: sudo $0"
    exit 1
fi

3. File System Protection

# Check if System Integrity Protection affects operation
csrutil status | grep -q "enabled"
if [ $? -eq 0 ]; then
    echo "Note: SIP is enabled. This may affect script operation."
fi

Best Practices for Setup Assistant Management

  1. Version Compatibility: Always check macOS version compatibility before deployment
  2. User Communication: Notify users before triggering Setup Assistant
  3. Data Backup: Create backups before major configuration changes
  4. Testing: Test scripts in controlled environments before mass deployment
  5. Logging: Maintain detailed logs of all Setup Assistant operations
  6. Rollback Plans: Prepare rollback procedures for deployment failures

Enterprise Deployment Considerations

  • Scheduling: Plan deployments during maintenance windows
  • User Impact: Consider user workflows and minimize disruption
  • Network Requirements: Ensure adequate network connectivity for Apple services
  • Security: Implement appropriate security measures for automated deployments
  • Compliance: Ensure deployments meet organizational compliance requirements

Conclusion

Setup Assistant management is a powerful tool for macOS device administration. These scripts provide comprehensive solutions for triggering, managing, and automating Setup Assistant across Mac fleets. From simple single-device triggers to complex enterprise automation, these tools enable efficient device management while maintaining user experience and organizational compliance.

Remember to test all scripts thoroughly in controlled environments before production deployment, and always maintain proper backups of system configurations. Regular monitoring and logging ensure successful Setup Assistant deployments and help identify potential issues before they impact users.

Set Screen Saver on macOS

Learn how to configure and deploy screen savers on Mac devices using scripts. This allows you to set custom slideshow styles, idle times, and photo sources across your Mac fleet.

Basic Screen Saver Setup

Configure a slideshow screen saver with custom settings:

#!/bin/bash

# Screen saver configuration
STYLE="Ken Burns"
IDLE_TIME=300  # 5 minutes in seconds
SHUFFLE_PHOTOS=true
PHOTOS_PATH="/System/Library/Screen Savers/Default Collections/1-National Geographic"

# Set screen saver style
defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "$STYLE"

# Set idle time before activation
defaults -currentHost write com.apple.screensaver idleTime -int $IDLE_TIME

# Configure photo shuffle
defaults -currentHost write com.apple.screensaver ShufflePhotos -bool $SHUFFLE_PHOTOS

# Set photos folder path
defaults -currentHost write com.apple.screensaver PhotosFolderPath "$PHOTOS_PATH"

echo "Screen saver configured: Style=$STYLE, IdleTime=${IDLE_TIME}s"

Available Screen Saver Styles

Choose from Apple's built-in slideshow styles:

#!/bin/bash

# Available screen saver styles
STYLES=(
    "Floating"
    "Flip-up"
    "Reflections"
    "Origami"
    "Shifting Tiles"
    "Sliding Panels"
    "Photo Mobile"
    "Holiday Mobile"
    "Photo Wall"
    "Vintage Prints"
    "Ken Burns"
    "Classic"
)

# Function to set screen saver style
set_screen_saver_style() {
    local style="$1"
    local idle_time="${2:-600}"  # Default 10 minutes
    local photos_path="${3:-/System/Library/Screen Savers/Default Collections}"
    
    echo "Setting screen saver: $style"
    
    # Configure screen saver
    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 "Screen saver configured successfully"
}

# Example: Set Ken Burns style with 5-minute idle time
set_screen_saver_style "Ken Burns" 300 "/Users/Shared/ScreenSaver Photos"

Interactive Screen Saver Manager

Script with user-friendly interface for configuration:

#!/bin/bash

# Function to display available styles
show_styles() {
    echo "Available Screen Saver Styles:"
    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"
}

# Function to configure screen saver
configure_screen_saver() {
    local style="$1"
    local idle_minutes="$2"
    local shuffle="$3"
    local photos_folder="$4"
    
    local idle_seconds=$((idle_minutes * 60))
    
    # Set all configuration options
    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"
    
    # Kill System Preferences to force refresh
    killall "System Preferences" 2>/dev/null || true
    
    echo "✓ Screen saver configured:"
    echo "  Style: $style"
    echo "  Idle time: $idle_minutes minutes"
    echo "  Shuffle photos: $shuffle"
    echo "  Photos folder: $photos_folder"
}

# Default configuration
STYLE="Ken Burns"
IDLE_MINUTES=10
SHUFFLE_PHOTOS=true
PHOTOS_FOLDER="/System/Library/Screen Savers/Default Collections/1-National Geographic"

# Configure with defaults
configure_screen_saver "$STYLE" "$IDLE_MINUTES" "$SHUFFLE_PHOTOS" "$PHOTOS_FOLDER"

Enterprise Screen Saver Deployment

Deploy standardized screen saver settings across multiple devices:

#!/bin/bash

# Corporate screen saver configuration
CORPORATE_CONFIG() {
    # Company branding configuration
    local style="Classic"
    local idle_time=600  # 10 minutes
    local photos_path="/Library/Desktop Pictures/Corporate"
    local shuffle=false
    
    echo "Deploying corporate screen saver settings..."
    
    # Create corporate photos directory if it doesn't exist
    if [[ ! -d "$photos_path" ]]; then
        sudo mkdir -p "$photos_path"
        echo "Created corporate photos directory: $photos_path"
    fi
    
    # Apply settings
    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"
    
    # Disable screen saver password requirement for corporate environment
    defaults write com.apple.screensaver askForPassword -int 0
    
    echo "Corporate screen saver configuration applied"
    echo "Style: $style | Idle: ${idle_time}s | Shuffle: $shuffle"
}

# Apply corporate configuration
CORPORATE_CONFIG

Screen Saver Status and Management

Check current screen saver settings and manage configuration:

#!/bin/bash

# Function to display current screen saver settings
show_current_settings() {
    echo "=== Current Screen Saver Settings ==="
    
    # Get current style
    local current_style=$(defaults -currentHost read com.apple.screensaver moduleDict 2>/dev/null | grep moduleName | cut -d'"' -f4)
    
    # Get idle time
    local idle_time=$(defaults -currentHost read com.apple.screensaver idleTime 2>/dev/null)
    
    # Get shuffle setting
    local shuffle=$(defaults -currentHost read com.apple.screensaver ShufflePhotos 2>/dev/null)
    
    # Get photos path
    local photos_path=$(defaults -currentHost read com.apple.screensaver PhotosFolderPath 2>/dev/null)
    
    echo "Style: ${current_style:-Not set}"
    echo "Idle time: ${idle_time:-Not set} seconds"
    echo "Shuffle photos: ${shuffle:-Not set}"
    echo "Photos folder: ${photos_path:-Not set}"
}

# Function to disable screen saver
disable_screen_saver() {
    defaults -currentHost write com.apple.screensaver idleTime -int 0
    echo "Screen saver disabled (idle time set to 0)"
}

# Function to enable screen saver with default settings
enable_screen_saver() {
    defaults -currentHost write com.apple.screensaver idleTime -int 600
    defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName "Ken Burns"
    echo "Screen saver enabled with default settings"
}

# Show current settings
show_current_settings

Usage with Roundfleet

  1. Choose your preferred screen saver style from the available options
  2. Set idle time in seconds (0 disables screen saver)
  3. Configure photo shuffle and source folder path
  4. Deploy through Roundfleet's remote script execution
  5. Monitor deployment in action history

Common Photo Paths

LocationPath
Default Collections/System/Library/Screen Savers/Default Collections
Desktop Pictures/Library/Desktop Pictures
User Pictures/Users/username/Pictures
Shared Folder/Users/Shared/ScreenSaver Photos

Troubleshooting

Settings not applied: Kill System Preferences and restart to refresh settings Photos not displaying: Verify folder path exists and contains image files Screen saver not activating: Check idle time setting and system sleep preferences


Note: Changes take effect immediately but may require restarting System Preferences to see in the GUI. Test configuration before mass deployment.