Главное: .app - это не файл, а папка
Самое важное прозрение для пришедших с Windows: приложение macOS - это бандл. То, что в Finder выглядит как один значок Safari или iTerm, на уровне файловой системы - обычная директория с расширением .app, внутри которой лежит исполняемый код, ресурсы, иконки и манифест. Finder просто прячет ее содержимое и показывает иконкой.
Заглянем внутрь. В Finder это пункт контекстного меню "Показать содержимое пакета", а в терминале - просто заходишь как в каталог.
Код: Выделить всё
$ ls -la /Applications/Safari.app/Contents
total 24
drwxr-xr-x ... CodeResources
-rw-r--r-- ... Info.plist
drwxr-xr-x ... MacOS
drwxr-xr-x ... Resources
drwxr-xr-x ... _CodeSignature
-rw-r--r-- ... PkgInfo
drwxr-xr-x ... Frameworks
Прочитать паспорт без выкапывания XML руками:
Код: Выделить всё
$ defaults read /Applications/Safari.app/Contents/Info CFBundleIdentifier
com.apple.Safari
$ mdls -name kMDItemVersion /Applications/Safari.app
kMDItemVersion = "26.0"

.dmg - монтируемый образ, а не установщик
Скачал приложение - часто получаешь файл .dmg. Это дисковый образ, виртуальный диск. dmg mac не устанавливает ничего сам по себе - его надо примонтировать, и тогда в системе появляется новый том, как будто ты воткнул флешку. Внутри обычно лежит тот самый бандл .app и стрелка-ссылка на /Applications с подписью "перетащи сюда".
Двойной клик в Finder монтирует образ и открывает окно. Дальше твоя задача - перетащить .app в папку Программы. Перетаскивание копирует бандл на системный диск; пока приложение лежит внутри смонтированного образа, оно работает "с флешки" и отвалится, как только ты образ извлечешь. Это классическая ошибка новичка: запустил прямо из окна dmg, а потом удивляется, почему после перезагрузки программы нет.
В терминале весь цикл виден насквозь. Монтируем (attach), смотрим содержимое, копируем, отмонтируем (detach):
Код: Выделить всё
$ hdiutil attach ~/Downloads/iTerm2.dmg
/dev/disk4 GUID_partition_scheme
/dev/disk4s1 Apple_HFS /Volumes/iTerm2
$ cp -R "/Volumes/iTerm2/iTerm.app" /Applications/
$ hdiutil detach /Volumes/iTerm2
"disk4" ejected.
.pkg - настоящий установщик с логикойГрабли: после установки .dmg остается у тебя в Загрузках и продолжает занимать место. Сам образ - это просто архив-контейнер, программе он больше не нужен, удаляй спокойно.
Когда программе мало просто скопировать бандл - надо положить файлы в системные каталоги, поставить демон launchd, прописать драйвер, выполнить скрипт - используют pkg установщик mac. Это уже инсталлятор в привычном смысле: мастер с шагами, лицензией и запросом пароля админа. Расширение .pkg.
Двойной клик открывает графический Installer. Но в терминале мощнее и прозрачнее - команда installer:
Код: Выделить всё
$ sudo installer -pkg ~/Downloads/google-chrome.pkg -target /
installer: Package name is Google Chrome
installer: Installing at base path /
installer: The install was successful.
Бывает два вида пакетов, и это важно для разбора. Component package - простой пакет с одним набором файлов, внутри лежит PackageInfo. Distribution package - обертка, которая может содержать несколько компонентов, показывать выбор опций, проверять версию macOS; внутри лежит файл Distribution. Внешне расширение одно и то же - .pkg.
Не доверяешь пакету - вскрой его перед установкой, не запуская. Для этого pkgutil:
Код: Выделить всё
$ pkgutil --expand ~/Downloads/google-chrome.pkg /tmp/chrome_pkg
$ ls /tmp/chrome_pkg
Distribution
GoogleChrome.pkg
Resources
$ ls /tmp/chrome_pkg/GoogleChrome.pkg
Bom PackageInfo Payload Scripts
Именно в Scripts прячется postinstall-скрипт, который выполнится с правами root после распаковки. Это и удобство (можно настроить демон), и вектор атаки. Вскрыть и прочитать postinstall перед установкой подозрительного пакета - нормальная гигиена админа.
Что уже стоит в системе и какие файлы принес конкретный пакет:
Код: Выделить всё
$ pkgutil --pkgs | grep -i chrome
com.google.Chrome
$ pkgutil --pkg-info com.google.Chrome
package-id: com.google.Chrome
version: 138.0.7204.0
install-time: 1749900000
$ pkgutil --files com.google.Chrome | head -3
Applications
Applications/Google Chrome.app
Applications/Google Chrome.app/Contents
Gatekeeper и карантин: почему mac не дает открыть программу
Теперь главный страж. Gatekeeper - подсистема, которая при первом запуске скачанного софта проверяет три вещи: подписан ли он валидным сертификатом Apple Developer, прошел ли нотаризацию (notarization - автопроверку Apple на известный вредонос) и не подменили ли бандл после подписи. Если все ок - запуск молча проходит. Если нет - ты получаешь то самое окно про неустановленного разработчика, и установить программу mac штатным двойным кликом не выходит.
Спусковой крючок - расширенный атрибут com.apple.quarantine. Когда браузер или мессенджер скачивает файл, он вешает на него этот xattr. Gatekeeper проверяет именно помеченные карантином файлы, а не все подряд - вот почему софт, собранный локально или скопированный с другого Mac по сети, часто запускается без вопросов.
Посмотреть карантин:
Код: Выделить всё
$ xattr -p com.apple.quarantine ~/Downloads/SomeApp.app
0083;6650a1b2;Safari;F1E2D3C4-...
$ xattr -l ~/Downloads/SomeApp.app
com.apple.quarantine: 0083;6650a1b2;Safari;F1E2D3C4-...
Проверить вердикт Gatekeeper заранее, не запуская:
Код: Выделить всё
$ spctl -a -vvv /Applications/iTerm.app
/Applications/iTerm.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: ...
$ spctl -a -vvv ~/Downloads/SomeApp.app
~/Downloads/SomeApp.app: rejected
source=no usable signature
Как все-таки открыть и три уровня доверия
Три категории софта по доверию. App Store - максимум доверия, проходит ревью Apple, запускается без единого вопроса. Notarized (Developer ID + нотаризация) - подписан реальным разработчиком и проверен Apple автоматически; ставится с обычным двойным кликом, Gatekeeper доволен. Unsigned/неподписанный - самопал, opensource без сертификата, что-то с торрента; вот его Gatekeeper и блокирует.
Раньше обходом был трюк "правый клик по приложению -> Открыть" в контекстном меню Finder. Важно для 2026: в macOS Sequoia Apple убрала этот Control-click обход. Теперь штатный путь такой - попробовать открыть приложение, получить отказ, затем зайти в Системные настройки -> Конфиденциальность и безопасность, пролистать вниз до сообщения о заблокированном приложении и нажать Открыть в любом случае, подтвердив паролем админа или Touch ID. Так Apple оставила лазейку для своего софта, но сделала ее осознанной, в один клик ее не пройдешь случайно.
Терминальный путь для опытных - снять карантин руками, и тогда Gatekeeper к файлу не придерется:
Код: Выделить всё
$ sudo xattr -r -d com.apple.quarantine /Applications/SomeApp.app
Где живут приложения и их данные
Чтобы чисто ставить и удалять, надо знать топологию. Приложения для всех пользователей лежат в /Applications. Приложения только для тебя - в ~/Applications (если папка есть). Системные программы Apple - в /System/Applications, и трогать их нельзя, том System защищен и смонтирован только для чтения.
Данные и настройки приложения разбросаны по библиотекам, и при удалении бандла они остаются:
- ~/Library/Preferences - файлы настроек .plist, обычно по bundle ID (com.google.Chrome.plist)
- ~/Library/Application Support - основные пользовательские данные приложения, профили, базы
- ~/Library/Caches - кэши, их можно сносить смело
- ~/Library/Containers - песочница для App Store и sandboxed-приложений, у каждого свой контейнер по bundle ID
- /Library/LaunchDaemons и /Library/LaunchAgents - сюда .pkg часто кладет фоновые службы launchd
Код: Выделить всё
$ find ~/Library -iname "*chrome*" -maxdepth 3 2>/dev/null
/Users/you/Library/Application Support/Google/Chrome
/Users/you/Library/Caches/Google/Chrome
/Users/you/Library/Preferences/com.google.Chrome.plist
Типичные грабли
- Запуск .app прямо из окна .dmg. Программа работает "с образа", после извлечения исчезает. Всегда сначала копируй в /Applications.
- Установка .pkg "куда-то не туда". -target / это том, а не каталог; реальные пути зашиты в пакете, их видно через pkgutil --files еще до установки.
- Паника от "неустановленного разработчика". Это не вирус по умолчанию, а отсутствие нотаризации. Проверь источник, прогони spctl -a -vvv, реши осознанно.
- Снятие карантина с чего попало через xattr -d. Ты вручную выключаешь защиту - делай только для доверенного.
- Ожидание, что правый клик -> Открыть спасет. В Sequoia и Tahoe этого обхода нет, иди в Конфиденциальность и безопасность.
- Удаление перетаскиванием "под ноль". Хвосты в ~/Library остаются; для .pkg остаются и receipts, и файлы в системных каталогах.
Возьми любое бесплатное нотаризованное приложение в .dmg (например iTerm2 или VLC) и пройди весь путь руками:
- Скачай .dmg в ~/Downloads и примонтируй: hdiutil attach ~/Downloads/имя.dmg - запиши точку монтирования из вывода.
- Загляни внутрь бандла: ls /Volumes/имя/ПриложениеApp/Contents и прочитай его bundle ID через defaults read .../Contents/Info CFBundleIdentifier.
- Скопируй бандл в /Applications через cp -R, затем отмонтируй: hdiutil detach /Volumes/имя.
- Проверь карантин и вердикт: xattr -l /Applications/ПриложениеApp и spctl -a -vvv /Applications/ПриложениеApp - сравни, что показал каждый.
- Запусти двойным кликом. Если выскочило предупреждение - сходи в Системные настройки -> Конфиденциальность и безопасность и открой через "Открыть в любом случае".
- Бонус: возьми любой .pkg и вскрой его pkgutil --expand в /tmp, найди папку Scripts и прочитай postinstall (если есть) - не устанавливая.
- Чем .dmg принципиально отличается от .pkg по тому, что происходит с системой при их использовании?
- Что физически представляет собой файл .app и почему его копируют с флагом -R?
- Какой расширенный атрибут запускает проверку Gatekeeper и как посмотреть и снять его в терминале?
- Почему в macOS Sequoia и Tahoe правый клик -> Открыть больше не открывает неподписанное приложение и каким стал штатный путь?
Три формата - три разных контракта. .app это папка-бандл, которую достаточно скопировать в /Applications. .dmg это образ-контейнер, его монтируешь через hdiutil, перетаскиваешь содержимое и отсоединяешь. .pkg это полноценный установщик с зашитыми путями и скриптами, поэтому требует доверия и осознанного запуска через installer -pkg -target /. Над всем этим стоит Gatekeeper, который по метке com.apple.quarantine решает, пускать ли скачанный код, а ты вердикт всегда можешь проверить через spctl и снять карантин через xattr - но только для того, чему реально доверяешь.