Tutorial

Neue Updates und Verbesserungen zu Macfleet.

Wichtiger Hinweis

Die in diesen Tutorials bereitgestellten Codebeispiele und Skripte dienen nur zu Bildungszwecken. Macfleet ist nicht verantwortlich für Probleme, Schäden oder Sicherheitslücken, die durch die Verwendung, Änderung oder Implementierung dieser Beispiele entstehen können. Überprüfen und testen Sie Code immer in einer sicheren Umgebung, bevor Sie ihn in Produktionssystemen verwenden.

Shutdown and Reboot Management for macOS

Implement enterprise-grade shutdown and reboot management across your MacFleet 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

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

# Configuration
CONFIG_FILE="/etc/macfleet/shutdown_policy.conf"
LOG_FILE="/var/log/macfleet_shutdown.log"
SCHEDULES_DIR="/Library/MacFleet/ShutdownSchedules"
AUDIT_LOG="/var/log/macfleet_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
# MacFleet 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="MacFleet 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/MacFleet/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 "=== MacFleet 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 "MacFleet 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/MacFleet/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/MacFleet/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.macfleet.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.macfleet.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 MacFleet to ensure business continuity and data protection. 

Tutorial

Neue Updates und Verbesserungen zu Macfleet.

Konfiguration eines GitHub Actions Runners auf einem Mac Mini (Apple Silicon)

GitHub Actions Runner

GitHub Actions ist eine leistungsstarke CI/CD-Plattform, die es Ihnen ermöglicht, Ihre Software-Entwicklungsworkflows zu automatisieren. Während GitHub gehostete Runner anbietet, bieten selbst-gehostete Runner erhöhte Kontrolle und Anpassung für Ihr CI/CD-Setup. Dieses Tutorial führt Sie durch die Einrichtung, Konfiguration und Verbindung eines selbst-gehosteten Runners auf einem Mac mini zur Ausführung von macOS-Pipelines.

Voraussetzungen

Bevor Sie beginnen, stellen Sie sicher, dass Sie haben:

  • Einen Mac mini (registrieren Sie sich bei Macfleet)
  • Ein GitHub-Repository mit Administratorrechten
  • Einen installierten Paketmanager (vorzugsweise Homebrew)
  • Git auf Ihrem System installiert

Schritt 1: Ein dediziertes Benutzerkonto erstellen

Erstellen Sie zunächst ein dediziertes Benutzerkonto für den GitHub Actions Runner:

# Das 'gh-runner' Benutzerkonto erstellen
sudo dscl . -create /Users/gh-runner
sudo dscl . -create /Users/gh-runner UserShell /bin/bash
sudo dscl . -create /Users/gh-runner RealName "GitHub runner"
sudo dscl . -create /Users/gh-runner UniqueID "1001"
sudo dscl . -create /Users/gh-runner PrimaryGroupID 20
sudo dscl . -create /Users/gh-runner NFSHomeDirectory /Users/gh-runner

# Das Passwort für den Benutzer setzen
sudo dscl . -passwd /Users/gh-runner ihr_passwort

# 'gh-runner' zur 'admin'-Gruppe hinzufügen
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Wechseln Sie zum neuen Benutzerkonto:

su gh-runner

Schritt 2: Erforderliche Software installieren

Installieren Sie Git und Rosetta 2 (wenn Sie Apple Silicon verwenden):

# Git installieren, falls noch nicht installiert
brew install git

# Rosetta 2 für Apple Silicon Macs installieren
softwareupdate --install-rosetta

Schritt 3: Den GitHub Actions Runner konfigurieren

  1. Gehen Sie zu Ihrem GitHub-Repository
  2. Navigieren Sie zu Einstellungen > Actions > Runners

GitHub Actions Runner

  1. Klicken Sie auf "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Wählen Sie macOS als Runner-Image und ARM64 als Architektur
  3. Folgen Sie den bereitgestellten Befehlen, um den Runner herunterzuladen und zu konfigurieren

GitHub Actions Runner

Erstellen Sie eine .env-Datei im _work-Verzeichnis des Runners:

# _work/.env Datei
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Führen Sie das run.sh-Skript in Ihrem Runner-Verzeichnis aus, um die Einrichtung abzuschließen.
  2. Überprüfen Sie, dass der Runner aktiv ist und auf Jobs im Terminal wartet, und überprüfen Sie die GitHub-Repository-Einstellungen für die Runner-Zuordnung und den Idle-Status.

GitHub Actions Runner

Schritt 4: Sudoers konfigurieren (Optional)

Wenn Ihre Actions Root-Privilegien benötigen, konfigurieren Sie die sudoers-Datei:

sudo visudo

Fügen Sie die folgende Zeile hinzu:

gh-runner ALL=(ALL) NOPASSWD: ALL

Schritt 5: Den Runner in Workflows verwenden

Konfigurieren Sie Ihren GitHub Actions Workflow, um den selbst-gehosteten Runner zu verwenden:

name: Beispiel-Workflow

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: [self-hosted, macOS, ARM64]
    steps:
      - name: NodeJS installieren
        run: brew install node

Der Runner ist bei Ihrem Repository authentifiziert und mit self-hosted, macOS und ARM64 markiert. Verwenden Sie ihn in Ihren Workflows, indem Sie diese Labels im runs-on-Feld angeben:

runs-on: [self-hosted, macOS, ARM64]

Best Practices

  • Halten Sie Ihre Runner-Software auf dem neuesten Stand
  • Überwachen Sie regelmäßig Runner-Logs auf Probleme
  • Verwenden Sie spezifische Labels für verschiedene Runner-Typen
  • Implementieren Sie angemessene Sicherheitsmaßnahmen
  • Erwägen Sie die Verwendung mehrerer Runner für Lastverteilung

Fehlerbehebung

Häufige Probleme und Lösungen:

  1. Runner verbindet sich nicht:

    • Überprüfen Sie die Netzwerkverbindung
    • Überprüfen Sie die Gültigkeit des GitHub-Tokens
    • Stellen Sie angemessene Berechtigungen sicher
  2. Build-Fehler:

    • Überprüfen Sie die Xcode-Installation
    • Überprüfen Sie erforderliche Abhängigkeiten
    • Überprüfen Sie Workflow-Logs
  3. Berechtigungsprobleme:

    • Überprüfen Sie Benutzerberechtigungen
    • Überprüfen Sie sudoers-Konfiguration
    • Überprüfen Sie Dateisystem-Berechtigungen

Fazit

Sie haben jetzt einen selbst-gehosteten GitHub Actions Runner auf Ihrem Mac mini konfiguriert. Diese Einrichtung bietet Ihnen mehr Kontrolle über Ihre CI/CD-Umgebung und ermöglicht es Ihnen, macOS-spezifische Workflows effizient auszuführen.

Denken Sie daran, Ihren Runner regelmäßig zu warten und ihn mit den neuesten Sicherheitspatches und Software-Versionen auf dem neuesten Stand zu halten.

Native App

Macfleet native App

Macfleet Installationsanleitung

Macfleet ist eine leistungsstarke Flottenmanagement-Lösung, die speziell für Cloud-gehostete Mac Mini-Umgebungen entwickelt wurde. Als Mac Mini Cloud-Hosting-Anbieter können Sie Macfleet verwenden, um Ihre gesamte Flotte virtualisierter Mac-Instanzen zu überwachen, zu verwalten und zu optimieren.

Diese Installationsanleitung führt Sie durch die Einrichtung der Macfleet-Überwachung auf macOS-, Windows- und Linux-Systemen, um eine umfassende Übersicht über Ihre Cloud-Infrastruktur zu gewährleisten.

🍎 macOS

  • Laden Sie die .dmg-Datei für Mac hier herunter
  • Doppelklicken Sie auf die heruntergeladene .dmg-Datei
  • Ziehen Sie die Macfleet-App in den Anwendungsordner
  • Werfen Sie die .dmg-Datei aus
  • Öffnen Sie Systemeinstellungen > Sicherheit & Datenschutz
    • Datenschutz-Tab > Bedienungshilfen
    • Aktivieren Sie Macfleet, um Überwachung zu erlauben
  • Starten Sie Macfleet aus den Anwendungen
  • Die Verfolgung startet automatisch

🪟 Windows

  • Laden Sie die .exe-Datei für Windows hier herunter
  • Rechtsklick auf die .exe-Datei > "Als Administrator ausführen"
  • Folgen Sie dem Installationsassistenten
  • Akzeptieren Sie die Allgemeinen Geschäftsbedingungen
  • Erlauben Sie in Windows Defender, wenn aufgefordert
  • Gewähren Sie Anwendungsüberwachungsberechtigungen
  • Starten Sie Macfleet aus dem Startmenü
  • Die Anwendung beginnt automatisch mit der Verfolgung

🐧 Linux

  • Laden Sie das .deb-Paket (Ubuntu/Debian) oder .rpm (CentOS/RHEL) hier herunter
  • Installieren Sie mit Ihrem Paketmanager
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Erlauben Sie X11-Zugriffsberechtigungen, wenn aufgefordert
  • Fügen Sie den Benutzer zu entsprechenden Gruppen hinzu, falls erforderlich
  • Starten Sie Macfleet aus dem Anwendungsmenü
  • Die Anwendung beginnt automatisch mit der Verfolgung

Hinweis: Nach der Installation auf allen Systemen melden Sie sich mit Ihren Macfleet-Anmeldedaten an, um Daten mit Ihrem Dashboard zu synchronisieren.