Ускорение загрузки Linux: анализ и оптимизация зависимостей systemd
Используйте systemd-analyze, critical-chain и очистку зависимостей модулей, чтобы найти и устранить медленные пути загрузки Linux.
Ускорение загрузки Linux: анализ и оптимизация зависимостей systemd
Оптимизация времени загрузки Linux начинается с одного вопроса: что именно мешает вашей системе стать работоспособной? В большинстве современных дистрибутивов systemd запускает службы параллельно, но медленный модуль или ненужное правило упорядочивания всё ещё могут задерживать процесс загрузки.
Проверив, какие модули занимают время и какие находятся на критической цепочке, вы можете решить, стоит ли их настраивать, откладывать или отключать. Примеры ниже сосредоточены на systemd-analyze и небольших изменениях зависимостей, которые сохраняют предсказуемость системы.
Понимание процесса загрузки systemd
Systemd управляет процессом запуска, выполняя службы параллельно, когда это возможно. Однако служба может запуститься только после выполнения всех её явных и неявных зависимостей. Если модуль A требует, чтобы модуль B был полностью активен, прежде чем он сможет продолжить, модуль A блокируется модулем B. Выявление этих блокирующих зависимостей — первый шаг к ускорению.
Ключевые инструменты анализа systemd
Systemd предоставляет несколько мощных утилит командной строки для диагностики производительности загрузки. Следующие инструменты необходимы для выявления узких мест:
1. systemd-analyze (Общий обзор)
Эта команда предоставляет общий обзор общего времени, затраченного на ядро, инициализацию пользовательского пространства и время, затраченное на загрузку доступных целей.
systemd-analyze
Пример интерпретации вывода:
| Компонент | Затраченное время |
|---|---|
| Ядро | 1.234s |
| Initrd | 0.500s |
| Пользовательское пространство | 5.789s |
| Всего | 7.523s |
Это быстро показывает, находится ли узкое место в фазе ядра (загрузка прошивки/драйверов) или в фазе пользовательского пространства (запуск служб).
2. systemd-analyze blame (Выявление медленных модулей)
Эта команда выводит список модулей, отсортированных по времени их активации, начиная с самых долгих.
systemd-analyze blame
Фокус: Посмотрите на первые 10 записей. Это службы, которые активно потребляют время во время загрузки. Обратите внимание, что длительное время инициализации может просто означать, что служба выполняет много работы; цель — понять, должна ли эта работа выполняться во время загрузки.
3. systemd-analyze critical-chain (Анализ зависимостей)
Эта команда показывает цепочку зависимостей, ведущую к целевой загрузке (обычно graphical.target или multi-user.target). Она выделяет последовательность модулей, которые должны завершиться, прежде чем система будет считаться полностью загруженной.
systemd-analyze critical-chain
Модули, перечисленные в критической цепочке, являются основными целями для оптимизации, потому что их задержка задерживает всю загрузку системы.
4. systemd-analyze plot (Визуализация последовательности загрузки)
Для графического представления параллелизма и блокировок используйте команду plot, которая генерирует SVG-файл:
systemd-analyze plot > boot_analysis.svg
# Откройте boot_analysis.svg в веб-браузере
Этот график наглядно показывает, какие службы работают параллельно, а какие ожидают другие, что делает проблемы с зависимостями очевидными.
Методы оптимизации: изменение файлов модулей
После выявления медленных или блокирующих модулей с помощью описанных выше инструментов оптимизация включает либо ускорение самого модуля, либо изменение времени его запуска.
1. Работа с медленными модулями, выявленными с помощью blame
Если служба, находящаяся высоко в выводе blame (например, slow-database.service занимает 10 секунд), не требуется немедленно для базовой работы системы (например, входа в систему или базовой работы сети), рассмотрите возможность её откладывания.
Действие: Измените уровень зависимости её запуска.
- Если она в настоящее время запускается на
multi-user.target, проверьте, можно ли запускать её по таймеру, сокету, пути или вручную. - Если служба необязательна, её отключение обычно безопаснее, чем изменение основного поведения зависимостей. Используйте
DefaultDependencies=noтолько в том случае, если вы понимаете порядок по умолчанию, который systemd обычно добавляет для данного типа модуля.
2. Оптимизация зависимостей с помощью Wants, Requires и After
Файлы модулей управляют порядком выполнения с помощью директив зависимостей. Неправильная конфигурация здесь является частой причиной ненужного последовательного выполнения.
Типы зависимостей:
Requires=: Сильная зависимость. Если требуемый модуль выходит из строя, этот модуль также выйдет из строя.Wants=: Слабая зависимость. Этот модуль запускается, если желаемый модуль доступен, но всё равно попытается запуститься, если желаемый модуль выйдет из строя.After=: Директива упорядочивания. Этот модуль запустится только после того, как указанный модуль завершит запуск (независимо от успеха).Before=: Директива упорядочивания. Этот модуль должен запуститься до указанного модуля.
Совет по лучшей практике: Предпочитайте Wants вместо Requires для необязательных отношений. Wants= изменяет поведение при сбое, но не упорядочивание само по себе. Желаемый модуль всё ещё может запускаться параллельно, если вы не добавите правило упорядочивания, такое как After=.
Удаление ненужных ограничений After=
Самый эффективный способ ускорить время загрузки — устранить ненужные ограничения упорядочивания. Если модуль A функционально не зависит от того, что модуль B запущен до начала работы модуля A, удалите строку After=unit-b.service из определения модуля A.
Пример модификации (концептуальный):
Предположим, ваш пользовательский модуль приложения app.service ненужно ожидает службу настройки сети:
# /etc/systemd/system/app.service
[Unit]
Description=Моё приложение
Requires=network.target
After=network.target <-- Потенциально ненужное ожидание!
[Service]
ExecStart=/usr/bin/myapp
Если вашему приложению нужен только локальный интерфейс loopback или только установка локальной блокировки файла, ожидание полного сетевого стека (network.target) может тратить несколько секунд. Если вы подтвердите, что приложение на самом деле не требует внешней сети, удалите строку After=network.target. Systemd затем попытается запустить app.service как можно раньше, параллельно с настройкой сети.
3. Маскирование ненужных служб
Если systemd-analyze blame показывает работающую службу, которая вам абсолютно не нужна (например, ненужная поддержка Bluetooth на сервере или конкретный монитор оборудования), её отключение или маскирование полностью предотвращает её запуск.
- Отключить:
systemctl disable <unit>(Предотвращает её запуск при будущих загрузках). - Маскировать (Сильнее):
systemctl mask <unit>(Связывает модуль с/dev/null, предотвращая также попытки ручного запуска).
# Пример: Маскирование ModemManager, если нет сотового модема
sudo systemctl mask ModemManager.service
Перезагрузка и проверка изменений
После изменения любого файла модуля (особенно помещённого в /etc/systemd/system/) вы должны сообщить systemd о необходимости перезагрузки конфигурации демона перед перезагрузкой для тестирования:
sudo systemctl daemon-reload
# Затем проверьте зависимости или статус перед перезагрузкой
systemctl list-dependencies myapp.service
Наконец, всегда перезагружайте систему, чтобы измерить реальное влияние на последовательность загрузки.
sudo reboot
После перезагрузки немедленно снова запустите systemd-analyze, чтобы количественно оценить экономию времени, достигнутую благодаря вашим оптимизациям.
Вывод
Относитесь к настройке загрузки как к циклу небольших изменений: измеряйте с помощью systemd-analyze, находите модули на критическом пути, удаляйте только те правила упорядочивания, которые вы можете обосновать, затем перезагружайтесь и измеряйте снова. Самые безопасные улучшения обычно достигаются за счёт отключения ненужных служб, преобразования работы в таймеры или активацию сокетов и удаления ненужных строк After= из ваших собственных модулей.