macOS pela visão de um usuário Linux
Last updated
Last updated
Depois de muitos anos, comprei um MacBook Air M1…
Posso estar generalizando, mas o sonho de todo nerdzinho de TI é ter um Mac (seja MacBook Pro, Air, iMac, Mac Mini, não importa). Quem já assistiu “Piratas do Vale do Silício”, algum filme ou documentário sobre a Apple, leu aquela biografia do Steve Jobs, e acompanha as notícias do mundo da tecnologia, sempre fica com a aquela vontade de ter um computador da Apple (mas o preço é sempre um empecilho).
Uso Linux como desktop já a alguns anos, então é inevitável que acabarei fazendo comparações entre ele e o macOS (ainda mais por ambos terem inspirações no UNIX).
Tópicos:
Como meu MacBook Air é de 2020, ele veio por padrão com a versão Monterey. Seguindo a recomendação do próprio sistema, atualizei para a versão mais nova, o Ventura. E cá entre nós: se tem uma coisa que a Apple faz bem é o processo de upgrade de sistemas operacionais dela (quem nunca ferrou uma distro Linux depois de um upgrade e teve que instalar tudo do zero depois?).
As 7 primeiras versões do macOS eram baseadas na arquitetura PowerPC. Sendo a 5ª, 6ª e 7ª versão também lançadas para a arquitetura Intel durante um período de transição de arquiteturas.
Da 8ª versão até a 16ª, o macOS foi lançado exclusivamente para a arquitetura Intel. Mas atualmente estamos presenciando uma nova transição de arquitetura onde as três versões mais recentes (Big Sur, Monterey, e Ventura) foram lançadas para a arquitetura Intel e também na nova arquitetura "Apple Silicon" (um SoC ARM de 64 bits fabricado pela própria Apple).
Aparentemente, não tem uma forma de acessar o setup do UEFI de um Mac como se faz com PCs (apertar Del ou F2 na inicialização não vai funcionar). O mais próximo disto (pelo menos no M1) é pressionar e segurar o botão de ligar fazendo o sistema carregar no modo de recuperação.
Durante o boot de várias distros Linux é comum vermos um splash screen ocultando as mensagens de carregamento do kernel e do sistema de init. Para desabilitar temporariamente basta pressionar a tecla F2.
No macOS não há uma tecla que mostre o carregamento do sistema (dizem que se pressionar ⌘+V em macOS Intel funciona, mas em Apple Silicon não). Mas com o sistema ligado, é possível ativar o "boot verboso" com:
Com isso, na próxima inicialização você poderá ver rapidamente as mensagens de boot.
A imagem do kernel se encontra no caminho /System/Library/Kernels/kernel
. E falando em kernel, se rodarmos o seguinte comando veremos coisas interessantes:
Observamos que ao invés de binários ELF (como no Linux e BSD), o formato usado é o Mach-O. E curiosamente, vimos na saída do comando file
acima que o binário /bin/ls
é compilado para as duas arquiteturas: x86_64 e ARM64. O conceito de "universal binary" proporcionado pelo Mach-O é um importante aliado da Apple no processo de transição para o Apple Silicon.
Falando em bibliotecas compartilhadas, no Linux e sistemas BSD estamos acostumados com bibliotecas no formato .so (como /lib/x86_64-linux-gnu/libc.so.6, por exemplo). No macOS a extensão é o .dylib (como /usr/lib/system/libsystem_info.dylib).
Para quem está acostumado com a hierarquia de diretórios no padrão FHS (man hier
) do Linux ou de sistemas BSD, é de se estranhar um pouco a estrutura do macOS:
Vimos que vários diretórios tradicionais estão presentes (bin, dev, etc, home, opt, sbin, tmp, usr, var). Mas, e esses diretórios com letras maiúsculas?
/Applications: diretórios .app de aplicações instaladas pelo usuário.
/Library: arquivos compartilhados por aplicações e componentes do sistema.
/System: arquivos críticos do sistema.
/Users: diretórios de usuários.
/Volumes: sistemas de arquivos montados.
Podemos fazer algumas equivalências com o Linux:
/
/
/bin
/bin
/sbin
/sbin
/etc
/etc
/var
/var
/dev
/dev
/tmp
/tmp
/usr
/usr
/Users
/home
/Volumes
/media
/Applications
/opt, /usr/bin/
/Library/Fonts/
/usr/share/fonts/
/System/Library/Kernels/kernel
/boot/vmlinuz
/System/Library/LaunchDaemons/
/lib/systemd/system/
O tipo de sistema de arquivos padrão nas versões recentes é o Apple File System (APFS), que de longe tem estrutura e funcionalidades parecidas com o ZFS e BTRFS, ou seja, trabalha com volumes lógicos, implementa mecanismos inteligentes para a garantia da integridade dos dados, tem suporte nativo de encriptação, snapshot, e etc.
No macOS temos o comando diskutil
. Ele une funcionalidades de comandos do Linux como fdisk, parted, mkfs, fsck, mount, e umount. Exemplos:
Vendo a saída do comando, percebemos que o macOS reconhece dispositivos de armazenamento no formato /dev/diskXsY
(uma nomenclatura mais no estilo de sistemas BSD). No caso da listagem acima, temos os dispositivos /dev/disk0
e /dev/disk3
.
Uma coisa interessante é que o diskutil além de lidar com partições GPT, montagem de dispositivos, correção de inconsistências, e etc, ele também gerencia o sistema de arquivos APFS.
O APFS chama partições do disco de "volumes" e volumes lógicos de uma partição de "containers". Podemos listar os "volumes" e seus "containers" com:
Mas além de simplesmente listar, o diskutil apfs
consegue fazer várias outras operações (como criar novos volumes, encriptar um volume, deletar volume, criar e deletar containers, criar e deletar snapshots, e etc).
Como todo sistema UNIX, após o processo de boot do kernel entra em cena o primeiro processo da userspace de PID 1: o sistema de init.
O sistema de init do macOS é o launchd e, assim como o systemd do Linux (que é inspirado nele), além de cuidar da inicialização dos serviços ele também cuida do gerenciamento deles. O launchd absorve uma série de daemons clássicos do UNIX, como os scripts de inicialização, crond, atd, inetd, watchdogd, e etc. Ele é tão centralizador que é responsável até pela execução das aplicações do usuário (Safari, Calculadora, Notas, etc, tudo passa pela "benção" do launchd).
Os serviços gerenciados por ele são chamados de "daemons" e "agentes", onde a diferença de um para o outro é que o agente roda após o login de um usuário, e o daemon roda (na maioria dos casos) como root desvinculado da sessão de um usuário. Os daemons e agentes são definidos em formato XML em arquivos com extensão .plist (property list).
Durante o processo de boot o launchd varre os dois seguintes diretórios:
/System/Library/LaunchDaemons
/Library/LaunchDaemons
Após o login de um usuário, o launchd carrega os arquivos .plist destes diretórios:
/System/Library/LaunchAgents
/Library/LaunchAgents
~/Library/LaunchAgents
Como exemplo de atuação de um agent, após a instalação do launcher da Epic Games foi criado em ~/Library/LaunchAgents o arquivo .plist responsável pelo carregamento automático do launcher após o login:
Após a inicialização do sistema, os daemons e os agentes podem ser gerenciados pelo comando launchctl (não muito diferente do systemctl):
Como exemplo da centralização de funcionalidades do launchd, executei pela GUI a Calculadora e através do launchctl listei sua execução e o encerrei:
Ao invés dos arquivos de log ficarem espalhados em /var/log
, o macOS possui um sistema de logs chamado "Unified Logs". Onde os diversos eventos do sistema e de aplicações são centralizadas em um serviço chamado "logd", e os logs são descarregados em arquivos binários em /var/db/diagnostics/
, podendo serem consultados pelo comando "log".
Isto não é muito diferente do journald do Linux, onde atualmente até mesmo os arquivos tradicionais como /var/log/messages
são obtidos pelo rsyslogd através de uma integração com o journald (via UNIX socket do journald). Todos os logs syslog do sistema e de aplicações são obtidos pelo journald via /dev/syslog
e mantido em arquivos binários em /var/log/journal/
, podendo ser consultados pelo comando journalctl.
Voltando para o macOS, para ver os logs em tempo real podemos checar com o log stream
:
Mas isso fará com que todos os logs produzidos no momento sejam cuspidos na tela de uma só vez (o que pode não ser legal). Então, se quiser filtrar pode usar um | grep
ou o parâmetro --predicate
:
No caso do print anterior, eu estava filtrando por eventos que me ajudasse a entender um problema de compartilhamento de tela VNC.
Outro comando útil é o log show
, que consulta os registros passados. Se executar um log show
sem nenhum parâmetro ele irá te mostrar todos os logs armazenados. Mas também é possível usar filtros como o --last
:
No comando anterior foi filtrado os logs do último segundo (--last 1s
). Mas poderia ser dos últimos 5 minutos (--last 5m
), 8 horas (--last 8h
), 3 dias (--last 3d
), por exemplo.
Ao contrário dos tradicionais arquivos /etc/passwd
, /etc/shadow
e /etc/group
, o macOS gerencia as configurações de cada usuário do sistema em arquivos .plist em /var/db/dslocal/nodes/Default/users/
.
Estes arquivos de usuários são gerenciados por um serviço local de diretórios chamado OpenDirectory (experimente rodar um ps aux | grep opendirectoryd
).
Estes arquivos de usuários podem ser lidos diretamente, como por exemplo:
Mas também podem ser consultados pelo cliente do OpenDirectory, o comando dscl
(Directory Service Command Line):
Falando em dscl
, como é por meio dele que gerenciamos a base de usuários do sistema, é através dele que podemos criar novos usuários, exemplo de criação de um usuário "outro_usuario":
Algumas maneiras de se instalar programas no macOS:
Simplesmente baixando, descompactando e executando uma aplicação.
Instalando pelo .pkg.
Baixando o .dmg, montando ele, e copiando o diretório .app de dentro do ponto de montagem.
Instalando pelo SoftwareUpdate.
Instalando pelo MacPorts.
Instalando pelo Homebrew.
Esse é método mais simples como o do caso abaixo:
Mas pode ficar um pouco complicado se for necessário copiar para diretórios globais do sistema e criar LaunchDaemon ou LaunchAgent.
Usamos o comando installer
para a instalação de pacotes no formato .pkg:
Esse é o formato mais comum para instalação de apps no macOS, como exemplo instalei a Steam com os seguintes procedimentos:
Com o comando softwareupdate
é possível instalar o Rosetta, atualizar aplicações, atualizar todo o sistema para uma versão mais nova, baixar imagens de instalação do macOS, e ativar atualizações automáticas.
Atualizações podem ser listadas antes da instalação com softwareupdate --list
.
O MacPorts tem uma pegada parecida com o ports do FreeBSD, ele permite o gerenciamento de pacotes através do comando port
. Os pacotes e dependências são obtidos do repositório packages.macports.org
e instalado no diretório /opt/local
.
Atualizando base de pacotes:
Exemplo de instalação do comando wget
:
O Homebrew permite o gerenciamento de pacotes através do comando brew
. Os pacotes e dependências são obtidos do repositório ghcr.io
(GitHub) e instalado no diretório /opt/homebrew
.
Uma das principais diferenças do MacPorts para o Homebrew está na forma como os pacotes são instalados: o Homebrew tenta reaproveitar dependências já instaladas no sistema (instalando menos pacotes), já o MacPorts tenta resolver todas as dependências com base no seu repositório.
Desde o lançamento dos primeiros computadores com M1 a Apple já tinha um ás na manga para contornar os problemas de compatibilidade com o novo Apple Silicon: o Rosetta 2 (o Rosetta 1 existiu durante a transição de PowerPC para Intel anos atrás).
Com o Rosetta é possível executar aplicações macOS originalmente desenvolvidas para Intel no Apple Silicon. Essa mágica acontece através de uma tradução de todos os binários envolvidos na execução de uma aplicação Intel para a arquitetura ARM64, descarregando os objetos traduzidos em subdiretórios de /var/db/oah/
, uma estratégia chamada de tradução Ahead-of-Time (AOT) (antes do tempo de execução).
Meu contato com o Rosetta aconteceu através do Fortnite! Ao instalar o launcher da Epic Games foi necessário a instalação do Rosetta, pois tanto o launcher quanto o Fortnite não são aplicações nativas para Apple Silicon.
Como esperado, a primeira execução do Fortnite demorou um pouco (pois os binários Intel primeiro foram traduzidos para ARM e depois executados). Na segunda execução tudo fluiu bem mais rápido (já que os binários traduzidos já estavam em cache em /var/db/oah
).
Inspecionando o binário original do Fortnite, vemos que ele é uma aplicação compilada para x86_64:
Procurando no cache do Rosetta, encontramos o binário convertido para ARM64:
Falando em Aqua, os três elementos do ambiente gráfico que mais chama a atenção é o Dock, Launchpad, e o Finder.
Outro comportamento da GUI do macOS que me chamou atenção é o conceito de apenas "fechar a janela de uma aplicação" mas mantendo-a em execução. Ou seja, o fato de você clicar em "fechar" não quer dizer que a aplicação será encerrada! Você tem que dar um ⌘+Q ou clicar na opção de fechar lá no alto para efetivar a encerramento da aplicação.
Fiquei impressionado com as várias similaridades da interface do Ubuntu (com GNOME Shell e extensões) e a interface do macOS. Equivalente a Dock do macOS, temos o Ubuntu Dock. Ao invés do Launchpad, temos o Dash. E no lugar do Finder temos o Nautilus. Fora que a barra de opções das janelas também ficam integradas com a barra fixa no canto superior da tela.
Sempre me incomodou meu completo desconhecimento sobre macOS. Acabei aprendendo muito durante a escrita desse artigo, onde usei o Linux como base para questionar o funcionamento desse sistema.
Sei que vários tópicos abordados aqui mereciam ser explorados com mais profundidade (poderia ter falado também de configurações de rede, soluções de segurança, etc), mas o que seria um artigo descompromissado acabaria se tornando um ebook.
Estou tendo meus primeiros contatos com o macOS, inclusive ainda apanho com os atalhos do teclado. Ainda não desenvolvi memória muscular suficiente para interagir com todas as funcionalidades gráficas desse sistema.
Agora tendo um contato prático com um MacBook Air, fico impressionado em como a Apple desde o Lisa não mede esforços para usar o que for de mais recente ou avançado do mundo da tecnologia (EFI, Secure Boot, TPM, Secure Enclave, ARM, Neural Engine, Touch ID, Retina, e... UNIX).
Fico feliz se você aprendeu alguma coisa nova por esse material (deu muito trabalho para escrevê-lo). Se fiz alguma afirmação incorreta aqui peço que me corrija, por favor.
^D
O é a 19ª versão do sistema operacional que já foi chamado de Mac OS X, OS X, e agora de macOS (para ficar no mesmo estilo padronizado de iOS, iPadOS, e tvOS).
Comprei esse MacBook Air M1 primeiramente por causa do preço, mas outro fator foi o chip M1. Eu realmente estava interessado em usar como desktop uma máquina com um SoC ARM. Tanto que meu plano inicial era comprar um com SoC ARM Mediatek MT8183 (mas tive que cancelar o pedido porque ia demorar muito tempo pra chegar).
Ao invés do GRUB2, o boot é iniciado pelo iBoot, localizado em /System/Library/CoreServices/boot.efi
. Os tem e são . Por exemplo, antes do iBoot entrar em cena uma ROM de inicialização faz os procedimentos iniciais, chama o Low-Level Bootloader (LLB), e por fim o iBoot é chamado.
É aqui que vemos a ligação do macOS com o universo UNIX. Sim, o macOS dispõe da mesma interface sysctl dos sistemas BSD. XNU é o kernel usado por um sistema básico chamado Darwin. E o Darwin é o sistema que estrutura toda a base do macOS (shells, comandos essenciais, bibliotecas compartilhadas, estrutura de diretórios, e etc). Por isso que é muito comum você encontrar a referência a "darwin" no .
Tanto o XNU, quanto os componentes do Darwin sob a licença Apple Public Source License (APSL). E uma curiosidade é que subsistemas do XNU e componentes da userspace do Darwin são derivados do FreeBSD.
Essa estrutura do Darwin e do kernel XNU foi herdada do , que era comercializado por uma antiga empresa do Steve Jobs chamada NeXT, antes do retorno dele para a Apple.
O kernel XNU é a fusão de dois projetos: o e . Podemos encontrar evidências do kernel Mach observando o layout de binários executáveis e bibliotecas compartilhadas no macOS:
Como hoje em dia o UNIX é um padrão, o macOS é oficialmente um UNIX, pois é certificado Single UNIX Specification:
E faz alguma diferença ser certificado Unix? Resposta: .
O ideal era que fosse possível (de forma oficial) instalar programas da App Store pela linha de comando. Até existem projetos como , mas não é um recurso oficial da Apple. Então, na ausência de um apt, yum, dnf, pacman, pkg, ou um zipper, duas soluções muito usadas no macOS é o MacPorts e o Homebrew.
Observação: , ele poderá ser chamado pelo caminho absoluto, ou o PATH
deverá ser alterado no ~/.bashrc
ou ~/.zshrc
do seu usuário:
Como outras alternativas de gerenciadores de pacotes, temos também o e o .
O diretório /var/db/oah
, por padrão, é protegido pelo System Integrity Protection. Para fazer o teste acima tive que desabilitá-lo temporariamente seguindo .
No macOS você não verá um Xorg ou Wayland, você encontrará o , e não adianta rodar um ps aux | grep -i quartz
pra tentar encontrar o processo dele pois ele roda parte embutido no kernel, parte pelo processo WindowServer
.
Como gerenciador de janela, você não verá um Mutter, Compiz, Xfwm, ou KWin, mas sim o (outro componente do Quartz) implementado também no processo WindowServer
. E como login manager não verá um lightdm ou gdm, mas sim o loginwindow
. E também não verá um GNOME, XFCE, ou KDE, mas sim o Aqua.