Tutorial

Novas atualizações e melhorias para a Macfleet.

Aviso importante

Os exemplos de código e scripts fornecidos nestes tutoriais são apenas para fins educacionais. A Macfleet não é responsável por quaisquer problemas, danos ou vulnerabilidades de segurança que possam surgir do uso, modificação ou implementação destes exemplos. Sempre revise e teste o código em um ambiente seguro antes de usá-lo em sistemas de produção.

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

Novas atualizações e melhorias para a Macfleet.

Configurando um Runner do GitHub Actions em um Mac Mini (Apple Silicon)

Runner do GitHub Actions

GitHub Actions é uma plataforma poderosa de CI/CD que permite automatizar seus fluxos de trabalho de desenvolvimento de software. Embora o GitHub ofereça runners hospedados, runners auto-hospedados fornecem maior controle e personalização para sua configuração de CI/CD. Este tutorial o guia através da configuração e conexão de um runner auto-hospedado em um Mac mini para executar pipelines do macOS.

Pré-requisitos

Antes de começar, certifique-se de ter:

  • Um Mac mini (registre-se no Macfleet)
  • Um repositório GitHub com direitos de administrador
  • Um gerenciador de pacotes instalado (preferencialmente Homebrew)
  • Git instalado em seu sistema

Passo 1: Criar uma Conta de Usuário Dedicada

Primeiro, crie uma conta de usuário dedicada para o runner do GitHub Actions:

# Criar a conta de usuário 'gh-runner'
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

# Definir a senha para o usuário
sudo dscl . -passwd /Users/gh-runner sua_senha

# Adicionar 'gh-runner' ao grupo 'admin'
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Mude para a nova conta de usuário:

su gh-runner

Passo 2: Instalar Software Necessário

Instale Git e Rosetta 2 (se estiver usando Apple Silicon):

# Instalar Git se ainda não estiver instalado
brew install git

# Instalar Rosetta 2 para Macs Apple Silicon
softwareupdate --install-rosetta

Passo 3: Configurar o Runner do GitHub Actions

  1. Vá para seu repositório GitHub
  2. Navegue para Configurações > Actions > Runners

Runner do GitHub Actions

  1. Clique em "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Selecione macOS como imagem do runner e ARM64 como arquitetura
  3. Siga os comandos fornecidos para baixar e configurar o runner

Runner do GitHub Actions

Crie um arquivo .env no diretório _work do runner:

# arquivo _work/.env
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Execute o script run.sh em seu diretório do runner para completar a configuração.
  2. Verifique se o runner está ativo e ouvindo por trabalhos no terminal e verifique as configurações do repositório GitHub para a associação do runner e status Idle.

Runner do GitHub Actions

Passo 4: Configurar Sudoers (Opcional)

Se suas ações requerem privilégios de root, configure o arquivo sudoers:

sudo visudo

Adicione a seguinte linha:

gh-runner ALL=(ALL) NOPASSWD: ALL

Passo 5: Usar o Runner em Fluxos de Trabalho

Configure seu fluxo de trabalho do GitHub Actions para usar o runner auto-hospedado:

name: Fluxo de trabalho de exemplo

on:
  workflow_dispatch:

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

O runner está autenticado em seu repositório e rotulado com self-hosted, macOS, e ARM64. Use-o em seus fluxos de trabalho especificando estes rótulos no campo runs-on:

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

Melhores Práticas

  • Mantenha seu software do runner atualizado
  • Monitore regularmente os logs do runner para problemas
  • Use rótulos específicos para diferentes tipos de runners
  • Implemente medidas de segurança adequadas
  • Considere usar múltiplos runners para balanceamento de carga

Solução de Problemas

Problemas comuns e soluções:

  1. Runner não conectando:

    • Verifique conectividade de rede
    • Verifique validade do token GitHub
    • Certifique-se de permissões adequadas
  2. Falhas de build:

    • Verifique instalação do Xcode
    • Verifique dependências necessárias
    • Revise logs do fluxo de trabalho
  3. Problemas de permissão:

    • Verifique permissões do usuário
    • Verifique configuração sudoers
    • Revise permissões do sistema de arquivos

Conclusão

Agora você tem um runner auto-hospedado do GitHub Actions configurado em seu Mac mini. Esta configuração fornece mais controle sobre seu ambiente CI/CD e permite executar fluxos de trabalho específicos do macOS de forma eficiente.

Lembre-se de manter regularmente seu runner e mantê-lo atualizado com os patches de segurança e versões de software mais recentes.

Aplicativo Nativo

Aplicativo nativo do Macfleet

Guia de Instalação do Macfleet

Macfleet é uma solução poderosa de gerenciamento de frota projetada especificamente para ambientes Mac Mini hospedados na nuvem. Como provedor de hospedagem na nuvem Mac Mini, você pode usar o Macfleet para monitorar, gerenciar e otimizar toda sua frota de instâncias Mac virtualizadas.

Este guia de instalação o conduzirá através da configuração do monitoramento do Macfleet em sistemas macOS, Windows e Linux para garantir supervisão abrangente de sua infraestrutura na nuvem.

🍎 macOS

  • Baixe o arquivo .dmg para Mac aqui
  • Clique duas vezes no arquivo .dmg baixado
  • Arraste o aplicativo Macfleet para a pasta Aplicativos
  • Ejete o arquivo .dmg
  • Abra Preferências do Sistema > Segurança e Privacidade
    • Aba Privacidade > Acessibilidade
    • Marque Macfleet para permitir monitoramento
  • Inicie o Macfleet a partir de Aplicativos
  • O rastreamento inicia automaticamente

🪟 Windows

  • Baixe o arquivo .exe para Windows aqui
  • Clique com o botão direito no arquivo .exe > "Executar como administrador"
  • Siga o assistente de instalação
  • Aceite os termos e condições
  • Permita no Windows Defender se solicitado
  • Conceda permissões de monitoramento de aplicativo
  • Inicie o Macfleet a partir do Menu Iniciar
  • O aplicativo começa o rastreamento automaticamente

🐧 Linux

  • Baixe o pacote .deb (Ubuntu/Debian) ou .rpm (CentOS/RHEL) aqui
  • Instale usando seu gerenciador de pacotes
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Permita permissões de acesso X11 se solicitado
  • Adicione o usuário aos grupos apropriados se necessário
  • Inicie o Macfleet a partir do menu Aplicativos
  • O aplicativo começa o rastreamento automaticamente

Nota: Após a instalação em todos os sistemas, faça login com suas credenciais do Macfleet para sincronizar dados com seu painel de controle.