Введение
MacOS фреймворк управления системными службами
launchd — это демон инициализации и управления службами операционной системы, разработанный Apple Inc. в составе macOS для замены init в стиле BSD и SystemStarter. Предпринимались попытки портировать launchd на FreeBSD и производные от неё системы.
Компоненты
В системе launchd существуют две основные программы: launchd и launchctl. launchd управляет демонами как на уровне системы, так и на уровне пользователя. Подобно xinetd, launchd может запускать демоны по требованию. Как и watchdogd, launchd может отслеживать демоны, чтобы убедиться, что они продолжают работать. launchd также заменил init в качестве PID 1 в macOS и, следовательно, отвечает за запуск системы при загрузке. Параметры служб, запускаемых launchd, определяются в конфигурационных файлах. Эти файлы, хранящиеся в подкаталогах LaunchAgents и LaunchDaemons папок Library, представляют собой списки свойств и содержат около тридцати различных ключей, которые можно настроить. Сам launchd не имеет доступа к этим конфигурационным файлам и не может их читать – это задача "launchctl". launchctl – это командная утилита, которая взаимодействует с launchd посредством IPC и умеет разбирать файлы списков свойств, используемые для описания заданий launchd, сериализуя их с помощью специализированного протокола словаря, понятного launchd. launchctl можно использовать для загрузки и выгрузки демонов, запуска и остановки заданий, управляемых launchd, получения статистики использования системы для launchd и его дочерних процессов, а также для установки переменных окружения.
Запуск
У launchd две основные задачи. Первая — загрузка системы, вторая — загрузка и обслуживание сервисов. Вот упрощенный обзор запуска системы Mac OS X Tiger на PowerPC Mac (на Intel Mac EFI заменяет Open Firmware, а boot.efi заменяет BootX): Open Firmware активируется, инициализирует аппаратное обеспечение, а затем загружает BootX. BootX загружает ядро, отображает спиннер (курсор в виде шестеренки) и загружает необходимые расширения ядра (kexts). Ядро загружает launchd. Launchd запускает /etc/rc, различные скрипты, которые сканируют каталоги /System/Library/LaunchDaemons и /Library/LaunchDaemons, вызывая launchctl для plist-файлов по мере необходимости, а затем launchd запускает окно входа в систему. На шаге 4 скрипты запуска сканируют несколько различных каталогов в поисках заданий для выполнения. Сканируются два различных каталога: каталоги LaunchDaemons содержат элементы, которые будут выполняться от имени root, как правило, фоновые процессы. Каталоги LaunchAgents содержат задания, называемые агентскими приложениями, которые будут выполняться от имени пользователя или в контексте пользовательского пространства. Это могут быть скрипты или другие приложения переднего плана, и они могут даже включать пользовательский интерфейс. Все эти каталоги хранятся в стандартных каталогах Library в Mac OS X.
Open Firmware activates, initializes the hardware, and then loads BootX. BootX loads the kernel, spins the pinwheel cursor, and loads any needed kernel extensions (kexts). The kernel loads launchd. launchd runs /etc/rc, various scripts which scan through /System/Library/LaunchDaemons and /Library/LaunchDaemons, calling launchctl on the plists as needed, then launchd starts the login window. In step 4, the startup scripts scan through a few different directories for jobs to run. There are two different directories that are scanned:
The LaunchDaemons directories contain items that will run as root, generally background processes. The LaunchAgents directories contain jobs, called agent applications, that will run as a user or in the context of userland. These may be scripts or other foreground items, and they can even include a user interface. These directories are all kept in the typical Library directories of Mac OS X.
launchd is very different from SystemStarter in that it may not actually launch all the daemons at boot time. Key to launchd, and similar to xinetd, is the idea of launch on demand daemons. When launchctl scans through the job plists at boot time, it asks launchd to reserve and listen on all of the ports requested by those jobs. If so indicated in the plist by the "OnDemand" key, the daemon is not actually loaded at the time. Rather, launchd will listen on the port, start the daemon when needed, and shut it down when it is no longer needed. After a daemon is loaded, launchd will keep track of it and make sure it is running if needed. In this way it is like watchdogd, and shares watchdogd's requirement that processes do not attempt to fork or daemonize on their own. If a process goes into the background, launchd will lose track of it and attempt to relaunch it. Mac OS X Tiger, consequently, boots much faster than previous releases. The system only has to register the daemons that are to run and does not actually launch them until they are needed. In fact, the progress bar that appears during boot time is just a placebo application (named WaitingForLoginWindow) that does not really show anything other than the passage of time. The hardest part to manage during a launchd boot is dependencies. SystemStarter had a very simple system of dependencies that used the "Uses", "Requires", and "Provides" keys in the plist of a startup item. There are two main strategies when creating launchd dependencies on Tiger: IPC allows daemons to talk amongst themselves to work out dependencies, or daemons can watch files or paths for changes. Using IPC is much more subtle than the SystemStarter's keys and requires more work from the developer, but it may lead to cleaner and quicker startups. SystemStarter was still supported up to OS X Mountain Lion, but was removed in OS X Yosemite.
Launchd сильно отличается от SystemStarter тем, что он может не запускать все демоны во время загрузки. Ключевая особенность launchd, схожая с xinetd, — это идея запуска демонов по требованию. Когда launchctl сканирует plist-файлы заданий во время загрузки, он просит launchd зарезервировать и прослушивать все порты, запрошенные этими заданиями. Если в plist-файле указан ключ "OnDemand", демон фактически не загружается в этот момент. Вместо этого launchd прослушивает порт, запускает демон при необходимости и завершает его работу, когда он больше не нужен. После загрузки демона launchd отслеживает его и обеспечивает его работу, если это необходимо. Таким образом, он похож на watchdogd и разделяет требование watchdogd о том, что процессы не должны самостоятельно создавать дочерние процессы или становиться демонами. Если процесс переходит в фоновый режим, launchd теряет его из виду и пытается перезапустить. Следовательно, Mac OS X Tiger загружается намного быстрее, чем предыдущие версии. Система должна только зарегистрировать демоны, которые необходимо запустить, и не запускает их, пока они не понадобятся. Фактически, панель прогресса, которая появляется во время загрузки, — это просто приложение-заглушка (называемое WaitingForLoginWindow), которое на самом деле не показывает ничего, кроме течения времени. Самой сложной задачей при управлении загрузкой launchd являются зависимости. SystemStarter имел очень простую систему зависимостей, которая использовала ключи "Uses", "Requires" и "Provides" в plist-файле элемента запуска. Существует две основные стратегии при создании зависимостей launchd в Tiger: IPC позволяет демонам общаться друг с другом для разрешения зависимостей, или демоны могут отслеживать изменения файлов или путей. Использование IPC намного сложнее, чем ключи SystemStarter, и требует больше работы от разработчика, но может привести к более чистому и быстрому запуску. SystemStarter поддерживался до OS X Mountain Lion, но был удален в OS X Yosemite.
Open Firmware activates, initializes the hardware, and then loads BootX. BootX loads the kernel, spins the pinwheel cursor, and loads any needed kernel extensions (kexts). The kernel loads launchd. launchd runs /etc/rc, various scripts which scan through /System/Library/LaunchDaemons and /Library/LaunchDaemons, calling launchctl on the plists as needed, then launchd starts the login window. In step 4, the startup scripts scan through a few different directories for jobs to run. There are two different directories that are scanned:
The LaunchDaemons directories contain items that will run as root, generally background processes. The LaunchAgents directories contain jobs, called agent applications, that will run as a user or in the context of userland. These may be scripts or other foreground items, and they can even include a user interface. These directories are all kept in the typical Library directories of Mac OS X.
launchd is very different from SystemStarter in that it may not actually launch all the daemons at boot time. Key to launchd, and similar to xinetd, is the idea of launch on demand daemons. When launchctl scans through the job plists at boot time, it asks launchd to reserve and listen on all of the ports requested by those jobs. If so indicated in the plist by the "OnDemand" key, the daemon is not actually loaded at the time. Rather, launchd will listen on the port, start the daemon when needed, and shut it down when it is no longer needed. After a daemon is loaded, launchd will keep track of it and make sure it is running if needed. In this way it is like watchdogd, and shares watchdogd's requirement that processes do not attempt to fork or daemonize on their own. If a process goes into the background, launchd will lose track of it and attempt to relaunch it. Mac OS X Tiger, consequently, boots much faster than previous releases. The system only has to register the daemons that are to run and does not actually launch them until they are needed. In fact, the progress bar that appears during boot time is just a placebo application (named WaitingForLoginWindow) that does not really show anything other than the passage of time. The hardest part to manage during a launchd boot is dependencies. SystemStarter had a very simple system of dependencies that used the "Uses", "Requires", and "Provides" keys in the plist of a startup item. There are two main strategies when creating launchd dependencies on Tiger: IPC allows daemons to talk amongst themselves to work out dependencies, or daemons can watch files or paths for changes. Using IPC is much more subtle than the SystemStarter's keys and requires more work from the developer, but it may lead to cleaner and quicker startups. SystemStarter was still supported up to OS X Mountain Lion, but was removed in OS X Yosemite.
Запуск
В launchd управление службами централизовано в приложении launchctl. Сам по себе launchctl может принимать команды из командной строки, из стандартного ввода или работать в интерактивном режиме. С правами суперпользователя launchctl можно использовать для внесения изменений в глобальном масштабе. Набор команд launchctl можно сделать постоянным, сохранив их в файле /etc/launchd.conf. (Файл ~/.launchd.conf для каждого пользователя рассматривался, но не поддерживается ни в одной существующей версии macOS.) launchctl взаимодействует с launchd посредством специфического для Mach механизма межпроцессного взаимодействия (IPC).
Протокол активации сокета
Имя каждого ключа в разделе Sockets будет помещено в окружение задачи при её запуске, а файловый дескриптор этого сокета станет доступен в этой переменной окружения. Это отличается от активации сокетов systemd тем, что имя определения сокета внутри конфигурации задачи жёстко прописано в приложении. Этот протокол менее гибок, хотя и не требует, как systemd, чтобы демон жёстко кодировал начальный файловый дескриптор (по состоянию на 2014 год, это был дескриптор 3).
История выпусков Apple с открытым исходным кодом
Версия Лицензия Включено в версии macOS Включено версии Apple Developer Tools launchd 106 Лицензия Apple Public Source launchd 106.3 Лицензия Apple Public Source launchd 106.10 Лицензия Apple Public Source launchd 106.13 Лицензия Apple Public Source launchd 106.14 Лицензия Apple Public Source launchd 106.20 Лицензия Apple Public Source launchd 152 Лицензия Apache 2.0 launchd 257 Лицензия Apache 2.0 launchd 258.1 Лицензия Apache 2.0 launchd 258.12 Лицензия Apache 2.0 launchd 258.18 Лицензия Apache 2.0 launchd 258.19 Лицензия Apache 2.0 launchd 258.22 Лицензия Apache 2.0 launchd 258.25 Лицензия Apache 2.0 launchd 328 Лицензия Apache 2.0 launchd 329.3 Лицензия Apache 2.0 launchd 329.3.1 Лицензия Apache 2.0 launchd 329.3.2 Лицензия Apache 2.0 launchd 329.3.3 Лицензия Apache 2.0 launchd 392.18 Лицензия Apache 2.0 launchd 392.35 Лицензия Apache 2.0 launchd 392.36 Лицензия Apache 2.0 launchd 392.38 Лицензия Apache 2.0 launchd 392.39 Лицензия Apache 2.0 launchd 442.21 Лицензия Apache 2.0 launchd 442.26.2 Лицензия Apache 2.0 launchd 842.1.4 Лицензия Apache 2.0 launchd 842.90.1 Лицензия Apache 2.0 launchd 842.92.1 Лицензия Apache 2.0