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.

Battery Charging Limit Management on macOS

Manage battery charging limits across your MacFleet devices to optimize battery health and implement enterprise power management policies. This tutorial covers installation of battery management tools, charging limit configuration, persistence settings, and comprehensive fleet-wide battery health monitoring.

Understanding Battery Charging Limits

Battery charging limits help preserve battery health by preventing overcharging, especially beneficial for devices that remain plugged in continuously:

Why Set Charging Limits?

  • Battery Longevity - Prevents degradation from constant 100% charge
  • Heat Reduction - Lower charge levels generate less heat during operation
  • Enterprise Cost Savings - Extended battery life reduces replacement costs
  • Power Management - Optimized charging for stationary workstations
  • Environmental Benefits - Longer battery life reduces electronic waste

Battery Management Tools

  • bclm - Battery Charge Limit Max (primary tool)
  • SMC - System Management Controller (hardware interface)
  • Homebrew - Package manager for macOS tools
  • Power Management - Built-in macOS power controls

Prerequisites and Installation

Install Homebrew Package Manager

#!/bin/bash

# Install Homebrew package manager
echo "🍺 Installing Homebrew package manager..."

# Check if Homebrew is already installed
if command -v brew >/dev/null 2>&1; then
    echo "ℹ️ Homebrew is already installed"
    echo "Homebrew version: $(brew --version | head -1)"
else
    echo "Installing Homebrew..."
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Homebrew installed successfully"
    else
        echo "❌ Homebrew installation failed"
        exit 1
    fi
fi

# Verify installation and add to PATH if needed
if [[ -f /opt/homebrew/bin/brew ]]; then
    echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
    eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -f /usr/local/bin/brew ]]; then
    echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zprofile
    eval "$(/usr/local/bin/brew shellenv)"
fi

echo "Homebrew location: $(which brew)"

Install BCLM (Battery Charge Limit Max)

#!/bin/bash

# Install bclm (Battery Charge Limit Max)
echo "🔋 Installing bclm (Battery Charge Limit Max)..."

# Ensure Homebrew is available
if ! command -v brew >/dev/null 2>&1; then
    echo "❌ Homebrew not found. Please install Homebrew first."
    exit 1
fi

# Install bclm
echo "Adding zackelia/formulae tap..."
if brew tap zackelia/formulae; then
    echo "✅ Tap added successfully"
else
    echo "❌ Failed to add tap"
    exit 1
fi

echo "Installing bclm..."
if brew install bclm; then
    echo "✅ bclm installed successfully"
else
    echo "❌ bclm installation failed"
    exit 1
fi

# Verify installation
if command -v bclm >/dev/null 2>&1; then
    echo "bclm location: $(which bclm)"
    echo "Testing bclm access..."
    
    # Test read access (doesn't require sudo)
    if bclm read >/dev/null 2>&1; then
        echo "✅ bclm is working correctly"
        echo "Current charging limit: $(bclm read)%"
    else
        echo "⚠️ bclm installed but may require additional permissions"
    fi
else
    echo "❌ bclm not found in PATH"
    exit 1
fi

Basic Charging Limit Management

Set Charging Limit

#!/bin/bash

# Set battery charging limit
LIMIT="$1"

if [[ -z "$LIMIT" ]]; then
    echo "❌ Usage: $0 <percentage>"
    echo "Example: $0 80"
    echo "Valid range: 50-100"
    exit 1
fi

# Validate limit range
if [[ "$LIMIT" -lt 50 || "$LIMIT" -gt 100 ]]; then
    echo "❌ Invalid limit: $LIMIT"
    echo "Charging limit must be between 50% and 100%"
    exit 1
fi

echo "🔋 Setting battery charging limit to $LIMIT%..."

# Get current limit for comparison
CURRENT_LIMIT=$(bclm read 2>/dev/null)
if [[ -n "$CURRENT_LIMIT" ]]; then
    echo "Current limit: $CURRENT_LIMIT%"
fi

# Set new charging limit
if sudo bclm write "$LIMIT"; then
    echo "✅ Charging limit set to $LIMIT%"
    
    # Verify the setting
    NEW_LIMIT=$(bclm read 2>/dev/null)
    if [[ "$NEW_LIMIT" == "$LIMIT" ]]; then
        echo "✅ Setting verified: $NEW_LIMIT%"
    else
        echo "⚠️ Warning: Verification shows $NEW_LIMIT% instead of $LIMIT%"
    fi
else
    echo "❌ Failed to set charging limit"
    exit 1
fi

echo "ℹ️ Note: Restart may be required for changes to take effect"

Read Current Charging Limit

#!/bin/bash

# Read current battery charging limit
echo "🔍 Reading current battery charging limit..."

if command -v bclm >/dev/null 2>&1; then
    CURRENT_LIMIT=$(bclm read 2>/dev/null)
    
    if [[ -n "$CURRENT_LIMIT" ]]; then
        echo "Current charging limit: $CURRENT_LIMIT%"
        
        # Provide context about the limit
        if [[ "$CURRENT_LIMIT" -eq 100 ]]; then
            echo "ℹ️ Battery charges to maximum capacity (no limit set)"
        elif [[ "$CURRENT_LIMIT" -ge 80 ]]; then
            echo "ℹ️ Conservative charging limit for battery longevity"
        elif [[ "$CURRENT_LIMIT" -ge 60 ]]; then
            echo "ℹ️ Moderate charging limit for extended battery life"
        else
            echo "ℹ️ Aggressive charging limit for maximum battery preservation"
        fi
    else
        echo "❌ Unable to read charging limit"
        echo "This may indicate bclm is not properly installed or lacks permissions"
        exit 1
    fi
else
    echo "❌ bclm not found. Please install bclm first."
    exit 1
fi

Make Charging Limit Persistent

#!/bin/bash

# Make charging limit persistent across reboots
echo "💾 Making charging limit persistent..."

if ! command -v bclm >/dev/null 2>&1; then
    echo "❌ bclm not found. Please install bclm first."
    exit 1
fi

# Get current limit
CURRENT_LIMIT=$(bclm read 2>/dev/null)
if [[ -z "$CURRENT_LIMIT" ]]; then
    echo "❌ Unable to read current charging limit"
    exit 1
fi

echo "Current charging limit: $CURRENT_LIMIT%"

# Make persistent
if sudo bclm persist; then
    echo "✅ Charging limit ($CURRENT_LIMIT%) is now persistent"
    echo "The limit will be maintained across system reboots"
else
    echo "❌ Failed to make charging limit persistent"
    exit 1
fi

echo "ℹ️ To remove persistence, run: sudo bclm unpersist"

Remove Charging Limit Persistence

#!/bin/bash

# Remove charging limit persistence
echo "🔄 Removing charging limit persistence..."

if ! command -v bclm >/dev/null 2>&1; then
    echo "❌ bclm not found. Please install bclm first."
    exit 1
fi

# Get current limit before removing persistence
CURRENT_LIMIT=$(bclm read 2>/dev/null)
if [[ -n "$CURRENT_LIMIT" ]]; then
    echo "Current charging limit: $CURRENT_LIMIT%"
fi

# Remove persistence
if sudo bclm unpersist; then
    echo "✅ Charging limit persistence removed"
    echo "The limit may reset to 100% after next reboot"
else
    echo "❌ Failed to remove charging limit persistence"
    exit 1
fi

echo "ℹ️ To restore persistence, run: sudo bclm persist"

Advanced Battery Management

Enterprise Battery Health Check

#!/bin/bash

# Comprehensive battery health assessment
echo "🔋 Performing comprehensive battery health check..."

# Check if battery is present
if ! system_profiler SPPowerDataType | grep -q "Battery Information"; then
    echo "❌ No battery found on this system"
    exit 1
fi

echo "=== Battery Health Assessment ==="

# Get battery information
BATTERY_INFO=$(system_profiler SPPowerDataType)

# Extract key metrics
CYCLE_COUNT=$(echo "$BATTERY_INFO" | grep "Cycle Count" | awk '{print $3}')
CONDITION=$(echo "$BATTERY_INFO" | grep "Condition" | awk '{print $2}')
MAX_CAPACITY=$(echo "$BATTERY_INFO" | grep "Maximum Capacity" | awk '{print $3}' | sed 's/%//')

echo "Battery Condition: $CONDITION"
echo "Cycle Count: $CYCLE_COUNT"
echo "Maximum Capacity: $MAX_CAPACITY%"

# Check charging limit if bclm is available
if command -v bclm >/dev/null 2>&1; then
    CHARGING_LIMIT=$(bclm read 2>/dev/null)
    if [[ -n "$CHARGING_LIMIT" ]]; then
        echo "Charging Limit: $CHARGING_LIMIT%"
    else
        echo "Charging Limit: Not set (100%)"
    fi
fi

# Power adapter information
POWER_ADAPTER=$(echo "$BATTERY_INFO" | grep -A5 "AC Charger Information" | grep "Wattage" | awk '{print $2}')
if [[ -n "$POWER_ADAPTER" ]]; then
    echo "Power Adapter: ${POWER_ADAPTER}W"
fi

# Health assessment
echo -e "\n=== Health Assessment ==="

if [[ "$CONDITION" == "Normal" ]]; then
    echo "✅ Battery condition is normal"
elif [[ "$CONDITION" == "Replace Soon" ]]; then
    echo "⚠️ Battery should be replaced soon"
elif [[ "$CONDITION" == "Replace Now" ]]; then
    echo "❌ Battery needs immediate replacement"
else
    echo "ℹ️ Battery condition: $CONDITION"
fi

if [[ -n "$CYCLE_COUNT" ]]; then
    if [[ "$CYCLE_COUNT" -lt 500 ]]; then
        echo "✅ Cycle count is healthy ($CYCLE_COUNT cycles)"
    elif [[ "$CYCLE_COUNT" -lt 1000 ]]; then
        echo "⚠️ Moderate cycle count ($CYCLE_COUNT cycles)"
    else
        echo "❌ High cycle count ($CYCLE_COUNT cycles)"
    fi
fi

if [[ -n "$MAX_CAPACITY" ]]; then
    if [[ "$MAX_CAPACITY" -ge 90 ]]; then
        echo "✅ Maximum capacity is excellent ($MAX_CAPACITY%)"
    elif [[ "$MAX_CAPACITY" -ge 80 ]]; then
        echo "✅ Maximum capacity is good ($MAX_CAPACITY%)"
    elif [[ "$MAX_CAPACITY" -ge 70 ]]; then
        echo "⚠️ Maximum capacity is declining ($MAX_CAPACITY%)"
    else
        echo "❌ Maximum capacity is poor ($MAX_CAPACITY%)"
    fi
fi

# Recommendations
echo -e "\n=== Recommendations ==="

if [[ -z "$CHARGING_LIMIT" || "$CHARGING_LIMIT" -eq 100 ]]; then
    echo "💡 Consider setting a charging limit (80-90%) for better battery health"
fi

if [[ "$CYCLE_COUNT" -gt 1000 && "$MAX_CAPACITY" -lt 80 ]]; then
    echo "💡 Battery replacement may be needed soon"
fi

Optimized Charging Limit Recommendations

#!/bin/bash

# Provide charging limit recommendations based on usage patterns
echo "🎯 Analyzing optimal charging limit recommendations..."

# Get device model and usage information
DEVICE_MODEL=$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F': ' '{print $2}')
UPTIME=$(uptime | awk '{print $3}' | sed 's/,//')

echo "Device: $DEVICE_MODEL"
echo "Current uptime: $UPTIME"

# Check if device is primarily plugged in
AC_POWER_COUNT=$(pmset -g log | grep -c "Using AC" 2>/dev/null || echo "0")
BATTERY_POWER_COUNT=$(pmset -g log | grep -c "Using Batt" 2>/dev/null || echo "0")

echo -e "\n=== Usage Pattern Analysis ==="

if [[ "$AC_POWER_COUNT" -gt "$BATTERY_POWER_COUNT" ]]; then
    USAGE_TYPE="Desktop/Stationary"
    RECOMMENDED_LIMIT=80
    echo "Usage pattern: Primarily AC powered"
    echo "Recommendation: Set charging limit to $RECOMMENDED_LIMIT%"
else
    USAGE_TYPE="Mobile/Portable"
    RECOMMENDED_LIMIT=90
    echo "Usage pattern: Frequently on battery"
    echo "Recommendation: Set charging limit to $RECOMMENDED_LIMIT%"
fi

# Get current battery health
BATTERY_CONDITION=$(system_profiler SPPowerDataType | grep "Condition" | awk '{print $2}')
MAX_CAPACITY=$(system_profiler SPPowerDataType | grep "Maximum Capacity" | awk '{print $3}' | sed 's/%//')

if [[ -n "$MAX_CAPACITY" && "$MAX_CAPACITY" -lt 85 ]]; then
    RECOMMENDED_LIMIT=75
    echo "⚠️ Battery health is declining, recommended limit: $RECOMMENDED_LIMIT%"
fi

# Check current setting
if command -v bclm >/dev/null 2>&1; then
    CURRENT_LIMIT=$(bclm read 2>/dev/null)
    
    if [[ -n "$CURRENT_LIMIT" ]]; then
        echo "Current limit: $CURRENT_LIMIT%"
        
        if [[ "$CURRENT_LIMIT" -eq "$RECOMMENDED_LIMIT" ]]; then
            echo "✅ Current setting is optimal"
        else
            echo "💡 Consider adjusting to $RECOMMENDED_LIMIT% for optimal battery health"
        fi
    else
        echo "Current limit: Not set (100%)"
        echo "💡 Recommended action: Set charging limit to $RECOMMENDED_LIMIT%"
    fi
fi

echo -e "\n=== Implementation Command ==="
echo "To set recommended limit: sudo bclm write $RECOMMENDED_LIMIT"
echo "To make persistent: sudo bclm persist"

Enterprise Battery Management Script

#!/bin/bash

# MacFleet Battery Management Tool
# Comprehensive battery charging limit management for enterprise environments

# Configuration
LOG_FILE="/var/log/macfleet_battery.log"
BACKUP_DIR="/var/backups/macfleet/battery"
REPORT_DIR="/var/reports/macfleet/battery"
CONFIG_FILE="/etc/macfleet/battery_policy.conf"

# Battery policy settings
DEFAULT_CHARGING_LIMIT=80
MOBILE_DEVICE_LIMIT=90
STATIONARY_DEVICE_LIMIT=75
ENFORCE_BATTERY_POLICY=false
HEALTH_CHECK_ENABLED=true
ALERT_CAPACITY_THRESHOLD=80
ALERT_CYCLE_THRESHOLD=1000

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

# Setup directories
setup_directories() {
    for dir in "$BACKUP_DIR" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")"; do
        if [[ ! -d "$dir" ]]; then
            sudo mkdir -p "$dir"
            log_action "Created directory: $dir"
        fi
    done
}

# Check if device has a battery
check_battery_presence() {
    if system_profiler SPPowerDataType | grep -q "Battery Information"; then
        return 0
    else
        echo "❌ No battery found on this system"
        log_action "No battery detected on device"
        return 1
    fi
}

# Install battery management tools
install_battery_tools() {
    echo "🔧 Installing battery management tools..."
    log_action "Battery tools installation started"
    
    # Check and install Homebrew
    if ! command -v brew >/dev/null 2>&1; then
        echo "Installing Homebrew..."
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
        
        # Add to PATH
        if [[ -f /opt/homebrew/bin/brew ]]; then
            eval "$(/opt/homebrew/bin/brew shellenv)"
        elif [[ -f /usr/local/bin/brew ]]; then
            eval "$(/usr/local/bin/brew shellenv)"
        fi
    fi
    
    # Install bclm
    if ! command -v bclm >/dev/null 2>&1; then
        echo "Installing bclm..."
        brew tap zackelia/formulae && brew install bclm
        
        if command -v bclm >/dev/null 2>&1; then
            echo "✅ bclm installed successfully"
            log_action "bclm installed successfully"
        else
            echo "❌ bclm installation failed"
            log_action "bclm installation failed"
            return 1
        fi
    else
        echo "✅ bclm already installed"
    fi
    
    return 0
}

# Generate comprehensive battery report
generate_battery_report() {
    local report_file="$REPORT_DIR/battery_report_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "📊 Generating comprehensive battery report..."
    
    {
        echo "MacFleet Battery Management Report"
        echo "Generated: $(date)"
        echo "Device: $(hostname)"
        echo "================================="
        echo ""
        
        # System information
        echo "=== System Information ==="
        system_profiler SPHardwareDataType | grep -E "Model Name|Model Identifier|Processor|Memory"
        echo ""
        
        # Battery hardware information
        echo "=== Battery Hardware Information ==="
        local battery_info=$(system_profiler SPPowerDataType)
        echo "$battery_info" | grep -E "Condition|Cycle Count|Maximum Capacity|Manufacturer|Device Name|Pack Lot Code|PCB Lot Code|Firmware Version|Hardware Revision"
        echo ""
        
        # Current charging limit
        echo "=== Charging Limit Configuration ==="
        if command -v bclm >/dev/null 2>&1; then
            local current_limit=$(bclm read 2>/dev/null)
            if [[ -n "$current_limit" ]]; then
                echo "Current charging limit: $current_limit%"
                
                # Check if persistent
                local smc_value=$(sudo bclm read 2>/dev/null)
                if [[ "$smc_value" == "$current_limit" ]]; then
                    echo "Persistence status: Enabled"
                else
                    echo "Persistence status: Disabled"
                fi
            else
                echo "Current charging limit: Not set (100%)"
                echo "Persistence status: N/A"
            fi
        else
            echo "bclm status: Not installed"
        fi
        echo ""
        
        # Power usage analysis
        echo "=== Power Usage Analysis ==="
        echo "Power adapter connected: $(system_profiler SPPowerDataType | grep -q "AC Charger Information" && echo "Yes" || echo "No")"
        
        # Get power adapter info if available
        local adapter_info=$(system_profiler SPPowerDataType | grep -A3 "AC Charger Information" | grep "Wattage")
        if [[ -n "$adapter_info" ]]; then
            echo "Power adapter: $(echo "$adapter_info" | awk '{print $2}')W"
        fi
        
        # Battery temperature and voltage
        echo "Battery temperature: $(ioreg -l | grep Temperature | awk '{print $3/100}' | head -1)°C"
        echo "Battery voltage: $(ioreg -l | grep Voltage | awk '{print $3/1000}' | head -1)V"
        echo ""
        
        # Health assessment
        echo "=== Battery Health Assessment ==="
        local condition=$(echo "$battery_info" | grep "Condition" | awk '{print $2}')
        local cycle_count=$(echo "$battery_info" | grep "Cycle Count" | awk '{print $3}')
        local max_capacity=$(echo "$battery_info" | grep "Maximum Capacity" | awk '{print $3}' | sed 's/%//')
        
        echo "Overall condition: $condition"
        echo "Cycle count: $cycle_count"
        echo "Maximum capacity: $max_capacity%"
        
        # Health scoring
        local health_score=100
        
        if [[ "$condition" != "Normal" ]]; then
            health_score=$((health_score - 20))
        fi
        
        if [[ -n "$cycle_count" ]]; then
            if [[ "$cycle_count" -gt 1000 ]]; then
                health_score=$((health_score - 20))
            elif [[ "$cycle_count" -gt 500 ]]; then
                health_score=$((health_score - 10))
            fi
        fi
        
        if [[ -n "$max_capacity" ]]; then
            if [[ "$max_capacity" -lt 70 ]]; then
                health_score=$((health_score - 30))
            elif [[ "$max_capacity" -lt 80 ]]; then
                health_score=$((health_score - 20))
            elif [[ "$max_capacity" -lt 90 ]]; then
                health_score=$((health_score - 10))
            fi
        fi
        
        echo "Health score: $health_score/100"
        
        # Recommendations
        echo ""
        echo "=== Recommendations ==="
        
        if [[ "$health_score" -ge 80 ]]; then
            echo "✅ Battery health is good"
            echo "💡 Consider setting charging limit to 80% for optimal longevity"
        elif [[ "$health_score" -ge 60 ]]; then
            echo "⚠️ Battery health is declining"
            echo "💡 Set charging limit to 75% and monitor closely"
        else
            echo "❌ Battery health is poor"
            echo "💡 Consider battery replacement and immediate charging limit to 70%"
        fi
        
        # Policy compliance check
        if [[ "$ENFORCE_BATTERY_POLICY" == "true" ]]; then
            echo ""
            echo "=== Policy Compliance ==="
            echo "Battery policy enforcement: ENABLED"
            echo "Default charging limit: $DEFAULT_CHARGING_LIMIT%"
            
            if [[ -n "$current_limit" ]]; then
                if [[ "$current_limit" -eq "$DEFAULT_CHARGING_LIMIT" ]]; then
                    echo "Compliance status: ✅ COMPLIANT"
                else
                    echo "Compliance status: ❌ NON-COMPLIANT"
                    echo "Current: $current_limit%, Required: $DEFAULT_CHARGING_LIMIT%"
                fi
            else
                echo "Compliance status: ❌ NON-COMPLIANT (no limit set)"
            fi
        fi
        
    } > "$report_file"
    
    echo "📊 Report saved to: $report_file"
    log_action "Battery report generated: $report_file"
}

# Set optimal charging limit based on usage pattern
set_optimal_charging_limit() {
    local force_limit="$1"
    
    echo "🎯 Determining optimal charging limit..."
    
    if ! check_battery_presence; then
        return 1
    fi
    
    # Install tools if needed
    if ! command -v bclm >/dev/null 2>&1; then
        if ! install_battery_tools; then
            echo "❌ Failed to install required tools"
            return 1
        fi
    fi
    
    local recommended_limit="$DEFAULT_CHARGING_LIMIT"
    
    # Override with forced limit if provided
    if [[ -n "$force_limit" ]]; then
        recommended_limit="$force_limit"
        echo "Using forced limit: $recommended_limit%"
    else
        # Analyze usage pattern
        echo "Analyzing device usage pattern..."
        
        # Check if device is primarily stationary (simplified detection)
        local model=$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F': ' '{print $2}')
        if echo "$model" | grep -qi "mac studio\|mac pro\|imac"; then
            recommended_limit="$STATIONARY_DEVICE_LIMIT"
            echo "Detected stationary device, recommended limit: $recommended_limit%"
        else
            recommended_limit="$MOBILE_DEVICE_LIMIT"
            echo "Detected mobile device, recommended limit: $recommended_limit%"
        fi
        
        # Adjust based on battery health
        local max_capacity=$(system_profiler SPPowerDataType | grep "Maximum Capacity" | awk '{print $3}' | sed 's/%//')
        if [[ -n "$max_capacity" && "$max_capacity" -lt 85 ]]; then
            recommended_limit=75
            echo "Adjusted for battery health: $recommended_limit%"
        fi
    fi
    
    # Set the charging limit
    echo "Setting charging limit to $recommended_limit%..."
    
    if sudo bclm write "$recommended_limit"; then
        echo "✅ Charging limit set to $recommended_limit%"
        
        # Make persistent
        if sudo bclm persist; then
            echo "✅ Charging limit made persistent"
            log_action "Charging limit set to $recommended_limit% and made persistent"
        else
            echo "⚠️ Failed to make charging limit persistent"
            log_action "Charging limit set to $recommended_limit% but persistence failed"
        fi
        
        # Verify setting
        local verify_limit=$(bclm read 2>/dev/null)
        if [[ "$verify_limit" == "$recommended_limit" ]]; then
            echo "✅ Setting verified: $verify_limit%"
        else
            echo "⚠️ Verification failed: expected $recommended_limit%, got $verify_limit%"
        fi
    else
        echo "❌ Failed to set charging limit"
        log_action "Failed to set charging limit to $recommended_limit%"
        return 1
    fi
}

# Monitor battery health and alert on issues
monitor_battery_health() {
    echo "🔍 Monitoring battery health..."
    
    if ! check_battery_presence; then
        return 1
    fi
    
    local battery_info=$(system_profiler SPPowerDataType)
    local condition=$(echo "$battery_info" | grep "Condition" | awk '{print $2}')
    local cycle_count=$(echo "$battery_info" | grep "Cycle Count" | awk '{print $3}')
    local max_capacity=$(echo "$battery_info" | grep "Maximum Capacity" | awk '{print $3}' | sed 's/%//')
    
    local alerts_triggered=0
    
    # Check condition
    if [[ "$condition" != "Normal" ]]; then
        echo "🚨 ALERT: Battery condition is $condition"
        log_action "ALERT: Battery condition is $condition"
        ((alerts_triggered++))
    fi
    
    # Check cycle count
    if [[ -n "$cycle_count" && "$cycle_count" -gt "$ALERT_CYCLE_THRESHOLD" ]]; then
        echo "🚨 ALERT: High cycle count - $cycle_count cycles"
        log_action "ALERT: High cycle count - $cycle_count cycles"
        ((alerts_triggered++))
    fi
    
    # Check capacity
    if [[ -n "$max_capacity" && "$max_capacity" -lt "$ALERT_CAPACITY_THRESHOLD" ]]; then
        echo "🚨 ALERT: Low maximum capacity - $max_capacity%"
        log_action "ALERT: Low maximum capacity - $max_capacity%"
        ((alerts_triggered++))
    fi
    
    if [[ "$alerts_triggered" -eq 0 ]]; then
        echo "✅ No battery health alerts"
        log_action "Battery health monitoring: No alerts"
    else
        echo "⚠️ $alerts_triggered battery health alert(s) triggered"
        log_action "Battery health monitoring: $alerts_triggered alerts triggered"
    fi
    
    return $alerts_triggered
}

# Main execution function
main() {
    local action="${1:-help}"
    local target="${2:-}"
    
    log_action "=== MacFleet Battery Management Started ==="
    
    setup_directories
    
    case "$action" in
        "install"|"setup")
            install_battery_tools
            ;;
        "report"|"status")
            generate_battery_report
            ;;
        "set")
            if [[ -n "$target" ]]; then
                set_optimal_charging_limit "$target"
            else
                set_optimal_charging_limit
            fi
            ;;
        "read"|"current")
            if command -v bclm >/dev/null 2>&1; then
                local current=$(bclm read 2>/dev/null)
                if [[ -n "$current" ]]; then
                    echo "Current charging limit: $current%"
                else
                    echo "No charging limit set (100%)"
                fi
            else
                echo "❌ bclm not installed"
            fi
            ;;
        "persist")
            if command -v bclm >/dev/null 2>&1; then
                if sudo bclm persist; then
                    echo "✅ Charging limit made persistent"
                else
                    echo "❌ Failed to make charging limit persistent"
                fi
            else
                echo "❌ bclm not installed"
            fi
            ;;
        "unpersist")
            if command -v bclm >/dev/null 2>&1; then
                if sudo bclm unpersist; then
                    echo "✅ Charging limit persistence removed"
                else
                    echo "❌ Failed to remove charging limit persistence"
                fi
            else
                echo "❌ bclm not installed"
            fi
            ;;
        "monitor")
            monitor_battery_health
            ;;
        "health")
            if check_battery_presence; then
                local battery_info=$(system_profiler SPPowerDataType)
                echo "=== Battery Health Summary ==="
                echo "$battery_info" | grep -E "Condition|Cycle Count|Maximum Capacity"
                
                if command -v bclm >/dev/null 2>&1; then
                    local limit=$(bclm read 2>/dev/null)
                    echo "Charging Limit: ${limit:-100}%"
                fi
            fi
            ;;
        "help"|*)
            echo "MacFleet Battery Management Tool"
            echo "Usage: $0 [action] [options]"
            echo ""
            echo "Actions:"
            echo "  install               - Install battery management tools (Homebrew, bclm)"
            echo "  report                - Generate comprehensive battery report"
            echo "  set [limit]           - Set optimal charging limit (or specify percentage)"
            echo "  read                  - Read current charging limit"
            echo "  persist               - Make charging limit persistent"
            echo "  unpersist             - Remove charging limit persistence"
            echo "  monitor               - Monitor battery health and trigger alerts"
            echo "  health                - Show battery health summary"
            echo "  help                  - Show this help message"
            echo ""
            echo "Examples:"
            echo "  $0 install             # Install required tools"
            echo "  $0 set 80              # Set 80% charging limit"
            echo "  $0 set                 # Set optimal limit based on device type"
            echo "  $0 report              # Generate detailed report"
            echo ""
            echo "Charging Limit Guidelines:"
            echo "  50-100%     - Valid range"
            echo "  80%         - Recommended for most devices"
            echo "  75%         - For stationary/desktop Macs"
            echo "  90%         - For mobile/laptop Macs"
            ;;
    esac
    
    log_action "=== MacFleet Battery Management Completed ==="
}

# Execute main function
main "$@"

Battery Health Monitoring

Automated Health Checks

# Schedule daily battery health monitoring
create_health_monitoring_schedule() {
    local plist_file="$HOME/Library/LaunchAgents/com.macfleet.battery-monitor.plist"
    
    cat > "$plist_file" << 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.battery-monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>$(realpath "$0")</string>
        <string>monitor</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>9</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    launchctl load "$plist_file" 2>/dev/null
    echo "✅ Daily battery monitoring scheduled"
}

Charging Limit Recommendations

Device TypeRecommended LimitReasoning
Desktop Macs75-80%Always plugged in, prioritize longevity
Laptop Macs (Stationary)80%Mostly plugged in usage
Laptop Macs (Mobile)90%Need higher capacity for portability
Degraded Battery70-75%Extend remaining battery life

Important Notes

  • Supported Devices - Only works on Mac devices with batteries
  • Administrative Privileges - Requires sudo access for SMC modifications
  • System Compatibility - Compatible with modern macOS versions
  • Restart Requirements - Some changes may require system restart
  • Fleet Deployment - Test on individual devices before bulk deployment
  • Battery Health - Monitor battery condition regularly for optimal results

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.