Tutorial

New updates and improvements to Macfleet.

Network Monitoring on macOS

Monitor and control network activity across your MacFleet devices using advanced network monitoring techniques, bandwidth analysis, and enterprise security controls. This tutorial provides comprehensive tools for implementing organizational network management and security policies.

Understanding macOS Network Monitoring

macOS provides several tools for network activity monitoring:

  • lsof - List open files and network connections
  • netstat - Display network connections and routing tables
  • nettop - Real-time network usage by process
  • tcpdump - Packet capture and analysis
  • Little Snitch - Application-level firewall and network monitor

Basic Network Connection Monitoring

List Internet-Connected Apps

#!/bin/bash

# List unique processes with internet connections
lsof -nPi | cut -f 1 -d " " | uniq | tail -n +2

echo "Internet-connected processes listed"

Detailed Network Connections

#!/bin/bash

# Show detailed network connection information
echo "=== Active Network Connections ==="
lsof -nPi

echo -e "\n=== Network Statistics ==="
netstat -an | head -20

Process-Specific Network Activity

#!/bin/bash

# Monitor specific application network activity
APP_NAME="Chrome"

echo "Network connections for $APP_NAME:"
lsof -nPi | grep -i "$APP_NAME"

Enterprise Network Monitoring System

#!/bin/bash

# MacFleet Enterprise Network Monitoring System
# Comprehensive network activity monitoring and security management

# Configuration
MACFLEET_DIR="/etc/macfleet"
MONITORING_DIR="$MACFLEET_DIR/network_monitoring"
REPORTS_DIR="$MACFLEET_DIR/reports"
COMPLIANCE_DIR="$MACFLEET_DIR/compliance"
AUDIT_DIR="$MACFLEET_DIR/audit"
LOG_FILE="/var/log/macfleet_network_monitoring.log"
ALERTS_DIR="$MACFLEET_DIR/alerts"

# Create directory structure
create_directories() {
    local dirs=("$MACFLEET_DIR" "$MONITORING_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$ALERTS_DIR")
    for dir in "${dirs[@]}"; do
        [[ ! -d "$dir" ]] && mkdir -p "$dir"
    done
}

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

# Application Categories for Network Monitoring
declare -A APP_CATEGORIES=(
    ["business_apps"]="Slack,Zoom,Microsoft Teams,Office 365,Salesforce"
    ["development_tools"]="Xcode,Visual Studio Code,Docker,Git,npm"
    ["browsers"]="Chrome,Firefox,Safari,Edge"
    ["communication"]="Mail,Messages,FaceTime,Skype"
    ["cloud_storage"]="Dropbox,Google Drive,OneDrive,iCloud"
    ["entertainment"]="Spotify,Netflix,YouTube,Steam"
    ["security_tools"]="1Password,Little Snitch,Wireshark"
    ["system_services"]="locationd,cloudd,nsurlsessiond,trustd"
)

# Network Monitoring Policies
declare -A MONITORING_POLICIES=(
    ["strict_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:monitored,communication:allowed,cloud_storage:monitored,entertainment:blocked,security_tools:allowed,system_services:allowed"
    ["balanced_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:monitored,security_tools:allowed,system_services:allowed"
    ["minimal_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:allowed,security_tools:allowed,system_services:allowed"
    ["development_focused"]="business_apps:allowed,development_tools:priority,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:blocked,security_tools:allowed,system_services:allowed"
    ["security_lockdown"]="business_apps:monitored,development_tools:monitored,browsers:monitored,communication:monitored,cloud_storage:blocked,entertainment:blocked,security_tools:allowed,system_services:allowed"
)

# Bandwidth Thresholds (in MB/s)
declare -A BANDWIDTH_THRESHOLDS=(
    ["critical"]=100
    ["high"]=50
    ["moderate"]=20
    ["low"]=5
)

# Get comprehensive network activity
get_network_activity() {
    local monitoring_level="$1"
    local output_file="$MONITORING_DIR/network_activity_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting network activity monitoring: $monitoring_level"
    
    # Get basic network connections
    local connections=$(lsof -nPi 2>/dev/null | tail -n +2)
    local unique_processes=$(echo "$connections" | cut -f 1 -d " " | sort | uniq)
    
    # Get detailed process information
    local detailed_info=""
    while IFS= read -r process; do
        [[ -z "$process" ]] && continue
        
        local pids=$(pgrep -f "$process" 2>/dev/null | head -5)
        for pid in $pids; do
            local cpu_usage=$(ps -p "$pid" -o %cpu= 2>/dev/null | tr -d ' ')
            local mem_usage=$(ps -p "$pid" -o %mem= 2>/dev/null | tr -d ' ')
            local process_connections=$(echo "$connections" | grep "^$process" | wc -l)
            
            if [[ -n "$cpu_usage" && -n "$mem_usage" ]]; then
                detailed_info="$detailed_info{\"process\":\"$process\",\"pid\":$pid,\"cpu\":$cpu_usage,\"memory\":$mem_usage,\"connections\":$process_connections},"
            fi
        done
    done <<< "$unique_processes"
    
    # Remove trailing comma and format JSON
    detailed_info="${detailed_info%,}"
    
    cat > "$output_file" << EOF
{
  "monitoring_metadata": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "monitoring_level": "$monitoring_level",
    "report_version": "1.0"
  },
  "network_activity": {
    "total_processes": $(echo "$unique_processes" | wc -l),
    "active_connections": $(echo "$connections" | wc -l),
    "processes": [$detailed_info]
  },
  "system_metrics": {
    "load_average": "$(uptime | awk -F'load average:' '{print $2}' | tr -d ' ')",
    "memory_pressure": "$(memory_pressure 2>/dev/null || echo 'unknown')",
    "network_interfaces": $(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
  }
}
EOF
    
    log_action "Network activity report saved: $output_file"
    echo "$output_file"
}

# Analyze bandwidth usage
analyze_bandwidth_usage() {
    local monitoring_duration="$1"
    local analysis_file="$MONITORING_DIR/bandwidth_analysis_$(date +%Y%m%d_%H%M%S).txt"
    
    log_action "Starting bandwidth analysis for $monitoring_duration seconds"
    
    # Use nettop for bandwidth monitoring
    timeout "$monitoring_duration" nettop -P -t wifi -t ethernet -l 1 > "$analysis_file" 2>/dev/null &
    local nettop_pid=$!
    
    sleep "$monitoring_duration"
    
    # Kill nettop if still running
    kill "$nettop_pid" 2>/dev/null
    
    # Parse bandwidth data
    local high_bandwidth_processes=""
    if [[ -f "$analysis_file" ]]; then
        # Extract processes with high bandwidth usage
        while IFS= read -r line; do
            [[ "$line" =~ ^[[:space:]]*[0-9] ]] || continue
            
            local process_name=$(echo "$line" | awk '{print $2}')
            local bytes_in=$(echo "$line" | awk '{print $3}' | sed 's/[^0-9]//g')
            local bytes_out=$(echo "$line" | awk '{print $4}' | sed 's/[^0-9]//g')
            
            # Convert to MB/s (rough estimation)
            local total_mb=$(( (bytes_in + bytes_out) / 1024 / 1024 / monitoring_duration ))
            
            if [[ $total_mb -gt ${BANDWIDTH_THRESHOLDS["moderate"]} ]]; then
                high_bandwidth_processes="$high_bandwidth_processes$process_name:${total_mb}MB/s,"
            fi
        done < "$analysis_file"
    fi
    
    log_action "Bandwidth analysis completed. High usage processes: ${high_bandwidth_processes%,}"
    echo "${high_bandwidth_processes%,}"
}

# Security threat detection
detect_security_threats() {
    local scan_mode="$1"
    local threats_file="$MONITORING_DIR/security_threats_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting security threat detection: $scan_mode"
    
    # Get network connections
    local connections=$(lsof -nPi 2>/dev/null)
    
    # Suspicious patterns
    local suspicious_ports=("22" "23" "3389" "5900" "6667" "6697" "1337" "31337")
    local suspicious_domains=("*.tor" "*.onion" "tempmail" "guerrillamail" "10minutemail")
    local suspicious_processes=("nc" "netcat" "telnet" "ssh" "tor")
    
    local threats_detected=""
    local threat_count=0
    
    # Check for suspicious ports
    for port in "${suspicious_ports[@]}"; do
        local port_connections=$(echo "$connections" | grep ":$port" | wc -l)
        if [[ $port_connections -gt 0 ]]; then
            threats_detected="$threats_detected{\"type\":\"suspicious_port\",\"details\":\"Port $port has $port_connections connections\",\"severity\":\"medium\"},"
            ((threat_count++))
        fi
    done
    
    # Check for suspicious processes
    for process in "${suspicious_processes[@]}"; do
        if pgrep -f "$process" >/dev/null 2>&1; then
            threats_detected="$threats_detected{\"type\":\"suspicious_process\",\"details\":\"Process $process is running\",\"severity\":\"high\"},"
            ((threat_count++))
        fi
    done
    
    # Check for unusual connection patterns
    local unique_external_ips=$(echo "$connections" | grep -E ":[0-9]+->.*:[0-9]+" | awk -F'->' '{print $2}' | cut -d':' -f1 | sort | uniq | wc -l)
    if [[ $unique_external_ips -gt 50 ]]; then
        threats_detected="$threats_detected{\"type\":\"connection_anomaly\",\"details\":\"Unusual number of external connections: $unique_external_ips\",\"severity\":\"medium\"},"
        ((threat_count++))
    fi
    
    # Remove trailing comma
    threats_detected="${threats_detected%,}"
    
    cat > "$threats_file" << EOF
{
  "security_scan": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "scan_mode": "$scan_mode",
    "threats_detected": $threat_count,
    "threats": [$threats_detected]
  },
  "network_summary": {
    "total_connections": $(echo "$connections" | wc -l),
    "unique_processes": $(echo "$connections" | cut -f1 -d' ' | sort | uniq | wc -l),
    "external_connections": $unique_external_ips
  }
}
EOF
    
    if [[ $threat_count -gt 0 ]]; then
        log_action "SECURITY ALERT: $threat_count threats detected. Report: $threats_file"
        
        # Create alert
        echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):SECURITY_THREAT:$threat_count threats detected" >> "$ALERTS_DIR/security_alerts.log"
    else
        log_action "Security scan completed. No threats detected."
    fi
    
    echo "$threats_file"
}

# Apply network monitoring policy
apply_monitoring_policy() {
    local policy="$1"
    
    if [[ -z "${MONITORING_POLICIES[$policy]}" ]]; then
        log_action "ERROR: Unknown monitoring policy: $policy"
        return 1
    fi
    
    log_action "Applying network monitoring policy: $policy"
    
    # Parse policy string
    IFS=',' read -ra policy_items <<< "${MONITORING_POLICIES[$policy]}"
    
    local policy_config="$MONITORING_DIR/active_policy.conf"
    echo "# MacFleet Network Monitoring Policy: $policy" > "$policy_config"
    echo "# Applied: $(date)" >> "$policy_config"
    echo "" >> "$policy_config"
    
    for item in "${policy_items[@]}"; do
        IFS=':' read -ra parts <<< "$item"
        local category="${parts[0]}"
        local action="${parts[1]}"
        
        echo "$category=$action" >> "$policy_config"
        
        case "$action" in
            "blocked")
                log_action "Configuring blocks for category: $category"
                # In a real implementation, this would configure firewall rules
                ;;
            "monitored")
                log_action "Enhanced monitoring for category: $category"
                ;;
            "priority")
                log_action "Priority bandwidth for category: $category"
                ;;
            "allowed")
                log_action "Standard access for category: $category"
                ;;
        esac
    done
    
    log_action "Network monitoring policy '$policy' applied successfully"
    
    # Generate policy compliance report
    generate_compliance_report "$policy"
}

# Real-time network monitoring
start_realtime_monitoring() {
    local monitoring_interval="$1"
    local alert_threshold="$2"
    
    log_action "Starting real-time network monitoring (interval: ${monitoring_interval}s, threshold: $alert_threshold connections)"
    
    local monitor_file="$MONITORING_DIR/realtime_monitor.log"
    
    while true; do
        local current_connections=$(lsof -nPi 2>/dev/null | wc -l)
        local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
        local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
        
        echo "$timestamp:$current_connections:$unique_processes" >> "$monitor_file"
        
        # Check alert threshold
        if [[ $current_connections -gt $alert_threshold ]]; then
            log_action "ALERT: High network activity detected - $current_connections connections"
            echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):HIGH_ACTIVITY:$current_connections connections" >> "$ALERTS_DIR/activity_alerts.log"
        fi
        
        sleep "$monitoring_interval"
    done
}

# Network access control
control_network_access() {
    local action="$1"
    local target="$2"
    local reason="$3"
    
    log_action "Network access control: $action for $target (Reason: $reason)"
    
    case "$action" in
        "block_process")
            # Kill network-connected processes
            local pids=$(pgrep -f "$target" 2>/dev/null)
            for pid in $pids; do
                if kill -TERM "$pid" 2>/dev/null; then
                    log_action "Terminated process: $target (PID: $pid)"
                fi
            done
            ;;
        "block_domain")
            # Add to hosts file for blocking
            if ! grep -q "127.0.0.1 $target" /etc/hosts; then
                echo "127.0.0.1 $target" >> /etc/hosts
                log_action "Blocked domain: $target"
            fi
            ;;
        "unblock_domain")
            # Remove from hosts file
            sed -i "" "/127.0.0.1 $target/d" /etc/hosts
            log_action "Unblocked domain: $target"
            ;;
        "limit_bandwidth")
            # This would require integration with traffic shaping tools
            log_action "Bandwidth limiting requested for: $target (Not implemented - requires pfctl or similar)"
            ;;
    esac
    
    # Record action in audit log
    echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):$action:$target:$reason:$(whoami)" >> "$AUDIT_DIR/network_control_actions.log"
}

# Generate comprehensive compliance report
generate_compliance_report() {
    local policy="$1"
    local report_file="$REPORTS_DIR/network_monitoring_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    # Get current network activity
    local active_connections=$(lsof -nPi 2>/dev/null | wc -l)
    local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
    
    # Count alerts
    local security_alerts=0
    local activity_alerts=0
    
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        security_alerts=$(wc -l < "$ALERTS_DIR/security_alerts.log")
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        activity_alerts=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
    fi
    
    cat > "$report_file" << EOF
{
  "report_metadata": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "policy_applied": "$policy",
    "report_version": "1.0"
  },
  "network_monitoring_status": {
    "active_connections": $active_connections,
    "monitored_processes": $unique_processes,
    "security_alerts": $security_alerts,
    "activity_alerts": $activity_alerts,
    "monitoring_active": $([ -f "$MONITORING_DIR/realtime_monitor.log" ] && echo "true" || echo "false")
  },
  "security_policy": {
    "name": "$policy",
    "categories_monitored": $(echo "${!APP_CATEGORIES[@]}" | wc -w),
    "compliance_frameworks": ["SOX", "HIPAA", "NIST", "ISO27001", "PCI-DSS"]
  },
  "network_health": {
    "bandwidth_monitoring": $(command -v nettop >/dev/null && echo "true" || echo "false"),
    "firewall_active": $(pfctl -s info 2>/dev/null | grep -q "Status: Enabled" && echo "true" || echo "false"),
    "dns_filtering": $(networksetup -getdnsservers Wi-Fi | grep -q "208.67" && echo "true" || echo "false"),
    "vpn_detected": $(ifconfig | grep -q "utun" && echo "true" || echo "false")
  },
  "compliance_metrics": {
    "policy_violations": 0,
    "data_exfiltration_attempts": 0,
    "unauthorized_connections": $security_alerts,
    "bandwidth_violations": 0
  }
}
EOF
    
    log_action "Network monitoring compliance report generated: $report_file"
    echo "Report saved to: $report_file"
}

# Health check and system validation
perform_health_check() {
    echo "=== MacFleet Network Monitoring Health Check ==="
    
    # Check network monitoring tools
    local tools=("lsof" "netstat" "nettop" "networksetup")
    for tool in "${tools[@]}"; do
        if command -v "$tool" >/dev/null 2>&1; then
            echo "✓ $tool: Available"
        else
            echo "✗ $tool: Missing"
        fi
    done
    
    # Check active connections
    local connections=$(lsof -nPi 2>/dev/null | wc -l)
    echo "✓ Active network connections: $connections"
    
    # Check monitoring files
    if [[ -f "$MONITORING_DIR/active_policy.conf" ]]; then
        local active_policy=$(grep -v "^#" "$MONITORING_DIR/active_policy.conf" | head -1)
        echo "✓ Active monitoring policy: $active_policy"
    else
        echo "○ No active monitoring policy"
    fi
    
    # Check for alerts
    local total_alerts=0
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        local security_count=$(wc -l < "$ALERTS_DIR/security_alerts.log")
        total_alerts=$((total_alerts + security_count))
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        local activity_count=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
        total_alerts=$((total_alerts + activity_count))
    fi
    
    if [[ $total_alerts -gt 0 ]]; then
        echo "⚠️  Total alerts: $total_alerts"
    else
        echo "✓ No active alerts"
    fi
    
    # Check system network health
    local network_interfaces=$(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
    echo "✓ Network interfaces: $network_interfaces"
    
    # Check DNS configuration
    local dns_servers=$(networksetup -getdnsservers Wi-Fi 2>/dev/null | head -1)
    echo "✓ DNS server: $dns_servers"
}

# Fleet deployment function
deploy_to_fleet() {
    local policy="$1"
    local fleet_file="$2"
    
    if [[ ! -f "$fleet_file" ]]; then
        log_action "ERROR: Fleet file not found: $fleet_file"
        return 1
    fi
    
    log_action "Starting fleet deployment of network monitoring policy: $policy"
    
    while IFS= read -r host; do
        [[ -z "$host" || "$host" =~ ^#.*$ ]] && continue
        
        echo "Deploying to: $host"
        
        # Copy this script to remote host and execute
        ssh "$host" "bash -s" << EOF
#!/bin/bash
# Remote deployment of network monitoring policy: $policy

# Create directories
mkdir -p /etc/macfleet/{network_monitoring,reports,compliance,audit,alerts}

# Apply the policy (simplified for remote execution)
$(declare -p APP_CATEGORIES)
$(declare -p MONITORING_POLICIES)
$(type apply_monitoring_policy | sed '1d')

apply_monitoring_policy "$policy"
EOF
        
        if [[ $? -eq 0 ]]; then
            log_action "Successfully deployed to: $host"
        else
            log_action "Failed to deploy to: $host"
        fi
        
    done < "$fleet_file"
    
    log_action "Fleet deployment completed"
}

# Main execution function
main() {
    create_directories
    
    case "${1:-}" in
        "monitor_activity")
            get_network_activity "${2:-standard}"
            ;;
        "analyze_bandwidth")
            analyze_bandwidth_usage "${2:-30}"
            ;;
        "detect_threats")
            detect_security_threats "${2:-standard}"
            ;;
        "apply_policy")
            apply_monitoring_policy "$2"
            ;;
        "realtime_monitor")
            start_realtime_monitoring "${2:-10}" "${3:-100}"
            ;;
        "control_access")
            control_network_access "$2" "$3" "${4:-manual}"
            ;;
        "health_check")
            perform_health_check
            ;;
        "report")
            generate_compliance_report "${2:-manual}"
            ;;
        "deploy")
            deploy_to_fleet "$2" "$3"
            ;;
        "help"|*)
            echo "MacFleet Enterprise Network Monitoring System"
            echo ""
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  monitor_activity [level]            - Monitor network activity (standard|detailed|security)"
            echo "  analyze_bandwidth [duration]        - Analyze bandwidth usage for duration in seconds"
            echo "  detect_threats [mode]               - Detect security threats (standard|strict|paranoid)"
            echo "  apply_policy <policy>               - Apply monitoring policy (strict_monitoring|balanced_monitoring|minimal_monitoring|development_focused|security_lockdown)"
            echo "  realtime_monitor [interval] [threshold] - Start real-time monitoring"
            echo "  control_access <action> <target> [reason] - Control network access (block_process|block_domain|unblock_domain|limit_bandwidth)"
            echo "  health_check                        - Perform system health check"
            echo "  report [policy]                     - Generate compliance report"
            echo "  deploy <policy> <fleet_file>        - Deploy policy to fleet"
            echo ""
            echo "Examples:"
            echo "  $0 monitor_activity detailed"
            echo "  $0 analyze_bandwidth 60"
            echo "  $0 detect_threats strict"
            echo "  $0 apply_policy strict_monitoring"
            echo "  $0 control_access block_domain malicious-site.com"
            echo "  $0 health_check"
            ;;
    esac
}

# Execute main function
main "$@"

Network Monitoring Categories

The enterprise system monitors applications across different categories:

CategoryApplicationsMonitoring Level
Business AppsSlack, Zoom, Microsoft Teams, Office 365Standard monitoring
Development ToolsXcode, Visual Studio Code, Docker, GitEnhanced logging
BrowsersChrome, Firefox, Safari, EdgeTraffic analysis
CommunicationMail, Messages, FaceTime, SkypeSecurity scanning
Cloud StorageDropbox, Google Drive, OneDriveData transfer monitoring
EntertainmentSpotify, Netflix, YouTube, SteamBandwidth limiting
Security Tools1Password, Little Snitch, WiresharkPriority access
System Serviceslocationd, cloudd, nsurlsessiondSystem health monitoring

Advanced Network Analysis

Real-time Bandwidth Monitoring

# Monitor bandwidth usage for 60 seconds
./network_monitor.sh analyze_bandwidth 60

# Check for high-bandwidth processes
nettop -P -t wifi -l 1 | head -20

Security Threat Detection

# Run security threat scan
./network_monitor.sh detect_threats strict

# Check for suspicious connections
lsof -nPi | grep -E ":(22|23|3389|5900|6667)"

Connection Analysis

# Detailed connection analysis
lsof -nPi | awk '{print $1, $8, $9}' | sort | uniq -c | sort -nr

# Monitor specific application
lsof -nPi | grep -i "chrome"

Policy Implementation

Apply Enterprise Monitoring Policy

# Strict monitoring for secure environments
./network_monitor.sh apply_policy strict_monitoring

# Balanced monitoring for general use
./network_monitor.sh apply_policy balanced_monitoring

# Development-focused monitoring
./network_monitor.sh apply_policy development_focused

Network Access Control

# Block suspicious process
./network_monitor.sh control_access block_process "suspicious_app" "security_violation"

# Block malicious domain
./network_monitor.sh control_access block_domain "malicious-site.com" "threat_detected"

# Unblock domain after verification
./network_monitor.sh control_access unblock_domain "example.com" "false_positive"

Enterprise Features

Automated Threat Response

The system can automatically respond to threats:

  • Block suspicious processes
  • Quarantine network connections
  • Alert security teams
  • Generate incident reports

Bandwidth Management

Monitor and control bandwidth usage:

  • Identify bandwidth-heavy applications
  • Implement quality of service (QoS) rules
  • Generate usage reports
  • Alert on excessive consumption

Compliance Monitoring

Track network activity for compliance:

  • Log all network connections
  • Monitor data transfer volumes
  • Detect policy violations
  • Generate audit reports

Important Security Considerations

  • Real-time monitoring requires appropriate system resources
  • Network analysis should respect user privacy policies
  • Threat detection may generate false positives requiring validation
  • Access controls should include emergency override procedures
  • Audit logging must be protected from unauthorized access

Compliance and Reporting

The enterprise system provides comprehensive audit trails for:

  • SOX Compliance - Financial data network access controls
  • HIPAA Requirements - Healthcare information transmission monitoring
  • PCI-DSS Standards - Payment card industry network security
  • NIST Framework - Cybersecurity network monitoring standards
  • ISO 27001 - Information security network management

Testing and Validation

Before enterprise deployment:

  1. Test monitoring accuracy with known network activities
  2. Verify threat detection effectiveness and false positive rates
  3. Confirm policy enforcement works as expected
  4. Test emergency procedures and override mechanisms
  5. Validate compliance reporting completeness and accuracy

This comprehensive system transforms basic network monitoring into an enterprise-grade security and management platform with advanced threat detection, policy enforcement, and fleet deployment capabilities.

Retrieve Network Information on macOS

Collect detailed network information from your MacFleet devices using command-line tools. This tutorial covers MAC address discovery, IP configuration, port monitoring, and network diagnostics for comprehensive fleet management.

Understanding macOS Network Information

macOS provides several command-line utilities for network information gathering:

  • networksetup - Hardware port and network configuration management
  • ifconfig - Network interface configuration and status
  • netstat - Network connections and port information
  • arp - Address Resolution Protocol table management
  • ipconfig - IP address and DHCP configuration

Retrieve MAC Addresses

List All Hardware Ports

#!/bin/bash

# Display all network hardware ports and their MAC addresses
networksetup -listallhardwareports

echo "Hardware port information retrieved successfully"

Get Specific Interface MAC Address

#!/bin/bash

# Get MAC address for specific interface (Wi-Fi)
echo "Wi-Fi Interface (en0) MAC Address:"
networksetup -getmacaddress en0

echo -e "\nEthernet Interface (en1) MAC Address:"
networksetup -getmacaddress en1

echo -e "\nThunderbolt Bridge (bridge0) MAC Address:"
networksetup -getmacaddress bridge0 2>/dev/null || echo "Thunderbolt Bridge not available"

Comprehensive MAC Address Report

#!/bin/bash

# Generate detailed MAC address report
echo "=== MacFleet Network Hardware Report ==="
echo "Device: $(hostname)"
echo "Date: $(date)"
echo "========================================="

# Get all hardware ports
echo -e "\n📡 Network Hardware Inventory:"
networksetup -listallhardwareports

echo -e "\n🔍 Primary Interface Details:"
echo "Wi-Fi (en0): $(networksetup -getmacaddress en0 | awk '{print $3}')"
echo "Ethernet (en1): $(networksetup -getmacaddress en1 | awk '{print $3}' 2>/dev/null || echo 'Not available')"

# Check for additional interfaces
echo -e "\n🌐 Additional Interfaces:"
for i in {2..5}; do
    mac_addr=$(networksetup -getmacaddress en$i 2>/dev/null | awk '{print $3}')
    if [[ -n "$mac_addr" && "$mac_addr" != "not" ]]; then
        echo "en$i: $mac_addr"
    fi
done

Discover IP Addresses

Basic IP Address Retrieval

#!/bin/bash

# Get IP address for Wi-Fi interface
WIFI_IP=$(ipconfig getifaddr en0 2>/dev/null)
ETHERNET_IP=$(ipconfig getifaddr en1 2>/dev/null)

echo "Network IP Addresses:"
echo "Wi-Fi (en0): ${WIFI_IP:-Not connected}"
echo "Ethernet (en1): ${ETHERNET_IP:-Not connected}"

Comprehensive IP Configuration

#!/bin/bash

# Detailed IP configuration report
echo "=== MacFleet IP Configuration Report ==="
echo "Device: $(hostname)"
echo "Timestamp: $(date)"
echo "========================================"

# Active network interfaces
echo -e "\n🌐 Active Network Interfaces:"
for interface in en0 en1 en2 en3; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        echo "$interface: $ip_addr"
        
        # Get additional details for active interfaces
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        router=$(ipconfig getoption $interface router 2>/dev/null)
        dns_servers=$(ipconfig getoption $interface domain_name_server 2>/dev/null)
        
        echo "  Subnet: ${subnet_mask:-N/A}"
        echo "  Gateway: ${router:-N/A}"
        echo "  DNS: ${dns_servers:-N/A}"
        echo ""
    fi
done

# Public IP address
echo "🌍 External IP Address:"
curl -s ifconfig.me 2>/dev/null || echo "Unable to retrieve external IP"

Network Interface Status

#!/bin/bash

# Monitor network interface status
echo "=== Network Interface Status Monitor ==="

# Get interface statistics
echo -e "\n📊 Interface Statistics:"
ifconfig | grep -E "(en[0-9]:|inet |status:|media:)" | while read line; do
    echo "$line"
done

echo -e "\n🔄 DHCP Lease Information:"
for interface in en0 en1; do
    lease_info=$(ipconfig getpacket $interface 2>/dev/null)
    if [[ -n "$lease_info" ]]; then
        echo "Interface $interface:"
        echo "$lease_info" | grep -E "(lease_time|server_identifier|domain_name)"
        echo ""
    fi
done

Analyze Network Configuration

Complete Network Overview

#!/bin/bash

# Comprehensive network configuration analysis
echo "=== Complete Network Overview ==="
ifconfig

echo -e "\n🔍 Network Summary:"
ifconfig | grep -E "^[a-z]" | while read line; do
    interface=$(echo $line | cut -d: -f1)
    status=$(ifconfig $interface | grep "status:" | cut -d' ' -f2-)
    echo "$interface: ${status:-active}"
done

Network Services and DNS

#!/bin/bash

# Network services and DNS configuration
echo "=== Network Services Configuration ==="

echo "🌐 DNS Configuration:"
echo "System DNS Servers:"
scutil --dns | grep "nameserver" | head -5

echo -e "\n📡 Network Services:"
networksetup -listallnetworkservices

echo -e "\n🔍 Active Network Service Details:"
active_service=$(networksetup -listallnetworkservices | grep -v "asterisk" | head -2 | tail -1)
if [[ -n "$active_service" ]]; then
    echo "Service: $active_service"
    networksetup -getinfo "$active_service"
fi

Subnet and Routing Information

#!/bin/bash

# Subnet mask and routing information
echo "=== Routing and Subnet Information ==="

echo "🛣️  Routing Table:"
netstat -rn | head -10

echo -e "\n🔍 Interface Subnet Details:"
for interface in en0 en1; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        echo "$interface: $ip_addr/${subnet_mask:-unknown}"
    fi
done

Monitor Port Information

Active TCP Connections

#!/bin/bash

# Display active TCP connections
echo "=== Active TCP Connections ==="
netstat -ap TCP

echo -e "\n📊 Connection Summary:"
echo "Total connections: $(netstat -ap TCP | grep -c ESTABLISHED)"
echo "Listening ports: $(netstat -ap TCP | grep -c LISTEN)"
echo "Time-wait connections: $(netstat -ap TCP | grep -c TIME_WAIT)"

Listening Ports Analysis

#!/bin/bash

# Analyze listening ports
echo "=== Listening Ports Analysis ==="

echo "🔍 All Listening Ports:"
netstat -a | grep -i "LISTEN"

echo -e "\n📋 Listening Ports Summary:"
netstat -a | grep -i "LISTEN" | awk '{print $4}' | cut -d. -f2 | sort -n | uniq -c | sort -nr

echo -e "\n🔒 Security-Relevant Ports:"
netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995|587|25|53|21|23) "

Port Monitoring Script

#!/bin/bash

# Comprehensive port monitoring
LOG_FILE="/var/log/macfleet_ports.log"

monitor_ports() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    {
        echo "=== Port Monitoring Report ==="
        echo "Timestamp: $timestamp"
        echo "Device: $(hostname)"
        echo "================================"
        
        echo -e "\n🔍 Current Listening Ports:"
        netstat -a | grep -i "LISTEN" | head -20
        
        echo -e "\n📊 Connection Statistics:"
        echo "ESTABLISHED: $(netstat -ap TCP | grep -c ESTABLISHED)"
        echo "LISTEN: $(netstat -ap TCP | grep -c LISTEN)"
        echo "TIME_WAIT: $(netstat -ap TCP | grep -c TIME_WAIT)"
        echo "CLOSE_WAIT: $(netstat -ap TCP | grep -c CLOSE_WAIT)"
        
        echo -e "\n🚨 Suspicious Connections:"
        netstat -ap TCP | grep -E ":(6667|6697|8080|9050|4444|31337)" || echo "None detected"
        
    } | tee -a "$LOG_FILE"
}

# Execute monitoring
monitor_ports

Display ARP Table

Basic ARP Information

#!/bin/bash

# Display Address Resolution Protocol table
arp -a

echo "ARP table retrieved successfully"

Detailed ARP Analysis

#!/bin/bash

# Comprehensive ARP table analysis
echo "=== ARP Table Analysis ==="
echo "Device: $(hostname)"
echo "Date: $(date)"
echo "=========================="

echo -e "\n🔍 Complete ARP Table:"
arp -a

echo -e "\n📊 ARP Statistics:"
total_entries=$(arp -a | wc -l)
incomplete_entries=$(arp -a | grep -c "incomplete")
complete_entries=$((total_entries - incomplete_entries))

echo "Total ARP entries: $total_entries"
echo "Complete entries: $complete_entries"
echo "Incomplete entries: $incomplete_entries"

echo -e "\n🌐 Network Neighbors:"
arp -a | head -10 | while read line; do
    hostname=$(echo $line | cut -d' ' -f1)
    ip=$(echo $line | cut -d'(' -f2 | cut -d')' -f1)
    mac=$(echo $line | cut -d' ' -f4)
    echo "$ip -> $mac ($hostname)"
done

ARP Security Check

#!/bin/bash

# ARP table security analysis
echo "=== ARP Security Analysis ==="

# Check for duplicate MAC addresses (potential ARP spoofing)
echo "🔒 Duplicate MAC Address Check:"
arp -a | awk '{print $4}' | sort | uniq -d | while read mac; do
    if [[ -n "$mac" ]]; then
        echo "⚠️  Duplicate MAC detected: $mac"
        arp -a | grep "$mac"
    fi
done

# Check for suspicious patterns
echo -e "\n🚨 Security Alerts:"
suspicious_count=$(arp -a | grep -c "incomplete")
if [[ $suspicious_count -gt 10 ]]; then
    echo "⚠️  High number of incomplete ARP entries: $suspicious_count"
fi

# Network vendor analysis
echo -e "\n🏢 Network Vendor Analysis:"
arp -a | grep -E "([0-9a-f]{2}:){5}[0-9a-f]{2}" | awk '{print $4}' | cut -d: -f1-3 | sort | uniq -c | sort -nr | head -5

Enterprise Network Monitoring Script

#!/bin/bash

# MacFleet Enterprise Network Monitoring Suite
LOG_FILE="/var/log/macfleet_network.log"
REPORT_FILE="/tmp/network_report_$(date +%Y%m%d_%H%M%S).txt"

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

# Generate comprehensive network report
generate_network_report() {
    {
        echo "MacFleet Network Assessment Report"
        echo "Generated: $(date)"
        echo "Device: $(hostname)"
        echo "User: $(whoami)"
        echo "OS Version: $(sw_vers -productVersion)"
        echo "=========================================="
        echo ""
        
        # Hardware inventory
        echo "🔧 Network Hardware:"
        networksetup -listallhardwareports
        echo ""
        
        # IP configuration
        echo "🌐 IP Configuration:"
        for interface in en0 en1 en2; do
            ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
            if [[ -n "$ip_addr" ]]; then
                echo "$interface: $ip_addr"
                mac_addr=$(networksetup -getmacaddress $interface | awk '{print $3}')
                echo "  MAC: $mac_addr"
                
                subnet=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
                router=$(ipconfig getoption $interface router 2>/dev/null)
                echo "  Subnet: ${subnet:-N/A}"
                echo "  Gateway: ${router:-N/A}"
                echo ""
            fi
        done
        
        # Network services
        echo "📡 Network Services:"
        networksetup -listallnetworkservices | grep -v "asterisk"
        echo ""
        
        # DNS configuration
        echo "🔍 DNS Configuration:"
        scutil --dns | grep "nameserver" | head -3
        echo ""
        
        # Security assessment
        echo "🔒 Security Assessment:"
        listening_ports=$(netstat -a | grep -c "LISTEN")
        established_connections=$(netstat -ap TCP | grep -c ESTABLISHED)
        echo "Listening ports: $listening_ports"
        echo "Active connections: $established_connections"
        
        # Check for common security ports
        security_ports=$(netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995)" | wc -l)
        echo "Security-relevant ports: $security_ports"
        
        echo ""
        echo "Report completed at: $(date)"
        
    } > "$REPORT_FILE"
    
    echo "📊 Network report generated: $REPORT_FILE"
}

# Network connectivity test
test_connectivity() {
    echo "=== Network Connectivity Test ==="
    
    # Test DNS resolution
    if nslookup google.com > /dev/null 2>&1; then
        echo "✅ DNS resolution: Working"
    else
        echo "❌ DNS resolution: Failed"
    fi
    
    # Test internet connectivity
    if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
        echo "✅ Internet connectivity: Working"
    else
        echo "❌ Internet connectivity: Failed"
    fi
    
    # Test local gateway
    gateway=$(route -n get default | grep gateway | awk '{print $2}')
    if [[ -n "$gateway" ]] && ping -c 1 "$gateway" > /dev/null 2>&1; then
        echo "✅ Gateway connectivity: Working ($gateway)"
    else
        echo "❌ Gateway connectivity: Failed"
    fi
}

# Main execution
main() {
    log_action "=== MacFleet Network Monitoring Started ==="
    
    generate_network_report
    echo ""
    test_connectivity
    
    log_action "Network monitoring completed. Report: $REPORT_FILE"
}

# Execute main function
main "$@"

Network Information Reference

Common Network Interfaces

InterfaceDescriptionCommon Usage
en0Primary network interfaceWi-Fi connection
en1Secondary interfaceEthernet connection
en2-en5Additional interfacesUSB adapters, Thunderbolt
lo0Loopback interfaceLocal system communication
bridge0Thunderbolt bridgeDevice-to-device connections
utun0-utun3Tunnel interfacesVPN connections

Network Commands Quick Reference

# Get interface IP
ipconfig getifaddr en0

# Get interface configuration
ipconfig getoption en0 subnet_mask
ipconfig getoption en0 router
ipconfig getoption en0 domain_name_server

# Network hardware
networksetup -listallhardwareports
networksetup -getmacaddress en0

# Interface status
ifconfig en0
ifconfig -a

# Network connections
netstat -rn          # Routing table
netstat -i           # Interface statistics
netstat -ap TCP      # TCP connections

# ARP operations
arp -a               # Show ARP table
arp -d hostname      # Delete ARP entry

Advanced Network Diagnostics

Network Performance Testing

#!/bin/bash

# Network performance diagnostics
echo "=== Network Performance Diagnostics ==="

# Interface statistics
echo "📊 Interface Statistics:"
netstat -i

# Bandwidth monitoring
echo -e "\n🚀 Network Activity (10 seconds):"
if command -v nettop >/dev/null 2>&1; then
    timeout 10 nettop -l 1 -J bytes_in,bytes_out -P
else
    echo "nettop not available, using netstat"
    netstat -i
fi

# Latency testing
echo -e "\n⏱️  Latency Tests:"
echo "Google DNS (8.8.8.8):"
ping -c 3 8.8.8.8 | tail -1

echo "Cloudflare DNS (1.1.1.1):"
ping -c 3 1.1.1.1 | tail -1

Wireless Network Information

#!/bin/bash

# Wireless network detailed information
echo "=== Wireless Network Analysis ==="

# Current Wi-Fi information
current_wifi=$(networksetup -getairportnetwork en0)
echo "Current Wi-Fi: $current_wifi"

# Wi-Fi power status
wifi_power=$(networksetup -getairportpower en0)
echo "Wi-Fi Power: $wifi_power"

# Available networks (requires admin privileges)
echo -e "\n📡 Available Networks:"
if [[ $EUID -eq 0 ]]; then
    airport -s 2>/dev/null || echo "Airport utility not available"
else
    echo "Admin privileges required for network scanning"
fi

# Wi-Fi interface details
echo -e "\n🔍 Wi-Fi Interface Details:"
ifconfig en0 | grep -E "(inet|ether|status)"

Important Notes

  • Interface names may vary between macOS versions and hardware
  • Administrative privileges required for some network operations
  • Security implications - Monitor open ports and connections regularly
  • Performance impact - Network monitoring scripts may affect system performance
  • Privacy considerations - ARP tables contain information about network neighbors

Troubleshooting

Common Network Issues

No IP Address:

# Renew DHCP lease
sudo ipconfig set en0 DHCP

DNS Resolution Problems:

# Flush DNS cache
sudo dscacheutil -flushcache

Interface Not Responding:

# Reset network interface
sudo ifconfig en0 down
sudo ifconfig en0 up

Remember to test these scripts on individual devices before deploying across your MacFleet environment.

Menu Bar Customization and Icon Management on macOS

Customize menu bar appearance and manage system icons across your MacFleet devices. This tutorial covers icon visibility control, user interface optimization, and enterprise-grade menu bar management for improved user experience and organizational consistency.

Understanding Menu Bar Management

The macOS menu bar contains various system indicators and quick access icons:

  • Network indicators - VPN, Wi-Fi, Bluetooth status
  • System monitors - Battery, volume, date/time
  • Application icons - Third-party app status indicators
  • User controls - Spotlight, Control Center, Siri
  • Corporate tools - MDM agents, security software

Basic VPN Icon Management

Hide VPN Icon from Menu Bar

#!/bin/bash

# Hide VPN icon from menu bar
hide_vpn_icon() {
    echo "=== Hiding VPN Icon from Menu Bar ==="
    
    # Get current user
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Current user: $currentUser"
    
    # Function to run commands as current user
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Remove VPN menu extra
    if runAsUser /usr/libexec/PlistBuddy -c 'delete menuExtras: "/System/Library/CoreServices/Menu Extras/VPN.menu"' "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ VPN menu entry removed"
    else
        echo "⚠️  VPN menu entry not found or already removed"
    fi
    
    # Restart system services to apply changes
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "🔄 System UI refreshed"
    echo "✅ VPN icon hidden from menu bar"
}

# Execute function
hide_vpn_icon

Show VPN Icon in Menu Bar

#!/bin/bash

# Show VPN icon in menu bar
show_vpn_icon() {
    echo "=== Adding VPN Icon to Menu Bar ==="
    
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Current user: $currentUser"
    
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Add VPN menu extra
    local vpn_path="/System/Library/CoreServices/Menu Extras/VPN.menu"
    if runAsUser /usr/libexec/PlistBuddy -c "add menuExtras: string '$vpn_path'" "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ VPN menu entry added"
    else
        echo "⚠️  VPN menu entry already exists"
    fi
    
    # Restart system services
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "✅ VPN icon shown in menu bar"
}

# Execute function
show_vpn_icon

Enterprise Menu Bar Management System

#!/bin/bash

# MacFleet Enterprise Menu Bar Management System
# Comprehensive interface customization, user experience optimization, and fleet deployment

# Configuration
LOG_FILE="/var/log/macfleet_menubar.log"
CONFIG_DIR="/etc/macfleet/interface"
PROFILES_DIR="$CONFIG_DIR/profiles"
BACKUP_DIR="/var/backups/menubar_configs"
REPORTS_DIR="$CONFIG_DIR/reports"

# Available menu extras
declare -A MENU_EXTRAS=(
    ["vpn"]="/System/Library/CoreServices/Menu Extras/VPN.menu"
    ["wifi"]="/System/Library/CoreServices/Menu Extras/AirPort.menu"
    ["bluetooth"]="/System/Library/CoreServices/Menu Extras/Bluetooth.menu"
    ["volume"]="/System/Library/CoreServices/Menu Extras/Volume.menu"
    ["battery"]="/System/Library/CoreServices/Menu Extras/Battery.menu"
    ["clock"]="/System/Library/CoreServices/Menu Extras/Clock.menu"
    ["displays"]="/System/Library/CoreServices/Menu Extras/Displays.menu"
    ["timemachine"]="/System/Library/CoreServices/Menu Extras/TimeMachine.menu"
    ["textinput"]="/System/Library/CoreServices/Menu Extras/TextInput.menu"
    ["script"]="/System/Library/CoreServices/Menu Extras/Script Menu.menu"
)

# Profile configurations
declare -A MENU_PROFILES=(
    ["minimal"]="clock,battery,wifi"
    ["standard"]="clock,battery,wifi,volume,bluetooth"
    ["full"]="clock,battery,wifi,volume,bluetooth,displays,vpn"
    ["corporate"]="clock,battery,wifi,vpn,timemachine"
    ["education"]="clock,battery,wifi,volume,textinput"
    ["kiosk"]="clock,battery"
    ["developer"]="clock,battery,wifi,volume,bluetooth,displays,script"
    ["secure"]="clock,battery,wifi"
)

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

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

# Get current user
get_current_user() {
    local user
    user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$user" == "loginwindow" || -z "$user" ]]; then
        return 1
    fi
    
    echo "$user"
    return 0
}

# Execute command as current user
run_as_user() {
    local user="$1"
    shift
    
    local userID
    userID=$(id -u "$user" 2>/dev/null) || return 1
    
    /bin/launchctl asuser "$userID" sudo -u "$user" "$@"
}

# Get current menu bar configuration
get_current_menubar_config() {
    local user="$1"
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    
    if [[ ! -f "$plist_path" ]]; then
        echo "[]"
        return 1
    fi
    
    # Extract current menu extras
    local menu_extras
    menu_extras=$(run_as_user "$user" /usr/libexec/PlistBuddy -c "print menuExtras:" "$plist_path" 2>/dev/null | grep -E "\.menu$" | sed 's/^[ ]*//' || echo "")
    
    if [[ -z "$menu_extras" ]]; then
        echo "[]"
    else
        echo "$menu_extras" | jq -R -s 'split("\n") | map(select(length > 0))'
    fi
}

# Apply menu bar profile
apply_menubar_profile() {
    local profile_name="$1"
    local target_user="$2"
    
    log_action "Applying menu bar profile: $profile_name"
    
    # Get profile configuration
    local profile_config="${MENU_PROFILES[$profile_name]}"
    if [[ -z "$profile_config" ]]; then
        log_action "❌ Unknown profile: $profile_name"
        return 1
    fi
    
    # Get target users
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Get all users with UID >= 500
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Apply profile to each user
    for user in "${users[@]}"; do
        log_action "Configuring menu bar for user: $user"
        
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Backup current configuration
        backup_user_menubar_config "$user"
        
        # Clear existing menu extras
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Add profile menu items
        IFS=',' read -ra ITEMS <<< "$profile_config"
        local index=0
        
        for item in "${ITEMS[@]}"; do
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                log_action "Added menu item: $item for user: $user"
                ((index++))
            else
                log_action "⚠️  Menu item not found: $item"
            fi
        done
        
        # Restart UI services
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Profile '$profile_name' applied to user: $user"
    done
    
    return 0
}

# Backup user menu bar configuration
backup_user_menubar_config() {
    local user="$1"
    local timestamp
    timestamp=$(date '+%Y%m%d_%H%M%S')
    
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    local backup_file="$BACKUP_DIR/menubar_${user}_${timestamp}.plist"
    
    if [[ -f "$plist_path" ]]; then
        cp "$plist_path" "$backup_file" 2>/dev/null
        log_action "Backed up menu bar config for $user: $backup_file"
        echo "$backup_file"
    fi
}

# Custom menu bar configuration
configure_custom_menubar() {
    local items_string="$1"
    local target_user="$2"
    
    log_action "Applying custom menu bar configuration: $items_string"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Parse items
    IFS=',' read -ra ITEMS <<< "$items_string"
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Backup and clear
        backup_user_menubar_config "$user"
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Add custom items
        local index=0
        for item in "${ITEMS[@]}"; do
            # Remove whitespace
            item=$(echo "$item" | sed 's/^[ \t]*//;s/[ \t]*$//')
            
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                ((index++))
            fi
        done
        
        # Apply changes
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Custom configuration applied to user: $user"
    done
}

# Generate menu bar audit report
generate_menubar_audit() {
    log_action "Generating menu bar audit report"
    
    local report_file="$REPORTS_DIR/menubar_audit_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$report_file" << EOF
{
    "audit_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)",
        "os_version": "$(sw_vers -productVersion)",
        "generator": "MacFleet Menu Bar Manager"
    },
    "user_configurations": [
EOF

    local first=true
    local total_users=0
    
    # Audit each user
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        total_users=$((total_users + 1))
        
        if [[ "$first" == true ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        
        local current_config
        current_config=$(get_current_menubar_config "$user")
        
        local last_login
        last_login=$(last -1 "$user" | head -1 | awk '{print $4, $5, $6, $7}' || echo 'Never')
        
        cat >> "$report_file" << EOF
        {
            "username": "$user",
            "current_menu_items": $current_config,
            "item_count": $(echo "$current_config" | jq 'length'),
            "last_login": "$last_login",
            "config_file_exists": $([ -f "/Users/$user/Library/Preferences/com.apple.systemuiserver.plist" ] && echo "true" || echo "false")
        }
EOF
        
        log_action "Audited user: $user"
    done
    
    cat >> "$report_file" << EOF
    ],
    "summary": {
        "total_users": $total_users,
        "available_menu_items": $(echo "${!MENU_EXTRAS[@]}" | tr ' ' '\n' | jq -R . | jq -s .),
        "available_profiles": $(echo "${!MENU_PROFILES[@]}" | tr ' ' '\n' | jq -R . | jq -s .)
    }
}
EOF

    log_action "✅ Menu bar audit completed: $report_file"
    echo "$report_file"
}

# Restore menu bar configuration from backup
restore_menubar_config() {
    local backup_file="$1"
    local target_user="$2"
    
    if [[ ! -f "$backup_file" ]]; then
        log_action "❌ Backup file not found: $backup_file"
        return 1
    fi
    
    log_action "Restoring menu bar configuration from: $backup_file"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Extract username from backup filename
        local extracted_user
        extracted_user=$(basename "$backup_file" | sed 's/menubar_\(.*\)_[0-9]*_[0-9]*.plist/\1/')
        if [[ -n "$extracted_user" ]]; then
            users=("$extracted_user")
        fi
    fi
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Create current backup before restore
        backup_user_menubar_config "$user"
        
        # Restore configuration
        if cp "$backup_file" "$plist_path" 2>/dev/null; then
            chown "$user:staff" "$plist_path" 2>/dev/null
            
            # Apply changes
            run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
            run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
            
            log_action "✅ Configuration restored for user: $user"
        else
            log_action "❌ Failed to restore configuration for user: $user"
            return 1
        fi
    done
    
    return 0
}

# Monitor menu bar changes
monitor_menubar_changes() {
    local duration="${1:-3600}"  # 1 hour default
    local check_interval="${2:-60}"  # 1 minute default
    
    log_action "Starting menu bar monitoring for ${duration} seconds"
    
    local monitoring_report="$REPORTS_DIR/menubar_monitoring_$(date '+%Y%m%d_%H%M%S').json"
    local baseline_file="/tmp/menubar_baseline.json"
    
    # Create baseline
    generate_menubar_audit > "$baseline_file"
    
    cat > "$monitoring_report" << EOF
{
    "monitoring_metadata": {
        "start_time": "$(date -Iseconds)",
        "duration_seconds": $duration,
        "check_interval_seconds": $check_interval,
        "hostname": "$(hostname)"
    },
    "changes_detected": [
EOF

    local start_time end_time
    start_time=$(date +%s)
    end_time=$((start_time + duration))
    
    local first=true
    while [[ $(date +%s) -lt $end_time ]]; do
        sleep "$check_interval"
        
        # Check for changes
        local current_state="/tmp/menubar_current.json"
        generate_menubar_audit > "$current_state"
        
        if ! diff "$baseline_file" "$current_state" >/dev/null 2>&1; then
            if [[ "$first" == true ]]; then
                first=false
            else
                echo "," >> "$monitoring_report"
            fi
            
            cat >> "$monitoring_report" << EOF
        {
            "timestamp": "$(date -Iseconds)",
            "change_type": "menu_bar_configuration_change",
            "details": "Changes detected in menu bar configuration"
        }
EOF
            
            log_action "⚠️  Menu bar configuration changes detected"
            cp "$current_state" "$baseline_file"
        fi
        
        rm -f "$current_state"
    done
    
    cat >> "$monitoring_report" << EOF
    ],
    "end_time": "$(date -Iseconds)"
}
EOF

    log_action "✅ Menu bar monitoring completed: $monitoring_report"
    rm -f "$baseline_file"
    echo "$monitoring_report"
}

# Main execution function
main() {
    local action="${1:-audit}"
    local parameter="$2"
    local additional_param="$3"
    
    log_action "=== MacFleet Menu Bar Management Started ==="
    log_action "Action: $action"
    log_action "Parameter: ${parameter:-N/A}"
    
    setup_directories
    
    case "$action" in
        "profile")
            if [[ -z "$parameter" ]]; then
                echo "Available menu bar profiles:"
                for profile in "${!MENU_PROFILES[@]}"; do
                    echo "  - $profile: ${MENU_PROFILES[$profile]}"
                done
                echo ""
                echo "Usage: $0 profile <profile_name> [username]"
                exit 1
            fi
            apply_menubar_profile "$parameter" "$additional_param"
            ;;
        "custom")
            if [[ -z "$parameter" ]]; then
                echo "Available menu items:"
                for item in "${!MENU_EXTRAS[@]}"; do
                    echo "  - $item"
                done
                echo ""
                echo "Usage: $0 custom <item1,item2,item3> [username]"
                echo "Example: $0 custom clock,battery,wifi,vpn john.doe"
                exit 1
            fi
            configure_custom_menubar "$parameter" "$additional_param"
            ;;
        "audit")
            generate_menubar_audit
            ;;
        "monitor")
            monitor_menubar_changes "$parameter" "$additional_param"
            ;;
        "restore")
            if [[ -z "$parameter" ]]; then
                echo "Usage: $0 restore <backup_file> [username]"
                echo "Available backups:"
                ls -la "$BACKUP_DIR"/*.plist 2>/dev/null || echo "No backups found"
                exit 1
            fi
            restore_menubar_config "$parameter" "$additional_param"
            ;;
        "hide-vpn")
            local user
            if user=$(get_current_user); then
                hide_vpn_icon
            else
                echo "❌ No active user session"
                exit 1
            fi
            ;;
        "show-vpn")
            local user
            if user=$(get_current_user); then
                show_vpn_icon
            else
                echo "❌ No active user session"
                exit 1
            fi
            ;;
        *)
            echo "Usage: $0 {profile|custom|audit|monitor|restore|hide-vpn|show-vpn}"
            echo "  profile     - Apply predefined menu bar profile"
            echo "  custom      - Apply custom menu bar configuration"
            echo "  audit       - Generate menu bar audit report"
            echo "  monitor     - Monitor menu bar changes over time"
            echo "  restore     - Restore from backup"
            echo "  hide-vpn    - Hide VPN icon from menu bar"
            echo "  show-vpn    - Show VPN icon in menu bar"
            exit 1
            ;;
    esac
    
    log_action "=== Menu bar management completed ==="
}

# Execute main function
main "$@"

Menu Bar Profile Examples

Corporate Profile Setup

#!/bin/bash

# Apply corporate menu bar profile across all devices
deploy_corporate_profile() {
    echo "=== Corporate Menu Bar Deployment ==="
    
    # Corporate profile: clock, battery, wifi, vpn, timemachine
    local corporate_items="clock,battery,wifi,vpn,timemachine"
    
    # Get all users
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        echo "Configuring corporate profile for: $user"
        
        # Apply configuration
        configure_custom_menubar "$corporate_items" "$user"
        
        # Verify application
        sleep 2
        local current_config
        current_config=$(get_current_menubar_config "$user")
        echo "Applied configuration: $current_config"
    done
    
    echo "✅ Corporate profile deployed to all users"
}

Kiosk Mode Configuration

#!/bin/bash

# Minimal menu bar for kiosk environments
setup_kiosk_menubar() {
    echo "=== Kiosk Menu Bar Setup ==="
    
    # Minimal items: clock and battery only
    local kiosk_items="clock,battery"
    
    local target_user="$1"
    if [[ -z "$target_user" ]]; then
        echo "Usage: setup_kiosk_menubar <username>"
        return 1
    fi
    
    configure_custom_menubar "$kiosk_items" "$target_user"
    
    echo "✅ Kiosk menu bar configured for: $target_user"
}

Advanced Menu Bar Features

Dynamic Profile Switching

#!/bin/bash

# Switch between different profiles based on conditions
smart_profile_switching() {
    local user="$1"
    
    echo "=== Smart Profile Switching ==="
    
    # Detect environment
    if pgrep -f "VPN" >/dev/null; then
        echo "VPN detected - applying corporate profile"
        apply_menubar_profile "corporate" "$user"
    elif [[ $(pmset -g batt | grep -c "Battery") -gt 0 ]]; then
        echo "Battery power detected - applying minimal profile"
        apply_menubar_profile "minimal" "$user"
    else
        echo "Standard environment - applying full profile"
        apply_menubar_profile "full" "$user"
    fi
}

Menu Bar Health Check

#!/bin/bash

# Verify menu bar configuration integrity
menubar_health_check() {
    echo "=== Menu Bar Health Check ==="
    
    local issues_found=0
    
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        if [[ ! -f "$plist_path" ]]; then
            echo "⚠️  Missing configuration file for user: $user"
            issues_found=$((issues_found + 1))
            continue
        fi
        
        # Check if SystemUIServer is running
        if ! pgrep -u "$(id -u "$user")" SystemUIServer >/dev/null; then
            echo "⚠️  SystemUIServer not running for user: $user"
            issues_found=$((issues_found + 1))
        fi
        
        # Validate plist format
        if ! plutil -lint "$plist_path" >/dev/null 2>&1; then
            echo "❌ Corrupted plist file for user: $user"
            issues_found=$((issues_found + 1))
        fi
    done
    
    if [[ $issues_found -eq 0 ]]; then
        echo "✅ All menu bar configurations are healthy"
    else
        echo "⚠️  Found $issues_found issues requiring attention"
    fi
    
    return $issues_found
}

Best Practices

🎯 User Experience Optimization

  • Consistent branding across all devices with standardized menu bar layouts
  • Profile-based configurations for different user roles and environments
  • Minimal kiosk setups for public or restricted-use devices
  • Dynamic switching based on power state or network conditions

🔧 Enterprise Management

  • Centralized deployment of menu bar configurations across device fleets
  • Backup and restore capabilities for configuration management
  • Audit reporting for compliance and standardization verification
  • Change monitoring with automated detection and alerting

🔐 Security Considerations

  • Remove sensitive indicators from public-facing devices
  • Hide VPN status in environments where network information should be private
  • Standardize corporate displays to prevent information leakage
  • Monitor unauthorized changes to menu bar configurations

📊 Monitoring and Maintenance

  • Regular health checks to ensure configuration integrity
  • Automated profile enforcement to maintain consistency
  • Change detection with rollback capabilities
  • User experience feedback collection and optimization

Important Notes

  • macOS 12+ required for optimal compatibility with modern menu extras
  • User session active required for menu bar modifications
  • System restart may be needed for some changes to take full effect
  • Test thoroughly before deploying to production environments
  • Backup configurations before making changes to allow easy rollback

Manage System Settings Panels on macOS

Control which System Settings panels users can access on macOS Ventura and later versions. This tutorial shows how to disable or hide specific preference panes to maintain security and prevent unwanted configuration changes across your MacFleet.

Understanding System Settings vs System Preferences

macOS Ventura (13.0+) replaced "System Preferences" with "System Settings". The management approach differs between versions:

  • macOS 13.0+: Use DisabledSystemSettings and bundle identifiers ending in .extension
  • macOS 12.x and earlier: Use DisabledPreferencePanes with different bundle identifiers

Disable System Settings Panels

Basic Disable Script

#!/bin/bash

# Disable specific System Settings panel
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "com.apple.Battery-Settings.extension"

echo "System Settings panel disabled successfully"

Disable Multiple Panels

#!/bin/bash

# Disable multiple System Settings panels
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings" \
    "com.apple.Network-Settings.extension" \
    "com.apple.Battery-Settings.extension"

echo "Multiple System Settings panels disabled"

System Settings Bundle Identifiers

Panel NameBundle Identifier
Accessibilitycom.apple.Accessibility-Settings.extension
AirDrop & Handoffcom.apple.AirDrop-Handoff-Settings.extension
Apple IDcom.apple.systempreferences.AppleIDSettings
Batterycom.apple.Battery-Settings.extension
Bluetoothcom.apple.BluetoothSettings
Control Centercom.apple.ControlCenter-Settings.extension
Date & Timecom.apple.Date-Time-Settings.extension
Desktop & Dockcom.apple.Desktop-Settings.extension
Displayscom.apple.Displays-Settings.extension
Extensionscom.apple.ExtensionsPreferences
Focuscom.apple.Focus-Settings.extension
Game Centercom.apple.Game-Center-Settings.extension
Internet Accountscom.apple.Internet-Accounts-Settings.extension
Keyboardcom.apple.Keyboard-Settings.extension
Language & Regioncom.apple.Localization-Settings.extension
Lock Screencom.apple.Lock-Screen-Settings.extension
Login Itemscom.apple.LoginItems-Settings.extension
Networkcom.apple.Network-Settings.extension
Notificationscom.apple.Notifications-Settings.extension
Passwordscom.apple.Passwords-Settings.extension
Printers & Scannerscom.apple.Print-Scan-Settings.extension
Screen Timecom.apple.Screen-Time-Settings.extension
Screen Savercom.apple.ScreenSaver-Settings.extension
Sharingcom.apple.Sharing-Settings.extension
Siri & Spotlightcom.apple.Siri-Settings.extension
Software Updatecom.apple.Software-Update-Settings.extension
Soundcom.apple.Sound-Settings.extension
Startup Diskcom.apple.Startup-Disk-Settings.extension
Storagecom.apple.settings.Storage
Time Machinecom.apple.Time-Machine-Settings.extension
Touch ID & Passwordcom.apple.Touch-ID-Settings.extension
Trackpadcom.apple.Trackpad-Settings.extension
Transfer or Resetcom.apple.Transfer-Reset-Settings.extension
Users & Groupscom.apple.Users-Groups-Settings.extension
Wallet & Apple Paycom.apple.WalletSettingsExtension
Wallpapercom.apple.Wallpaper-Settings.extension
Wi-Ficom.apple.wifi-settings-extension

Open System Settings Panels Remotely

Open Specific Panel

#!/bin/bash

# Open Network settings panel
open "x-apple.systempreferences:com.apple.Network-Settings.extension"

echo "Network settings panel opened"

Conditional Panel Opening

#!/bin/bash

PANEL_ID="com.apple.Battery-Settings.extension"

# Check if panel is not disabled before opening
if ! defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "$PANEL_ID"; then
    open "x-apple.systempreferences:$PANEL_ID"
    echo "Battery settings panel opened"
else
    echo "Battery settings panel is disabled"
fi

Re-enable Disabled Panels

Re-enable All Panels

#!/bin/bash

# Remove all disabled System Settings restrictions
defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

echo "All System Settings panels re-enabled"

Re-enable Specific Panels

#!/bin/bash

# Get current disabled panels
CURRENT_DISABLED=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null)

# Remove specific panel from disabled list (requires custom logic)
# This example shows the concept - implement based on your needs
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings"
    # Add other panels you want to keep disabled

echo "Specific System Settings panels re-enabled"

Enterprise Management Script

#!/bin/bash

# Enterprise System Settings Management
# Restricts access to sensitive configuration panels

RESTRICTED_PANELS=(
    "com.apple.Network-Settings.extension"
    "com.apple.BluetoothSettings"
    "com.apple.Security-Privacy-Settings.extension"
    "com.apple.Software-Update-Settings.extension"
    "com.apple.Users-Groups-Settings.extension"
)

# Apply restrictions
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "${RESTRICTED_PANELS[@]}"

# Verify restrictions
echo "Disabled System Settings panels:"
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null || echo "No panels currently disabled"

# Log the action
logger "MacFleet: System Settings panels restricted on $(date)"

Troubleshooting

Check Current Restrictions

# View currently disabled panels
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

# Check if specific panel is disabled
if defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "com.apple.Battery-Settings.extension"; then
    echo "Battery panel is disabled"
else
    echo "Battery panel is accessible"
fi

Clear All Restrictions

# Emergency reset - re-enable all panels
sudo defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings
sudo killall cfprefsd

Common Use Cases

ScenarioRecommended Panels to Disable
Shared WorkstationsUsers & Groups, Software Update, Network
BYOD DevicesApple ID, Transfer or Reset, Users & Groups
Kiosk ModeAll except essential panels for operation
Educational LabsNetwork, Software Update, Touch ID & Password
Corporate SecuritySoftware Update, Transfer or Reset, Sharing

Important Notes

  • macOS Compatibility: These scripts work only on macOS 13.0 (Ventura) and later
  • User Experience: Disabled panels appear grayed out but remain visible
  • System Restart: Changes take effect immediately without restart
  • Persistence: Settings persist across user sessions and system reboots

For devices running macOS 12.x and earlier, use the legacy System Preferences management approach with different bundle identifiers.

Manage Running Processes on macOS

Monitor and control running processes on your MacFleet devices using command-line tools. This tutorial covers CPU monitoring, memory analysis, process listing, and process termination for effective system management.

Understanding macOS Process Management

macOS provides several command-line tools for process management:

  • top - Real-time display of running processes and system usage
  • ps - Snapshot of current processes
  • kill - Terminate processes by PID
  • Activity Monitor - GUI equivalent for visual monitoring

Show CPU Utilization

Basic CPU Usage

#!/bin/bash

# Display current CPU utilization
top -l 1 -s 0 | grep "CPU usage"

echo "CPU utilization retrieved successfully"

Detailed CPU Analysis

#!/bin/bash

# Get comprehensive CPU information
echo "=== CPU Utilization Analysis ==="
echo "Current CPU Usage:"
top -l 1 -s 0 | grep "CPU usage"

echo -e "\nTop CPU-consuming processes:"
top -l 1 -s 0 | head -20 | tail -10

echo -e "\nLoad average:"
uptime

Show Memory Status

Basic Memory Information

#!/bin/bash

# Display memory utilization
top -l 1 -s 0 | grep PhysMem

echo "Memory status retrieved successfully"

Comprehensive Memory Analysis

#!/bin/bash

# Detailed memory report
echo "=== Memory Status Analysis ==="
echo "Physical Memory Usage:"
top -l 1 -s 0 | grep PhysMem

echo -e "\nVirtual Memory Statistics:"
vm_stat

echo -e "\nMemory pressure:"
memory_pressure

List Running Processes

View All Processes

#!/bin/bash

# List all running processes
ps aux

echo "Process list generated successfully"

Limited Process List

#!/bin/bash

# Show top 10 processes
echo "Top 10 running processes:"
ps aux | head -11

# Show specific number of processes (replace 15 with desired count)
echo -e "\nTop 15 processes:"
ps aux | head -16

Filtered Process Views

#!/bin/bash

# Show only user processes
echo "User processes:"
ps aux | grep -v "^root"

echo -e "\nSystem processes:"
ps aux | grep "^root" | head -10

echo -e "\nProcesses using most CPU:"
ps aux --sort=-%cpu | head -10

echo -e "\nProcesses using most memory:"
ps aux --sort=-%mem | head -10

Process Termination

Kill Process by PID

#!/bin/bash

# Kill specific process (replace PID with actual process ID)
PID="1234"

if kill -9 "$PID" 2>/dev/null; then
    echo "Process $PID terminated successfully"
else
    echo "Failed to terminate process $PID or process not found"
fi

Kill Process by Name

#!/bin/bash

# Kill process by application name
APP_NAME="Safari"

if pkill -f "$APP_NAME"; then
    echo "$APP_NAME processes terminated successfully"
else
    echo "No $APP_NAME processes found or termination failed"
fi

Safe Process Termination

#!/bin/bash

# Gracefully terminate process with confirmation
terminate_process() {
    local pid="$1"
    local process_name
    
    # Get process name
    process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
    
    if [[ -z "$process_name" ]]; then
        echo "Process $pid not found"
        return 1
    fi
    
    echo "Found process: $process_name (PID: $pid)"
    
    # Try graceful termination first
    if kill -TERM "$pid" 2>/dev/null; then
        echo "Sent termination signal to $process_name"
        sleep 3
        
        # Check if process still exists
        if kill -0 "$pid" 2>/dev/null; then
            echo "Process still running, forcing termination..."
            kill -9 "$pid" 2>/dev/null
        fi
        
        echo "Process $process_name terminated"
        return 0
    else
        echo "Failed to terminate process $process_name"
        return 1
    fi
}

# Usage example (replace with actual PID)
# terminate_process 1234

Enterprise Process Management Script

#!/bin/bash

# MacFleet Process Management Tool
# Monitor and manage processes across fleet devices

# Configuration
LOG_FILE="/var/log/macfleet_processes.log"
ALERT_CPU_THRESHOLD=80
ALERT_MEMORY_THRESHOLD=80

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

# Get system statistics
get_system_stats() {
    echo "=== System Statistics ==="
    
    # CPU usage
    local cpu_info
    cpu_info=$(top -l 1 -s 0 | grep "CPU usage")
    echo "CPU: $cpu_info"
    
    # Memory usage
    local mem_info
    mem_info=$(top -l 1 -s 0 | grep PhysMem)
    echo "Memory: $mem_info"
    
    # Load average
    echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
    
    # Top processes
    echo -e "\nTop 5 CPU consumers:"
    ps aux --sort=-%cpu | head -6 | tail -5
    
    echo -e "\nTop 5 Memory consumers:"
    ps aux --sort=-%mem | head -6 | tail -5
}

# Check for problematic processes
check_system_health() {
    echo "=== System Health Check ==="
    
    # Check high CPU usage processes
    local high_cpu_procs
    high_cpu_procs=$(ps aux | awk -v threshold="$ALERT_CPU_THRESHOLD" '$3 > threshold {print $2, $11, $3"%"}')
    
    if [[ -n "$high_cpu_procs" ]]; then
        echo "⚠️  High CPU usage processes:"
        echo "$high_cpu_procs"
        log_action "High CPU alert: $high_cpu_procs"
    fi
    
    # Check high memory usage processes
    local high_mem_procs
    high_mem_procs=$(ps aux | awk -v threshold="$ALERT_MEMORY_THRESHOLD" '$4 > threshold {print $2, $11, $4"%"}')
    
    if [[ -n "$high_mem_procs" ]]; then
        echo "⚠️  High memory usage processes:"
        echo "$high_mem_procs"
        log_action "High memory alert: $high_mem_procs"
    fi
}

# Kill runaway processes
kill_runaway_processes() {
    echo "=== Runaway Process Detection ==="
    
    # Find processes using excessive CPU (>90% for >5 minutes)
    local runaway_pids
    runaway_pids=$(ps aux | awk '$3 > 90 {print $2}')
    
    for pid in $runaway_pids; do
        local process_name
        process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
        
        if [[ -n "$process_name" ]]; then
            echo "Found runaway process: $process_name (PID: $pid)"
            
            # Skip critical system processes
            if [[ "$process_name" =~ ^(kernel|launchd|WindowServer)$ ]]; then
                echo "Skipping critical system process: $process_name"
                continue
            fi
            
            log_action "Terminating runaway process: $process_name (PID: $pid)"
            kill -TERM "$pid"
        fi
    done
}

# Main monitoring function
main() {
    log_action "=== MacFleet Process Monitoring Started ==="
    
    get_system_stats
    echo ""
    check_system_health
    echo ""
    
    # Optionally kill runaway processes (uncomment to enable)
    # kill_runaway_processes
    
    log_action "=== Process monitoring completed ==="
}

# Execute main function
main "$@"

Process Information Details

When using ps aux, each column provides specific information:

ColumnDescription
USERUser running the process (system or user process)
PIDProcess ID (unique identifier)
%CPUCPU usage percentage
%MEMMemory usage percentage
VSZVirtual memory size in KB
RSSPhysical memory usage in KB
TTTerminal associated with process
STATProcess status (R=running, S=sleeping, Z=zombie)
STARTEDProcess start date/time
TIMECPU time consumed
COMMANDCommand used to start the process

Common Process Management Tasks

Find Process by Name

# Find Safari processes
ps aux | grep -i safari

# Find all processes containing "mail"
ps aux | grep -i mail | grep -v grep

Monitor Process in Real-time

# Watch specific process
watch -n 1 'ps aux | grep -i safari'

# Monitor system resources continuously
top -s 1 -n 10

Generate Process Report

#!/bin/bash

# Create comprehensive process report
REPORT_FILE="process_report_$(date +%Y%m%d_%H%M%S).txt"

{
    echo "MacFleet Process Report"
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo "=========================="
    echo ""
    
    echo "System Overview:"
    top -l 1 -s 0 | grep -E "(CPU usage|PhysMem)"
    echo ""
    
    echo "Top 20 Processes:"
    ps aux | head -21
    echo ""
    
    echo "Process Count by User:"
    ps aux | awk '{print $1}' | sort | uniq -c | sort -nr
    
} > "$REPORT_FILE"

echo "Process report saved to: $REPORT_FILE"

Important Notes

  • Process IDs (PIDs) change when processes restart
  • System processes require admin privileges to terminate
  • Force kill (kill -9) should be used as last resort
  • Monitor resource usage before terminating processes
  • Test scripts on individual devices before fleet deployment