Решение проблем загрузки systemd: распространенные проблемы и решения

Диагностика проблем загрузки systemd с помощью journalctl, проверки отказавших модулей, целей восстановления, исправлений fstab, анализа зависимостей и отладки initramfs.

Решение проблем загрузки systemd: распространенные проблемы и решения

Проблемы с загрузкой Linux кажутся срочными, потому что вы часто сначала теряете удобные инструменты. SSH может быть недоступен, графический вход может никогда не появиться, а консоль может сбросить вас в аварийный режим с сообщением, которое выглядит хуже, чем есть на самом деле. При проблемах с загрузкой systemd лучший первый шаг — не гадать. Найдите точку, где загрузка остановилась, затем работайте в обратном направлении через журналы модулей, ошибки монтирования, ошибки зависимостей или ранние сообщения ядра.

Это руководство фокусируется на сбоях, которые происходят после того, как ядро запустило systemd как PID 1, а также на нескольких смежных проблемах, которые выглядят как сбои systemd с консоли: неправильные записи /etc/fstab, проблемы с initramfs и ошибки загрузчика.

Понимание процесса загрузки systemd

Systemd управляет процессом загрузки Linux через систему «модулей». Эти модули описывают различные системные ресурсы и службы, такие как службы (.service), точки монтирования (.mount), устройства (.device) и цели (.target). Цели — это специальные модули, которые группируют другие модули и представляют определенные точки синхронизации или состояния во время загрузки, такие как multi-user.target (традиционный runlevel 3) или graphical.target (runlevel 5).

Процесс загрузки обычно включает:

  1. Инициализация ядра: Ядро загружается и инициализирует оборудование.
  2. Этап Initramfs: Загружается начальная RAM-файловая система, которая включает необходимые драйверы и инструменты для монтирования корневой файловой системы.
  3. Запуск Systemd: Systemd берет на себя управление как PID 1, запуская default.target (который часто является символической ссылкой на multi-user.target или graphical.target).
  4. Активация модулей: Systemd читает файлы модулей, разрешает зависимости и запускает службы и монтирования высокопараллельным образом.

Проблемы с загрузкой могут возникнуть на любом из этих этапов, но это руководство в первую очередь фокусируется на проблемах, которые проявляются после запуска systemd.

Первичная сортировка: доступ к журналам загрузки

Когда ваша система не загружается должным образом, первым и наиболее важным шагом является доступ к журналам загрузки. Эти журналы содержат подсказки о том, что пошло не так. Если ваша система не загружается в графическую среду или даже в стандартный TTY, вам нужно будет использовать альтернативные методы.

1. Использование journalctl (из режима восстановления/аварийного режима или Live-носителя)

journalctl — это утилита для запросов к журналу systemd. Если ваша система может загрузиться в режим восстановления или аварийный режим, или если вы используете Live USB/CD для доступа к вашему диску, journalctl — ваш основной инструмент.

Для просмотра журналов предыдущей загрузки:

journalctl -b -1

Для просмотра всех сообщений с момента загрузки системы:

journalctl -b

Для просмотра журналов, связанных с отказавшими модулями:

journalctl -b -p err..emerg # Показать ошибки, критические, предупреждения, аварийные сообщения
journalctl -b --since "-5min" # Показать журналы за последние 5 минут текущей загрузки

Если вы используете live-среду, вам не всегда нужен полный chroot только для чтения журналов. Примонтируйте установленную систему и укажите journalctl на нее:

mount /dev/mapper/vg0-root /mnt
journalctl --directory=/mnt/var/log/journal -b -1

В системах без постоянных журналов старые журналы загрузки могут отсутствовать в /var/log/journal. В этом случае проверьте журналы, специфичные для дистрибутива, в /var/log, или воспроизведите загрузку после включения постоянного ведения журнала, когда система будет достаточно работоспособна для этого.

2. Использование dmesg

dmesg отображает кольцевой буфер ядра, который содержит сообщения от ядра во время загрузки. Это особенно полезно для проблем, возникающих на очень ранних этапах загрузки, до того, как systemd полностью вступит в управление.

dmesg

3. Проверка статуса модулей

Попав в рабочую оболочку (режим восстановления, аварийный режим или live-среда с chroot), вы можете проверить статус всех модулей systemd.

systemctl --failed

Эта команда выводит список всех модулей, которые не удалось запустить. Для получения подробной информации о конкретном отказавшем модуле используйте:

systemctl status <имя_модуля>.service

И для просмотра его конкретных записей журнала:

journalctl -u <имя_модуля>.service -b

Распространенные проблемы загрузки systemd и их решения

1. Отказавшие службы и сбои модулей

Проблема: Критическая служба не запускается, что мешает системе достичь желаемой цели (например, multi-user.target). Это часто проявляется в том, что система переходит в аварийный режим.

Симптомы: systemctl --failed показывает один или несколько модулей в состоянии «failed». journalctl -u <имя_модуля>.service показывает сообщения об ошибках, указывающие, почему служба не смогла запуститься.

Распространенные причины:

  • Неправильная конфигурация: Опечатка в файле конфигурации, неверные пути, отсутствующие зависимости.
  • Отсутствующие файлы/зависимости: Служба пытается получить доступ к файлу или каталогу, который не существует или недоступен.
  • Исчерпание ресурсов: Служба пытается выделить слишком много памяти или других ресурсов.
  • Проблемы с разрешениями: У службы нет необходимых разрешений для чтения/записи файлов или выполнения команд.

Решения:

  1. Определите отказавший модуль: Используйте systemctl --failed.
  2. Проверьте журналы: Выполните journalctl -u <имя_модуля>.service -b для получения подробных сообщений об ошибках.
  3. Исправьте конфигурацию: Отредактируйте файл конфигурации службы (например, /etc/systemd/system/<имя_модуля>.service или файлы в /etc/). Обратите внимание на директивы ExecStart, WorkingDirectory, User, Group, Environment.
  4. Проверьте зависимости: Убедитесь, что все директивы Wants=, Requires=, After=, Before= указаны правильно и что требуемые службы включены.
  5. Перезапустите и повторно включите: После внесения изменений выполните systemctl daemon-reload, затем попробуйте systemctl start <имя_модуля>.service и systemctl enable <имя_модуля>.service.

Пример: Пользовательская веб-служба mywebapp.service не запускается, потому что ее база данных недоступна.

# Проверка статуса
systemctl status mywebapp.service

# Проверка журналов на наличие подсказок
journalctl -u mywebapp.service -b

# Редактирование файла модуля (например, в /etc/systemd/system/mywebapp.service)
# Добавление/изменение директивы After= для обеспечения запуска базы данных первой
# например, After=postgresql.service mysql.service

# Перезагрузка systemd и повторная попытка
systemctl daemon-reload
systemctl start mywebapp.service
systemctl enable mywebapp.service # Обеспечение запуска при следующей загрузке

2. Проблемы с файловой системой

Проблема: Поврежденные файловые системы или неверные записи в /etc/fstab могут помешать системе смонтировать критические разделы, что приведет к аварийному режиму.

Симптомы: Сообщения об ошибках fsck, ошибки mount или переход системы в аварийный режим с сообщением типа «Give root password for maintenance (or type Control-D to continue)».

Распространенные причины:

  • Грязная файловая система: Неправильное завершение работы, потеря питания.
  • Неверный /etc/fstab: Опечатка в UUID/пути к устройству, неверный тип файловой системы, отсутствие noauto для некритичных точек монтирования.
  • Аппаратный сбой: Повреждение диска.

Решения:

  1. Доступ к аварийному режиму: Если будет предложено, введите пароль root.
  2. Проверьте /etc/fstab: Внимательно просмотрите /etc/fstab на наличие ошибок. Временно закомментируйте подозрительные строки с помощью #.
  3. Запустите fsck осторожно: Вручную проверяйте и восстанавливайте файловые системы только когда они размонтированы или смонтированы только для чтения в контексте обслуживания, где ваш дистрибутив документирует это как безопасное. Для некорневого раздела:
    umount /dev/sdb1
    fsck -f /dev/sdb1
    
    Если корневая файловая система требует восстановления, загрузитесь с live-носителя или из среды восстановления и запустите fsck оттуда. Избегайте fsck -y в качестве первого шага на важных дисках; просматривайте подсказки, если у вас нет резервной копии или вы не понимаете характер повреждения.
  4. Перезагрузитесь: После внесения изменений или запуска fsck попробуйте перезагрузиться.

3. Конфликты зависимостей и порядок модулей

Проблема: Службы запускаются в неправильном порядке, или модули имеют конфликтующие зависимости, что приводит к взаимоблокировкам или сбоям.

Симптомы: Тайм-ауты служб, сбои служб из-за того, что их зависимости не готовы, systemd-analyze plot, показывающий длинные цепочки или циклы.

Распространенные причины:

  • Неправильно настроенные директивы Wants=, Requires=, After=, Before= в файлах модулей.
  • Модули, ожидающие ресурсы, которые еще не доступны.

Решения:

  1. Проанализируйте последовательность загрузки: Используйте systemd-analyze для визуализации процесса загрузки.

    • systemd-analyze blame: Показывает службы, упорядоченные по времени их запуска, выделяя медленные модули.
    • systemd-analyze critical-chain: Показывает критический путь модулей, которые напрямую влияют на общее время загрузки.
    • systemd-analyze plot > boot.svg: Генерирует SVG-изображение всего графа зависимостей загрузки, бесценно для сложных проблем.
  2. Проверьте зависимости модулей: Используйте systemctl list-dependencies <имя_модуля>, чтобы увидеть, что требуется модулю и что от него зависит.

  3. Настройте директивы файла модуля:

    • After=, Before=: Управляют порядком модулей. Если A.service имеет After=B.service, A запустится после B (если B вообще запускается). Используйте After= для большинства потребностей в упорядочивании.
    • Wants=: Выражает слабую зависимость. Если A.service Wants=B.service, B будет запущен при запуске A, но A продолжит работу, даже если B не удастся.
    • Requires=: Выражает сильную зависимость. Если A.service Requires=B.service, B подтягивается при запуске A, и A не удается, если B не может быть запущен. Если B явно остановлен, A также останавливается.
    • Conflicts=: Гарантирует, что определенный модуль будет остановлен, если текущий модуль запущен, и наоборот.
    • PartOf=: Связывает жизненный цикл одного модуля с другим (например, если slice остановлен, все модули PartOf него также останавливаются).

    Совет: Всегда отдавайте предпочтение After= и Wants= для большинства зависимостей, чтобы избежать создания тесной связи, которая может привести к взаимоблокировкам или каскадам сбоев.

4. Паники ядра / Проблемы с Initramfs

Проблема: Система не загружается на очень раннем этапе, часто до того, как systemd полностью вступит в управление, отображая сообщения типа «Kernel panic - not syncing» или связанные с dracut или initramfs.

Симптомы: Ранний сбой загрузки, часто с большим объемом текста, показывающим трассировки стека или сообщения об отсутствующем корневом устройстве, /dev/root не найден и т.д.

Распространенные причины:

  • Отсутствующие модули ядра: Initramfs не содержит необходимых драйверов для корневой файловой системы (например, LVM, RAID, определенные контроллеры дисков).
  • Поврежденное ядро/Initramfs: Файлы повреждены.
  • Неверные параметры ядра: Параметр root= в GRUB указывает на неверное устройство.

Решения:

  1. Перестройте Initramfs: Это распространенное исправление. Загрузитесь в live-среду или другое ядро, выполните chroot в вашу систему и перестройте initramfs.
    # Пример для Dracut (Fedora/RHEL/CentOS)
    dracut -f -v /boot/initramfs-$(uname -r).img $(uname -r)
    
    # Пример для mkinitcpio (Arch Linux)
    mkinitcpio -P
    
    # Пример для update-initramfs (Debian/Ubuntu)
    update-initramfs -u -k all
    
  2. Проверьте конфигурацию GRUB: Проверьте /boot/grub/grub.cfg (или /etc/default/grub, если вы его перегенерируете) на наличие правильного параметра root= и пути initrd.
  3. Параметры ядра: Если вы подозреваете, что определенный модуль отсутствует или вызывает проблемы, вы можете попробовать добавить параметры ядра в GRUB (например, rd.break, чтобы перейти в оболочку initramfs для отладки).

5. Проблемы с GRUB/Загрузчиком

Проблема: Система даже не доходит до точки загрузки ядра или зависает в меню GRUB.

Симптомы: «No boot device found», приглашение GRUB rescue или GRUB не может загрузить ядро.

Распространенные причины:

  • Поврежденный загрузчик.
  • Неверная конфигурация GRUB, указывающая на несуществующее ядро/initramfs.
  • Настройки BIOS/UEFI, препятствующие правильному порядку загрузки.

Решения:

  1. Переустановите GRUB: Загрузитесь с Live USB, выполните chroot в вашу систему и переустановите GRUB в MBR/EFI-раздел.
    # Пример
    mount /dev/sdaX /mnt # Монтирование корневого раздела
    
    mount /dev/sdaY /mnt/boot/efi # Если отдельный EFI-раздел
    
    for i in /dev /dev/pts /proc /sys /run; do mount --bind $i /mnt$i; done
    chroot /mnt
    
    grub-install /dev/sda # Установка на основной диск
    
    grub-mkconfig -o /boot/grub/grub.cfg # Перегенерация конфигурации GRUB
    
    exit
    umount -R /mnt
    reboot
    
  2. Проверьте настройки BIOS/UEFI: Убедитесь, что правильный загрузочный диск имеет приоритет.

Продвинутые методы устранения неполадок

Загрузка в режим восстановления/аварийный режим

Эти режимы предоставляют минимальную среду для устранения неполадок. Чтобы войти в них:

  1. Во время GRUB: Нажмите e для редактирования командной строки ядра.
  2. Найдите строку linux: Найдите строку, начинающуюся с linux (или linuxefi).
  3. Добавьте systemd.unit=rescue.target для режима восстановления (большинство служб выключены, однопользовательская оболочка).
  4. Добавьте systemd.unit=emergency.target для аварийного режима (минимальные службы, часто корневая файловая система только для чтения).
  5. Нажмите Ctrl+X или F10 для загрузки.

Использование rd.break для отладки Initramfs

Добавление rd.break в командную строку ядра в GRUB перебросит вас в оболочку внутри initramfs до монтирования реальной корневой файловой системы. Это чрезвычайно полезно для отладки проблем initramfs, таких как отсутствующие драйверы или проблемы с настройкой LVM/RAID.

Попав в оболочку initramfs, вы можете:

  • Проверить lsblk, mount.
  • Проверить наличие отсутствующих файлов в /sysroot.
  • Попробовать вручную смонтировать корневую файловую систему.

Анализ производительности загрузки

Хотя это и не является строго «сбоем», медленное время загрузки может указывать на основные проблемы или неэффективные конфигурации служб.

  • systemd-analyze blame: Определите службы, которые запускаются дольше всего.
  • systemd-analyze critical-chain: Поймите критический путь зависимостей, влияющих на общее время загрузки.

Безопасная последовательность восстановления

Когда вы находитесь на консоли, а машина загружена наполовину, придерживайтесь скучной последовательности восстановления:

  1. Зафиксируйте точную ошибку на экране, если можете.
  2. Выполните systemctl --failed.
  3. Прочитайте journalctl -b -p err..alert --no-pager.
  4. Если модуль не удался, прочитайте journalctl -u имя-модуля -b.
  5. Если монтирование не удалось, проверьте /etc/fstab, проверьте UUID с помощью blkid и закомментируйте только подозрительное некритичное монтирование.
  6. Если задействованы корневая файловая система или initramfs, переключитесь на live-носитель или режим восстановления перед внесением инвазивных исправлений.
  7. После редактирования файлов модулей выполните systemctl daemon-reload и перезапустите только затронутый модуль, когда это возможно.

Большинство проблем с загрузкой systemd не решаются изменением многих вещей одновременно. Плохая строка монтирования, отсутствующий диск, служба с неработающим ExecStart= или ошибка упорядочивания оставляют довольно прямой след. Следуйте этому следу, сделайте одно небольшое исправление и перезагружайтесь только тогда, когда текущая оболочка не может проверить исправление.

Используйте эти инструменты для выявления узких мест и оптимизации запуска модулей путем настройки директив After=, Requires=, TimeoutStartSec= или Type=.

Профилактика и лучшие практики

  • Тестируйте изменения: Перед развертыванием изменений файлов модулей в производственной среде тестируйте их в промежуточной среде.
  • Резервное копирование конфигурации: Регулярно создавайте резервные копии /etc/ или, по крайней мере, критических файлов /etc/systemd/system/.
  • Понимайте директивы модулей: Твердое понимание man-страниц systemd.service(5) и systemd.unit(5) бесценно.
  • Используйте drop-in файлы: Вместо прямого изменения файлов модулей /lib/systemd/system/ (которые могут быть перезаписаны при обновлениях) используйте drop-in файлы (/etc/systemd/system/<имя_модуля>.service.d/*.conf) для пользовательских конфигураций.
  • Храните ядра: Всегда храните хотя бы одно заведомо рабочее старое ядро в вашей системе, чтобы загрузиться с него, если новое ядро вызовет проблемы.

Заключение

Решение проблем загрузки systemd требует системного подхода, начиная с эффективного анализа журналов. Понимая модульную архитектуру systemd и используя такие инструменты, как journalctl, systemctl и systemd-analyze, вы сможете эффективно определить первопричину сбоев загрузки, будь то неправильно настроенная служба, проблема с файловой системой или сложный конфликт зависимостей. Возможность загрузиться в режим восстановления или аварийный режим в сочетании с продвинутыми методами отладки позволяет вам восстановить контроль над вашей системой, даже когда она кажется полностью не отвечающей. С этими стратегиями и лучшими практиками вы будете хорошо подготовлены к решению большинства проблем с загрузкой systemd и поддержанию стабильной и надежной работы Linux.