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.

Application Force Close Management for macOS

Implement enterprise-grade application force close management across your MacFleet deployment with automated process termination, security validation, troubleshooting diagnostics, and comprehensive fleet-wide application control. This tutorial provides solutions for maintaining system stability while ensuring secure and efficient application process management.

Understanding macOS Application Process Management

macOS provides several methods for process termination:

  • killall - Terminate all instances of a named process
  • kill - Terminate specific processes by PID
  • pkill - Pattern-based process termination
  • Activity Monitor - GUI-based process management
  • Force Quit - System-level application termination

Basic Force Close Operations

Simple Force Close

#!/bin/bash

# Basic force close
killall "appname"

Force Close with Verbose Output

#!/bin/bash

# Force close with PID output
killall -v "Notes"

Detailed Process Information

#!/bin/bash

# Get detailed process info without killing
killall -d "appname"

List Available Signals

#!/bin/bash

# List available signals
killall -l "appname"

Force Close with Specific Signal

#!/bin/bash

# Force close with ABRT signal
killall -abrt "Pages"

Enterprise Application Force Close Management System

Comprehensive Process Control Tool

#!/bin/bash

# MacFleet Enterprise Application Force Close Management Tool
# Advanced process termination and application control

# Configuration
CONFIG_FILE="/etc/macfleet/force_close_policy.conf"
LOG_FILE="/var/log/macfleet_force_close.log"
QUARANTINE_DIR="/Library/MacFleet/TerminatedApps"
AUDIT_LOG="/var/log/macfleet_process_audit.log"

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

# Default force close management policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# MacFleet Enterprise Application Force Close Management Policy
# Version: 2.0

# Force Close Policy Enforcement
ENFORCE_FORCE_CLOSE_POLICIES=true
GRACEFUL_TERMINATION_FIRST=true
ESCALATION_TIMEOUT=10
SAVE_WORK_BEFORE_TERMINATION=true
PREVENT_SYSTEM_PROCESS_TERMINATION=true

# Security and Safety
REQUIRE_ADMIN_APPROVAL=false
VALIDATE_PROCESS_LEGITIMACY=true
CHECK_PROCESS_DEPENDENCIES=true
MALWARE_DETECTION_ENABLED=true
SUSPICIOUS_BEHAVIOR_MONITORING=true

# Business Rules
BUSINESS_HOURS_PROTECTION=true
BUSINESS_HOURS_START="09:00"
BUSINESS_HOURS_END="18:00"
CRITICAL_APP_PROTECTION=true
PRODUCTIVITY_APP_MONITORING=true

# Diagnostic and Troubleshooting
DIAGNOSTIC_LOGGING=true
CRASH_REPORT_COLLECTION=true
PERFORMANCE_MONITORING=true
RESOURCE_USAGE_TRACKING=true
HANG_DETECTION_ENABLED=true

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

# Compliance and Audit
AUDIT_ALL_TERMINATIONS=true
COMPLIANCE_REPORTING=true
INCIDENT_DOCUMENTATION=true
ESCALATION_PROCEDURES=true
AUTOMATED_RECOVERY=true

# Recovery and Restart
AUTO_RESTART_CRITICAL_APPS=true
RESTART_DELAY=5
CRASH_RECOVERY_ENABLED=true
STATE_PRESERVATION=true
USER_SESSION_PROTECTION=true
EOF

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

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

# Audit logging function
audit_log() {
    local action="$1"
    local process_name="$2"
    local result="$3"
    local details="$4"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ACTION:$action PROCESS:$process_name RESULT:$result DETAILS:$details USER:$(whoami)" >> "$AUDIT_LOG"
}

# Get comprehensive process information
get_process_info() {
    local process_name="$1"
    
    echo "=== Process Information Analysis ==="
    
    # Check if process exists
    if ! pgrep -f "$process_name" >/dev/null 2>&1; then
        echo "Process not found: $process_name"
        return 1
    fi
    
    # Get process details
    echo "Process Name: $process_name"
    
    # Get PIDs
    local pids
    pids=$(pgrep -f "$process_name" | tr '\n' ' ')
    echo "Process IDs: $pids"
    
    # Get CPU and memory usage
    echo "Resource Usage:"
    ps -p $(pgrep -f "$process_name" | head -1) -o pid,pcpu,pmem,time,command 2>/dev/null | tail -1
    
    # Get process tree
    echo "Process Tree:"
    pstree $(pgrep -f "$process_name" | head -1) 2>/dev/null || echo "  Process tree not available"
    
    # Get open files
    echo "Open Files Count:"
    lsof -p $(pgrep -f "$process_name" | head -1) 2>/dev/null | wc -l || echo "  Unable to determine"
    
    # Get network connections
    echo "Network Connections:"
    lsof -i -p $(pgrep -f "$process_name" | head -1) 2>/dev/null | wc -l || echo "  0"
    
    # Check if process is hanging
    local cpu_usage
    cpu_usage=$(ps -p $(pgrep -f "$process_name" | head -1) -o pcpu= 2>/dev/null | xargs)
    if [[ -n "$cpu_usage" ]] && (( $(echo "$cpu_usage < 0.1" | bc -l) )); then
        echo "Status: Potentially hung (very low CPU usage)"
    else
        echo "Status: Active"
    fi
}

# Check if process termination is safe
check_termination_safety() {
    local process_name="$1"
    local force="${2:-false}"
    
    echo "=== Validating Process Termination Safety ==="
    
    # Check if process exists
    if ! pgrep -f "$process_name" >/dev/null 2>&1; then
        echo "✅ Process not running: $process_name"
        return 0
    fi
    
    # Prevent system process termination
    if [[ "$PREVENT_SYSTEM_PROCESS_TERMINATION" == "true" ]]; then
        local system_processes=(
            "kernel"
            "launchd"
            "WindowServer"
            "loginwindow"
            "SystemUIServer"
            "Dock"
            "Finder"
            "cfprefsd"
            "CoreServicesUIAgent"
        )
        
        for system_process in "${system_processes[@]}"; do
            if [[ "$process_name" == "$system_process" ]]; then
                echo "❌ Cannot terminate critical system process: $process_name"
                audit_log "TERMINATION_BLOCKED" "$process_name" "SYSTEM_PROCESS" "System process protection active"
                return 1
            fi
        done
    fi
    
    # Business hours protection for critical apps
    if [[ "$BUSINESS_HOURS_PROTECTION" == "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
            local critical_apps=(
                "Microsoft Word"
                "Microsoft Excel"
                "Microsoft PowerPoint"
                "Slack"
                "Microsoft Teams"
                "Zoom"
                "Safari"
                "Google Chrome"
            )
            
            for critical_app in "${critical_apps[@]}"; do
                if [[ "$process_name" == *"$critical_app"* ]]; then
                    echo "❌ Termination blocked: Critical productivity app during business hours"
                    audit_log "TERMINATION_BLOCKED" "$process_name" "BUSINESS_HOURS" "Critical app protection during business hours"
                    return 1
                fi
            done
        fi
    fi
    
    # Check for unsaved work
    if [[ "$SAVE_WORK_BEFORE_TERMINATION" == "true" ]]; then
        echo "⚠️  Checking for unsaved work..."
        
        # Check for document apps with potential unsaved changes
        local document_apps=(
            "TextEdit"
            "Pages"
            "Numbers"
            "Keynote"
            "Microsoft Word"
            "Microsoft Excel"
            "Microsoft PowerPoint"
        )
        
        for doc_app in "${document_apps[@]}"; do
            if [[ "$process_name" == *"$doc_app"* ]]; then
                echo "📝 Document application detected - attempting to save work"
                try_save_work "$process_name"
                break
            fi
        done
    fi
    
    # Check process dependencies
    if [[ "$CHECK_PROCESS_DEPENDENCIES" == "true" ]]; then
        local child_processes
        child_processes=$(pgrep -P $(pgrep -f "$process_name" | head -1) 2>/dev/null | wc -l)
        
        if [[ $child_processes -gt 0 ]]; then
            echo "⚠️  Process has $child_processes child processes"
            if [[ "$force" != "true" ]]; then
                echo "❌ Termination blocked: Process has dependencies. Use force option to proceed."
                audit_log "TERMINATION_BLOCKED" "$process_name" "DEPENDENCIES" "Process has $child_processes child processes"
                return 1
            fi
        fi
    fi
    
    echo "✅ Process termination safety validated"
    audit_log "SAFETY_CHECK" "$process_name" "PASSED" "All safety checks passed"
    return 0
}

# Try to save work in document applications
try_save_work() {
    local process_name="$1"
    
    echo "=== Attempting to Save Work ==="
    
    # Send save command via AppleScript for common applications
    local save_commands=(
        "osascript -e 'tell application \"System Events\" to keystroke \"s\" using command down'"
        "osascript -e 'tell application \"$process_name\" to save every document'"
    )
    
    for cmd in "${save_commands[@]}"; do
        eval "$cmd" 2>/dev/null || true
        sleep 1
    done
    
    # Wait a moment for save operations to complete
    sleep 3
    
    echo "💾 Save attempt completed"
    log_action "Work save attempt completed for $process_name"
}

# Detect suspicious or malware processes
detect_suspicious_process() {
    local process_name="$1"
    
    if [[ "$MALWARE_DETECTION_ENABLED" != "true" ]]; then
        return 0
    fi
    
    echo "=== Suspicious Process Detection ==="
    
    local suspicious_indicators=(
        "crypto"
        "miner"
        "trojan"
        "virus"
        "malware"
        "ransomware"
        "keylogger"
        "backdoor"
    )
    
    # Check process name for suspicious keywords
    for indicator in "${suspicious_indicators[@]}"; do
        if [[ "$process_name" == *"$indicator"* ]]; then
            echo "🚨 Suspicious process detected: $process_name (matches: $indicator)"
            log_action "SECURITY ALERT: Suspicious process detected: $process_name"
            audit_log "SUSPICIOUS_PROCESS" "$process_name" "DETECTED" "Matches indicator: $indicator"
            
            # Quarantine process information
            quarantine_process_info "$process_name"
            return 1
        fi
    done
    
    # Check for unusual resource consumption
    local cpu_usage
    cpu_usage=$(ps -p $(pgrep -f "$process_name" | head -1) -o pcpu= 2>/dev/null | xargs)
    
    if [[ -n "$cpu_usage" ]] && (( $(echo "$cpu_usage > 80" | bc -l) )); then
        echo "⚠️  High CPU usage detected: ${cpu_usage}%"
        log_action "High CPU usage detected for $process_name: ${cpu_usage}%"
    fi
    
    return 0
}

# Quarantine suspicious process information
quarantine_process_info() {
    local process_name="$1"
    
    echo "=== Quarantining Process Information ==="
    
    local quarantine_file="$QUARANTINE_DIR/suspicious_process_$(date +%Y%m%d_%H%M%S).json"
    
    mkdir -p "$QUARANTINE_DIR"
    
    # Gather comprehensive process information
    local pid
    pid=$(pgrep -f "$process_name" | head -1)
    
    cat > "$quarantine_file" << EOF
{
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "process_name": "$process_name",
  "pid": "$pid",
  "detection_reason": "suspicious_indicators",
  "system_info": {
    "hostname": "$(hostname)",
    "user": "$(whoami)",
    "os_version": "$(sw_vers -productVersion)"
  },
  "process_details": {
    "command_line": "$(ps -p $pid -o command= 2>/dev/null || echo 'unknown')",
    "cpu_usage": "$(ps -p $pid -o pcpu= 2>/dev/null || echo 'unknown')",
    "memory_usage": "$(ps -p $pid -o pmem= 2>/dev/null || echo 'unknown')",
    "start_time": "$(ps -p $pid -o lstart= 2>/dev/null || echo 'unknown')"
  }
}
EOF
    
    echo "🔒 Process information quarantined: $quarantine_file"
    log_action "Suspicious process information quarantined: $quarantine_file"
}

# Send termination notification
send_termination_notification() {
    local process_name="$1"
    local operation="$2"
    local result="$3"
    local reason="$4"
    
    if [[ "$USER_NOTIFICATION_ENABLED" != "true" ]]; then
        return 0
    fi
    
    echo "=== Sending Termination Notifications ==="
    
    local notification_title="MacFleet Process Management"
    local notification_message="Process $operation: $process_name ($result)"
    
    if [[ -n "$reason" ]]; then
        notification_message="$notification_message - Reason: $reason"
    fi
    
    # Display notification to 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
    
    # 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 "Termination notifications sent for $process_name ($operation - $result)"
}

# Enterprise force close with escalation
enterprise_force_close() {
    local process_name="$1"
    local force="${2:-false}"
    local signal="${3:-TERM}"
    
    echo "=== Enterprise Force Close Initiated ==="
    
    if [[ -z "$process_name" ]]; then
        echo "❌ Process name required"
        return 1
    fi
    
    # Get process information
    echo "Analyzing process: $process_name"
    get_process_info "$process_name"
    
    # Detect suspicious processes
    if detect_suspicious_process "$process_name"; then
        echo "⚠️  Suspicious process detected - proceeding with caution"
    fi
    
    # Safety checks
    if ! check_termination_safety "$process_name" "$force"; then
        return 1
    fi
    
    log_action "ENTERPRISE FORCE CLOSE: Starting termination of $process_name"
    audit_log "FORCE_CLOSE" "$process_name" "INITIATED" "Signal: $signal Force: $force"
    
    # Graceful termination first (if enabled)
    if [[ "$GRACEFUL_TERMINATION_FIRST" == "true" && "$force" != "true" ]]; then
        echo "🔄 Attempting graceful termination first..."
        
        if killall -TERM "$process_name" 2>/dev/null; then
            echo "Graceful termination signal sent, waiting ${ESCALATION_TIMEOUT}s..."
            sleep "$ESCALATION_TIMEOUT"
            
            # Check if process is still running
            if ! pgrep -f "$process_name" >/dev/null 2>&1; then
                echo "✅ Process terminated gracefully"
                send_termination_notification "$process_name" "graceful termination" "success"
                audit_log "FORCE_CLOSE" "$process_name" "SUCCESS" "Graceful termination successful"
                return 0
            else
                echo "⚠️  Graceful termination failed, escalating to force termination"
            fi
        fi
    fi
    
    # Force termination
    echo "🚨 Executing force termination..."
    
    case "$signal" in
        "TERM")
            if killall "$process_name" 2>/dev/null; then
                echo "✅ Process force closed successfully with TERM signal"
                termination_result="success"
            else
                echo "❌ Failed to force close process with TERM signal"
                termination_result="failed"
            fi
            ;;
        "KILL")
            if killall -KILL "$process_name" 2>/dev/null; then
                echo "✅ Process force killed successfully with KILL signal"
                termination_result="success"
            else
                echo "❌ Failed to force kill process with KILL signal"
                termination_result="failed"
            fi
            ;;
        "ABRT")
            if killall -ABRT "$process_name" 2>/dev/null; then
                echo "✅ Process aborted successfully with ABRT signal"
                termination_result="success"
            else
                echo "❌ Failed to abort process with ABRT signal"
                termination_result="failed"
            fi
            ;;
        *)
            if killall -"$signal" "$process_name" 2>/dev/null; then
                echo "✅ Process terminated successfully with $signal signal"
                termination_result="success"
            else
                echo "❌ Failed to terminate process with $signal signal"
                termination_result="failed"
            fi
            ;;
    esac
    
    # Send notifications
    send_termination_notification "$process_name" "force close" "$termination_result" "Signal: $signal"
    
    # Auto-restart critical applications if configured
    if [[ "$AUTO_RESTART_CRITICAL_APPS" == "true" && "$termination_result" == "success" ]]; then
        restart_if_critical "$process_name"
    fi
    
    if [[ "$termination_result" == "success" ]]; then
        log_action "Process force closed successfully: $process_name"
        audit_log "FORCE_CLOSE" "$process_name" "SUCCESS" "Signal: $signal"
        return 0
    else
        log_action "FAILED: Could not force close process: $process_name"
        audit_log "FORCE_CLOSE" "$process_name" "FAILED" "Signal: $signal"
        return 1
    fi
}

# Restart critical applications
restart_if_critical() {
    local process_name="$1"
    
    local critical_apps=(
        "Finder"
        "Dock"
        "SystemUIServer"
        "Spotlight"
    )
    
    for critical_app in "${critical_apps[@]}"; do
        if [[ "$process_name" == *"$critical_app"* ]]; then
            echo "🔄 Restarting critical application: $critical_app"
            log_action "Auto-restarting critical application: $critical_app"
            
            sleep "$RESTART_DELAY"
            
            case "$critical_app" in
                "Finder")
                    open -a Finder &
                    ;;
                "Dock")
                    killall Dock &
                    ;;
                "SystemUIServer")
                    killall SystemUIServer &
                    ;;
                "Spotlight")
                    mdutil -E / &
                    ;;
            esac
            
            break
        fi
    done
}

# Bulk force close operations
bulk_force_close() {
    local process_list_file="$1"
    local force="${2:-false}"
    local signal="${3:-TERM}"
    
    echo "=== Bulk Force Close Operations ==="
    
    if [[ ! -f "$process_list_file" ]]; then
        echo "❌ Process list file not found: $process_list_file"
        return 1
    fi
    
    local success_count=0
    local failure_count=0
    local total_count=0
    
    while IFS= read -r process_name; do
        # Skip empty lines and comments
        if [[ -z "$process_name" || "$process_name" == \#* ]]; then
            continue
        fi
        
        ((total_count++))
        echo "Processing ($total_count): $process_name"
        
        if enterprise_force_close "$process_name" "$force" "$signal"; then
            ((success_count++))
        else
            ((failure_count++))
        fi
        
        echo "---"
        sleep 1  # Brief pause between operations
    done < "$process_list_file"
    
    echo "=== Bulk Force Close Summary ==="
    echo "Total processes: $total_count"
    echo "Successful terminations: $success_count"
    echo "Failed terminations: $failure_count"
    
    log_action "Bulk force close completed: $success_count/$total_count successful"
    audit_log "BULK_FORCE_CLOSE" "MULTIPLE" "COMPLETED" "Success: $success_count Failed: $failure_count Total: $total_count Signal: $signal"
}

# Hang detection and automatic recovery
detect_and_recover_hangs() {
    echo "=== Hang Detection and Recovery ==="
    
    if [[ "$HANG_DETECTION_ENABLED" != "true" ]]; then
        echo "Hang detection is disabled"
        return 0
    fi
    
    local hang_threshold=0.1  # CPU usage below this for extended time indicates hang
    local hang_duration=30    # Seconds of low activity to consider hung
    
    # Find processes with very low CPU usage
    local potentially_hung
    potentially_hung=$(ps -A -o pid,pcpu,time,command | awk -v threshold="$hang_threshold" '$2 < threshold && $2 > 0 {print $1 ":" $4}')
    
    if [[ -n "$potentially_hung" ]]; then
        echo "Potentially hung processes detected:"
        echo "$potentially_hung" | while IFS=':' read -r pid command; do
            echo "  PID $pid: $command"
            
            # Check if it's a user application (not system process)
            if [[ "$command" == *".app"* ]]; then
                local app_name
                app_name=$(basename "$command")
                echo "🔄 Attempting recovery of hung application: $app_name"
                
                log_action "Hang detected and recovery attempted: $app_name (PID: $pid)"
                audit_log "HANG_RECOVERY" "$app_name" "ATTEMPTED" "PID: $pid"
                
                # Try graceful recovery first
                kill -USR1 "$pid" 2>/dev/null || true
                sleep 5
                
                # If still hanging, force close
                if ps -p "$pid" >/dev/null 2>&1; then
                    enterprise_force_close "$app_name" "true" "TERM"
                fi
            fi
        done
    else
        echo "No hung processes detected"
    fi
}

# Generate comprehensive process management report
generate_process_report() {
    local report_file="/Library/MacFleet/Reports/process_management_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Process Management Report ==="
    
    mkdir -p "$(dirname "$report_file")"
    
    # Count recent operations from audit log
    local recent_terminations=0
    local recent_hangs=0
    local suspicious_processes=0
    
    if [[ -f "$AUDIT_LOG" ]]; then
        recent_terminations=$(grep -c "ACTION:FORCE_CLOSE.*RESULT:SUCCESS" "$AUDIT_LOG" 2>/dev/null || echo 0)
        recent_hangs=$(grep -c "ACTION:HANG_RECOVERY" "$AUDIT_LOG" 2>/dev/null || echo 0)
        suspicious_processes=$(grep -c "ACTION:SUSPICIOUS_PROCESS" "$AUDIT_LOG" 2>/dev/null || echo 0)
    fi
    
    # Get current system load
    local load_average
    load_average=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
    
    # Count running processes
    local total_processes
    total_processes=$(ps -A | wc -l)
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "process_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": {
    "load_average": "$load_average",
    "total_processes": $total_processes,
    "recent_terminations": $recent_terminations,
    "hang_recoveries": $recent_hangs,
    "suspicious_processes_detected": $suspicious_processes
  },
  "policy_configuration": {
    "graceful_termination_first": $GRACEFUL_TERMINATION_FIRST,
    "business_hours_protection": $BUSINESS_HOURS_PROTECTION,
    "hang_detection_enabled": $HANG_DETECTION_ENABLED,
    "malware_detection_enabled": $MALWARE_DETECTION_ENABLED
  },
  "security_status": {
    "system_process_protection": $PREVENT_SYSTEM_PROCESS_TERMINATION,
    "suspicious_behavior_monitoring": $SUSPICIOUS_BEHAVIOR_MONITORING,
    "audit_enabled": $AUDIT_ALL_TERMINATIONS
  }
}
EOF
    
    echo "Process management report saved to: $report_file"
    log_action "Process management report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== MacFleet Process Management Tool Started ==="
    
    case "${1:-help}" in
        "close")
            enterprise_force_close "$2" "$3" "$4"
            ;;
        "bulk")
            bulk_force_close "$2" "$3" "$4"
            ;;
        "info")
            get_process_info "$2"
            ;;
        "detect-hangs")
            detect_and_recover_hangs
            ;;
        "report")
            generate_process_report
            ;;
        *)
            echo "MacFleet Enterprise Application Force Close Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  close [process_name] [force] [signal]    - Force close application with safety checks"
            echo "  bulk [list_file] [force] [signal]       - Bulk force close from file list"
            echo "  info [process_name]                     - Get detailed process information"
            echo "  detect-hangs                            - Detect and recover hung applications"
            echo "  report                                  - Generate process management report"
            echo ""
            echo "Signals:"
            echo "  TERM (default)  - Graceful termination signal"
            echo "  KILL           - Immediate termination (cannot be ignored)"
            echo "  ABRT           - Abort with core dump generation"
            echo "  HUP            - Hang up signal"
            echo "  INT            - Interrupt signal"
            echo ""
            echo "Examples:"
            echo "  $0 close \"Safari\"                      - Safe force close of Safari"
            echo "  $0 close \"Notes\" true KILL             - Force kill Notes (bypass safety)"
            echo "  $0 bulk hung_processes.txt              - Bulk close from list"
            echo "  $0 info \"Google Chrome\"                - Get Chrome process information"
            echo "  $0 detect-hangs                         - Scan for and recover hung apps"
            ;;
    esac
    
    log_action "=== Process management operation completed ==="
}

# Execute main function
main "$@"

## Advanced Process Management Features

### Intelligent Hang Detection

```bash
#!/bin/bash

# Advanced hang detection with machine learning patterns
detect_application_patterns() {
    local process_name="$1"
    
    echo "=== Application Behavior Pattern Analysis ==="
    
    # Monitor CPU and memory usage over time
    local cpu_samples=()
    local memory_samples=()
    
    for i in {1..10}; do
        local pid
        pid=$(pgrep -f "$process_name" | head -1)
        
        if [[ -n "$pid" ]]; then
            local cpu_usage
            local mem_usage
            cpu_usage=$(ps -p "$pid" -o pcpu= | xargs)
            mem_usage=$(ps -p "$pid" -o pmem= | xargs)
            
            cpu_samples+=("$cpu_usage")
            memory_samples+=("$mem_usage")
        fi
        
        sleep 2
    done
    
    # Analyze patterns
    local avg_cpu=0
    local cpu_variance=0
    
    for cpu in "${cpu_samples[@]}"; do
        avg_cpu=$(echo "$avg_cpu + $cpu" | bc -l)
    done
    avg_cpu=$(echo "scale=2; $avg_cpu / ${#cpu_samples[@]}" | bc -l)
    
    echo "Average CPU Usage: ${avg_cpu}%"
    
    # Detect hang patterns
    if (( $(echo "$avg_cpu < 0.5" | bc -l) )); then
        echo "🚨 Pattern indicates potential hang: Very low CPU activity"
        return 1
    elif (( $(echo "$avg_cpu > 90" | bc -l) )); then
        echo "🚨 Pattern indicates potential infinite loop: Sustained high CPU"
        return 1
    else
        echo "✅ Process behavior appears normal"
        return 0
    fi
}

# Resource leak detection
detect_resource_leaks() {
    local process_name="$1"
    
    echo "=== Resource Leak Detection ==="
    
    local pid
    pid=$(pgrep -f "$process_name" | head -1)
    
    if [[ -z "$pid" ]]; then
        echo "Process not found: $process_name"
        return 1
    fi
    
    # Check memory growth
    local initial_memory
    initial_memory=$(ps -p "$pid" -o rss= | xargs)
    
    sleep 60  # Monitor for 1 minute
    
    local final_memory
    final_memory=$(ps -p "$pid" -o rss= | xargs)
    
    local memory_growth
    memory_growth=$((final_memory - initial_memory))
    
    echo "Memory Growth: ${memory_growth} KB in 60 seconds"
    
    if [[ $memory_growth -gt 50000 ]]; then  # More than 50MB growth
        echo "🚨 Potential memory leak detected"
        log_action "Memory leak detected in $process_name: ${memory_growth}KB growth"
        return 1
    fi
    
    # Check file descriptor leaks
    local open_files
    open_files=$(lsof -p "$pid" 2>/dev/null | wc -l)
    
    echo "Open File Descriptors: $open_files"
    
    if [[ $open_files -gt 1000 ]]; then
        echo "🚨 Potential file descriptor leak detected"
        log_action "File descriptor leak detected in $process_name: $open_files open files"
        return 1
    fi
    
    echo "✅ No resource leaks detected"
    return 0
}

## Important Configuration Notes

### macOS Process Control Commands

- **`killall`** - Terminate all processes by name (case-sensitive)
- **`kill`** - Terminate specific process by PID
- **`pkill`** - Pattern-based process termination
- **Signals** - TERM (graceful), KILL (immediate), ABRT (with core dump)

### Enterprise Integration Points

- **Security Information and Event Management (SIEM)** - Process termination logging
- **Application Performance Monitoring** - Integration with APM platforms
- **Incident Management Systems** - Automated ticket creation for hangs
- **Change Management** - Documentation of process interventions

### Best Practices for Enterprise Process Management

1. **Safety and Validation**
   - Always attempt graceful termination before force killing
   - Protect critical system processes from accidental termination
   - Implement business hours restrictions for productivity applications
   - Maintain comprehensive audit trails

2. **User Experience**
   - Attempt to save user work before terminating applications
   - Provide clear notifications about process terminations
   - Auto-restart critical applications when possible
   - Minimize disruption during business hours

3. **Security and Monitoring**
   - Detect and quarantine suspicious processes
   - Monitor for unusual resource consumption patterns
   - Implement hang detection and automatic recovery
   - Track process behavior for security analysis

4. **Troubleshooting and Diagnostics**
   - Collect detailed process information before termination
   - Generate crash reports for analysis
   - Monitor system performance impact
   - Provide comprehensive reporting capabilities

### Troubleshooting Common Issues

- **Process won't terminate** - Escalate through signal hierarchy (TERM → KILL)
- **System stability issues** - Avoid terminating critical system processes
- **Data loss concerns** - Implement work-saving procedures before termination
- **Resource leaks** - Monitor memory and file descriptor usage
- **Hang detection false positives** - Tune detection thresholds based on application behavior

Remember to test process management procedures thoroughly in a controlled environment before implementing across your entire MacFleet to ensure system stability and user productivity. 

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.