Spring til indhold

macOS

Apples styresystem til computere

Hvad det er

macOS er det styresystem, Apple leverer på hver Mac: skrivebordet og Finder, de medfølgende apps og under dem et Unix-system med terminal, shell og de velkendte kommandolinjeværktøjer. Apple bygger det til sin egen hardware og sælger de to sammen, så i praksis er et valg af macOS et valg af en Mac.

Fundamentet hedder Darwin, og Apple offentliggør kildekoden til det. Systemkernen, XNU, er en hybrid, der forener Mach-kernen fra Carnegie Mellon University med komponenter fra FreeBSD og en driverramme i C++ ved navn IOKit; navnet står for »X is Not Unix«. Meget af brugerlandet kommer også fra FreeBSD, og manualsiderne for sed og date på en Mac beskriver FreeBSD’s udgaver af de to værktøjer. Siden macOS 10.15 Catalina har standardshellen været zsh.

Hardwaren under systemet er skiftet for nylig. I slutningen af 2020 begyndte Apple at flytte Mac’en fra Intel-processorer til sine egne chips, Apple silicon, og hver Mac-serie fra MacBook Air til Mac Pro findes nu med Apple silicon. De chips er arm64, og det får betydning, så snart software bygget på en Mac skal køre på en x86-64-server.

På bærbare og stationære computere holdes macOS op imod Windows og Linux.

Hvorfor det betyder noget

For en virksomhed, der skriver software, spiller macOS to roller, som er lette at blande sammen: det er den maskine, mange udviklere arbejder på, og det er en platform, kunderne kører software på.

Som arbejdsstation adskiller en Mac sig fra de Linux-servere, koden udrulles til, tre steder. Kommandolinjeværktøjerne stammer fra FreeBSD og ikke fra GNU, så samme flag kan betyde to forskellige ting i et script. Processoren er arm64, hvor serveren måske er x86-64. Og der er ingen Linux-kerne på en Mac, mens containere deler værtens kerne, så containerværktøjer på en Mac starter først en virtuel Linux-maskine; Apples eget værktøj container, som kræver Apple silicon og macOS 26, giver hver container sin egen lette virtuelle maskine. Intet af det udelukker en Mac. Det betyder, at man tester på det system, man udruller til, frem for at stole på en grøn kørsel på en bærbar.

Som platform rejser macOS spørgsmålet om, hvordan man bygger til den. En skal på tværs af platforme, én kodebase med en indlejret browsermotor, der leveres til Windows, Linux og Mac, holder flere systemer i takt for få penge, men på Mac’en slæber den en browserkøretid med, som et native program ikke har brug for, og tegner sine egne kontroller i stedet for systemets. Et native program i Swift og SwiftUI bruger systemets kontroller og materialer og følger brugerens indstillinger for udseende, accentfarve, kontrast, tekststørrelse og reduceret bevægelse uden ekstra kode. Prisen er en separat klient og folk, der kender platformen. Native betaler sig, når Mac-brugerne er kunderne.

Levering til Mac går også gennem en kontrol. Software, der distribueres uden for Mac App Store, signeres med et Developer ID-certifikat og sendes til Apples notariseringstjeneste, en automatisk scanning for skadeligt indhold og fejl i kodesigneringen, som er noget andet end App Review. Siden macOS 10.15 skal al software, der er bygget efter 1. juni 2019 og distribueres med Developer ID, være notariseret. Apple sender en billet tilbage, som hæftes på softwaren, og offentliggør den samme billet online, hvor Gatekeeper slår den op, første gang brugeren åbner appen. Certifikatet følger med Apple Developer Program, der koster 99 dollar om året. Planlæg medlemskabet og signeringen ind i den første udgivelse.

Sådan ser det ud i praksis

Skrivebordsoplevelsen af et beskedprodukt på macOS var en skal på tværs af platforme, der hverken lignede eller opførte sig som et Mac-program. Produktets velafprøvede Rust-kerne har en C-grænseflade, og Swift kan kalde C, så en native klient i Swift og SwiftUI blev bygget direkte på den grænseflade. Rust-kernen er linket ind som et statisk arkiv fra en fastlåst opstrømsrevision, hvilket gør bygningen gentagelig, og en tynd indpakning ejer hver pointer, der krydser mellem sprogene. Klienten starter som et Mac-program, bruger platformens egne materialer og kontroller og har ingen indlejret browser. Siden er ærlig om afstanden: der er ingen notariseret distribution og ingen opdateringskanal, så det er et fungerende program og ikke et produkt, som andre kører. Notariseringen ovenfor er netop det, der står mellem de to.

Platformens udseende kan håndhæves i stedet for at efterlignes. Et designsystem på 48 navngivne tokens i seks grupper bygger farve og materiale på platformens semantiske farver og dens glasmateriale frem for faste værdier, så grænsefladen følger systemets udseende, accentfarven og kontrastindstillingerne, uden at nogen kode holder øje med dem, og tekststilene skalerer med brugerens foretrukne størrelse. En linter afviser et råt tal, hvor et token hører hjemme, en hårdkodet skriftstørrelse og en animation, der ignorerer præferencen for reduceret bevægelse. Siden nævner også sin grænse: tokens gør en grænseflade ensartet, og det er noget andet end at gøre den god.

Hvordan macOS håndterer hukommelse, viste sig i arbejde på en macOS-applikation, hvor et program voksede med omkring 41 MB i sekundet, indtil styresystemet slog det ihjel. Maskinen havde 36 GB, og alligevel kom programmet op på 111 GB i komprimerede sider: komprimeringen og swap lod det vokse langt forbi den fysiske hukommelse, og da drabet kom, var resten af skrivebordet holdt op med at svare. Tre årsager gangede hinanden op: en ubegrænset hændelsesstrøm, abonnenter, der hver fik hver eneste hændelse, og logning uden budget. Afgrænsede buffere, abonnement efter hændelsestype og et hastighedsbudget på logningen rettede alle tre, og en regressionstest holder hukommelsesloftet. Den session, der skrev 610.996 loglinjer, skriver nu 1.411, og siden siger prisen ligeud: når noget går hurtigt galt, er loggen bevidst ufuldstændig.

Hvor det går galt

Aktivitetsovervågning viser næsten ingen ledig hukommelse på en Mac, der kører helt fint. macOS bruger ellers ubrugt hukommelse som cache for nyligt brugte filer og komprimerer, efterhånden som hukommelsen fyldes, inaktive apps for at give plads til aktive. Brugt hukommelse tæt på den fysiske og et stort tal for komprimeret hukommelse er derfor normalt. Apple skriver selv, at ledig hukommelse ikke nødvendigvis forbedrer computerens ydeevne. Læs i stedet grafen Belastning af hukommelse: grøn betyder, at computeren bruger al RAM effektivt, gul, at den kan få brug for mere på et tidspunkt, og rød, at den har brug for mere. Swap er det tydeligste tegn:

sysctl vm.swapusage
vm_stat | grep -E '^Swap(ins|outs)'

Tællerne i vm_stat løber fra opstart, så sammenlign to aflæsninger med et minuts mellemrum; swapouts, der bliver ved med at stige, betyder, at arbejdet er vokset fra RAM’en.

Et script, der virker på Mac’en, stopper med en mærkelig fejl på Linux-serveren, eller omvendt. Den FreeBSD-afledte sed på en Mac læser ordet efter -i som et suffiks til sikkerhedskopien, så GNU-vanen sed -i 's/a/b/' fil tager udtrykket som suffiks og filnavnet som script. Mac-vanen sed -i '' … får GNU sed til at læse udtrykket som et filnavn. Et suffiks skrevet sammen med flaget virker begge steder:

sed -i.bak 's/^port=80$/port=8080/' app.conf && rm app.conf.bak

Den varige løsning er at køre scripts i CI på det system, de møder i produktion.

En app, der deles uden for holdet, bliver blokeret af Gatekeeper, når modtageren åbner den. Appen er signeret til udvikling, eller den er signeret, men aldrig notariseret. Signér den med et Developer ID-certifikat med hardened runtime slået til og et sikkert tidsstempel, send den til notariseringstjenesten, og hæft billetten på, så Gatekeeper finder den, også uden netforbindelse. Et ZIP-arkiv kan notariseres, men kan ikke bære en billet, så hæft den på appen indeni:

ditto -c -k --keepParent App.app App.zip
xcrun notarytool submit App.zip --keychain-profile notary --wait
xcrun stapler staple App.app

Et containerimage kører på udviklerens Mac og dør på serveren med exec format error. Docker bygger som standard til platformen for den BuildKit-dæmon, der udfører bygningen, og på en Mac med Apple silicon kører den dæmon i en virtuel arm64-maskine. En container deler værtens kerne, så uden emulering kører en x86-64-vært kun x86-64-kode. Tjek serveren med uname -m, og byg derefter til den med docker build --platform linux/amd64, eller byg i CI på serverens processorarkitektur.

Læs mere

Ordliste