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.

Fetch Device Logs on macOS

macOS provides a powerful unified logging system that captures detailed information about system processes, applications, and user activities. This tutorial shows how to effectively collect and analyze device logs across your MacFleet for troubleshooting, security monitoring, and performance analysis.

Understanding macOS Logging

macOS uses the unified logging system introduced in macOS 10.12, which consolidates various log sources:

  • System logs - Kernel, system services, and daemons
  • Application logs - User applications and background processes
  • Security logs - Authentication, authorization, and security events
  • Network logs - Network activity and connectivity

Basic Log Commands

View Recent System Logs

#!/bin/bash

# Show logs from the last minute
sudo log show --last 1m

# Show logs from the last hour
sudo log show --last 1h

# Show logs from the last day
sudo log show --last 1d

Live Log Streaming

#!/bin/bash

# Stream live logs
sudo log stream

# Stream with timestamp
sudo log stream --info --debug

Application-Specific Logs

Get Logs for Specific Application

#!/bin/bash

# Basic app log query
log show --predicate 'processImagePath CONTAINS[c] "safari"'

# Query with time range
log show --predicate 'processImagePath CONTAINS[c] "Finder"' --last 30m

# Save app logs to file
log show --predicate 'processImagePath CONTAINS[c] "Mail"' --last 1h > ~/Desktop/mail_logs.txt

Enterprise Log Collection Script

#!/bin/bash

# Device Log Collection Script for MacFleet
# Compatible with macOS 10.14+

# Configuration
LOG_DIR="/var/log/macfleet_logs"
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
HOSTNAME=$(hostname -s)
OUTPUT_DIR="$LOG_DIR/${HOSTNAME}_${TIMESTAMP}"
ARCHIVE_NAME="${HOSTNAME}_logs_${TIMESTAMP}.tar.gz"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_DIR/collection.log"
}

# Function to create output directory
setup_directories() {
    if mkdir -p "$OUTPUT_DIR"; then
        log_message "✓ Created output directory: $OUTPUT_DIR"
        return 0
    else
        log_message "✗ Failed to create output directory"
        return 1
    fi
}

# Function to collect system logs
collect_system_logs() {
    log_message "Collecting system logs..."
    
    # Recent system logs (last 24 hours)
    if log show --last 24h > "$OUTPUT_DIR/system_logs_24h.log"; then
        log_message "✓ System logs collected (24h)"
    else
        log_message "✗ Failed to collect system logs"
    fi
    
    # Critical and error logs only
    if log show --last 24h --predicate 'messageType == 16 OR messageType == 17' > "$OUTPUT_DIR/critical_errors.log"; then
        log_message "✓ Critical/Error logs collected"
    else
        log_message "✗ Failed to collect critical logs"
    fi
    
    # Boot logs
    if log show --predicate 'process == "kernel"' --last 7d > "$OUTPUT_DIR/kernel_logs.log"; then
        log_message "✓ Kernel logs collected"
    else
        log_message "✗ Failed to collect kernel logs"
    fi
}

# Function to collect application logs
collect_app_logs() {
    log_message "Collecting application logs..."
    
    # Common applications to monitor
    local apps=("Safari" "Finder" "Mail" "Calendar" "Contacts" "Notes" "Spotlight" "WindowServer")
    
    for app in "${apps[@]}"; do
        local output_file="$OUTPUT_DIR/${app,,}_logs.log"
        if log show --predicate "processImagePath CONTAINS[c] \"$app\"" --last 24h > "$output_file" 2>/dev/null; then
            # Only keep file if it has content
            if [[ -s "$output_file" ]]; then
                log_message "✓ $app logs collected"
            else
                rm -f "$output_file"
                log_message "! No logs found for $app"
            fi
        else
            log_message "✗ Failed to collect $app logs"
        fi
    done
}

# Function to collect security logs
collect_security_logs() {
    log_message "Collecting security logs..."
    
    # Authentication logs
    if log show --predicate 'category == "authorization" OR process == "authd"' --last 7d > "$OUTPUT_DIR/auth_logs.log"; then
        log_message "✓ Authentication logs collected"
    else
        log_message "✗ Failed to collect auth logs"
    fi
    
    # Login/logout events
    if log show --predicate 'eventMessage CONTAINS "login" OR eventMessage CONTAINS "logout"' --last 7d > "$OUTPUT_DIR/login_events.log"; then
        log_message "✓ Login events collected"
    else
        log_message "✗ Failed to collect login events"
    fi
}

# Function to collect system information
collect_system_info() {
    log_message "Collecting system information..."
    
    {
        echo "=== System Information ==="
        echo "Hostname: $(hostname)"
        echo "macOS Version: $(sw_vers -productVersion)"
        echo "Build: $(sw_vers -buildVersion)"
        echo "Uptime: $(uptime)"
        echo "Date: $(date)"
        echo ""
        
        echo "=== Hardware Information ==="
        system_profiler SPHardwareDataType
        echo ""
        
        echo "=== Disk Usage ==="
        df -h
        echo ""
        
        echo "=== Memory Usage ==="
        vm_stat
        echo ""
        
        echo "=== Running Processes ==="
        ps aux | head -20
        
    } > "$OUTPUT_DIR/system_info.txt"
    
    log_message "✓ System information collected"
}

# Function to create archive
create_archive() {
    log_message "Creating archive..."
    
    cd "$LOG_DIR" || return 1
    
    if tar -czf "$ARCHIVE_NAME" "$(basename "$OUTPUT_DIR")"; then
        log_message "✓ Archive created: $LOG_DIR/$ARCHIVE_NAME"
        
        # Clean up temporary directory
        rm -rf "$OUTPUT_DIR"
        log_message "✓ Temporary files cleaned up"
        
        # Show archive size
        local size
        size=$(du -h "$LOG_DIR/$ARCHIVE_NAME" | cut -f1)
        log_message "Archive size: $size"
        
        return 0
    else
        log_message "✗ Failed to create archive"
        return 1
    fi
}

# Function to upload archive (placeholder for enterprise integration)
upload_archive() {
    local archive_path="$LOG_DIR/$ARCHIVE_NAME"
    
    # Example: Upload to central logging server
    # Replace with your actual upload mechanism
    log_message "Archive ready for collection: $archive_path"
    
    # Placeholder for upload logic
    # scp "$archive_path" user@logserver:/logs/
    # curl -F "file=@$archive_path" https://logserver.company.com/upload
    
    return 0
}

# Main execution function
main() {
    log_message "=== Starting MacFleet log collection ==="
    
    # Setup
    if ! setup_directories; then
        exit 1
    fi
    
    # Collect logs
    collect_system_logs
    collect_app_logs
    collect_security_logs
    collect_system_info
    
    # Create archive
    if create_archive; then
        upload_archive
        log_message "=== Log collection completed successfully ==="
        exit 0
    else
        log_message "=== Log collection failed ==="
        exit 1
    fi
}

# Execute main function
main "$@"

Quick Log Collection Scripts

Collect Logs for Specific Time Period

#!/bin/bash

# Collect logs between specific dates
START_DATE="2025-01-01"
END_DATE="2025-01-02"
OUTPUT_FILE="~/Desktop/logs_${START_DATE}_to_${END_DATE}.txt"

log show --start "$START_DATE" --end "$END_DATE" > "$OUTPUT_FILE"
echo "Logs saved to: $OUTPUT_FILE"

Collect Application Crash Logs

#!/bin/bash

# Collect crash reports
CRASH_DIR="~/Library/Logs/DiagnosticReports"
OUTPUT_DIR="~/Desktop/crash_logs"

mkdir -p "$OUTPUT_DIR"
find "$CRASH_DIR" -name "*.crash" -mtime -7 -exec cp {} "$OUTPUT_DIR/" \;

echo "Recent crash logs copied to: $OUTPUT_DIR"

Monitor Specific Events

#!/bin/bash

# Monitor USB device connections
log stream --predicate 'eventMessage CONTAINS "USB"' --info

# Monitor network changes
log stream --predicate 'subsystem == "com.apple.network"' --info

# Monitor file system events
log stream --predicate 'subsystem == "com.apple.filesystem"' --debug

Log Analysis Scripts

Parse Authentication Events

#!/bin/bash

# Extract failed login attempts
log show --predicate 'eventMessage CONTAINS "authentication failure"' --last 7d \
    | grep -E "(authentication failure|failed)" \
    | sort | uniq -c | sort -nr > ~/Desktop/failed_logins.txt

echo "Failed login analysis saved to ~/Desktop/failed_logins.txt"

Application Usage Statistics

#!/bin/bash

# Analyze application launches
log show --predicate 'process == "launchd" AND eventMessage CONTAINS "spawn"' --last 24h \
    | grep -oE '"[^"]*\.app"' \
    | sort | uniq -c | sort -nr > ~/Desktop/app_usage.txt

echo "Application usage statistics saved to ~/Desktop/app_usage.txt"

Log Archive Management

Create System Log Archive

#!/bin/bash

# Create complete system log archive
ARCHIVE_PATH="~/Desktop/SystemLogs_$(date +%Y%m%d_%H%M%S).logarchive"

log collect --output "$ARCHIVE_PATH" --last 24h

echo "System log archive created: $ARCHIVE_PATH"

View Archived Logs

#!/bin/bash

# View logs from archive
ARCHIVE_PATH="~/Desktop/SystemLogs.logarchive"

if [[ -f "$ARCHIVE_PATH" ]]; then
    log show --archive "$ARCHIVE_PATH" --last 1h
else
    echo "Archive not found: $ARCHIVE_PATH"
fi

Troubleshooting Common Issues

IssueSolution
Permission deniedRun with sudo for system logs
No logs foundCheck date range and predicates
Large log filesUse time filters and specific predicates
Script timeoutsReduce time range or use async collection
Archive corruptionVerify disk space and permissions

Log Filtering Examples

Filter by Log Level

# Error messages only
log show --predicate 'messageType == 16' --last 1h

# Info and debug messages
log show --predicate 'messageType >= 1' --last 30m

# Critical errors only
log show --predicate 'messageType == 17' --last 24h

Filter by Process

# System processes
log show --predicate 'process == "kernel" OR process == "launchd"' --last 1h

# User processes
log show --predicate 'processImagePath BEGINSWITH "/Applications"' --last 1h

# Background daemons
log show --predicate 'processImagePath CONTAINS "daemon"' --last 1h

Security Considerations

  • Privacy - Be mindful of user data in logs
  • Retention - Implement log rotation and cleanup
  • Access Control - Restrict log access to authorized personnel
  • Encryption - Encrypt log archives before transmission
  • Compliance - Follow data retention policies

Performance Tips

  • Use specific time ranges to limit data volume
  • Filter by process or category to reduce noise
  • Stream logs in real-time for immediate analysis
  • Compress archives to save storage space
  • Schedule regular log collection during off-hours

Important Notes

  • System logs may contain sensitive information
  • Large time ranges can generate massive log files
  • Some logs require admin privileges to access
  • Log collection can impact system performance
  • Test scripts on individual devices before fleet deployment

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.