С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Цели загрузки: default, multi-user, rescue и emergency

10 мин Ubuntu 24.04 · systemd 255

Цель (target) — группа юнитов, до которой systemd доводит загрузку; rescue и emergency — цели для починки.

Шпаргалка

8 команд Версия для печати
  • systemctl get-default цель загрузки по умолчанию
  • sudo systemctl set-default multi-user.target
  • systemctl list-units --type=target активные цели
  • systemctl list-dependencies multi-user.target что она тянет
  • systemctl list-dependencies --reverse network-online.target
  • systemctl is-system-running running, degraded, starting
  • sudo systemctl rescue перейти в rescue сейчас
  • sudo systemctl default вернуться в цель по умолчанию

Обзор

Цель (target) — юнит без своей работы: имя для группы юнитов и точка в порядке загрузки. systemd загружает систему до цели: берёт default.target, запускает всё, что ей нужно, и зависимости этого. Цели сервера идут по цепочке:

text
sysinit.target → basic.target → multi-user.target → graphical.target
Цель Что к ней готово
sysinit.target файловые системы смонтированы, udev и журнал работают
basic.target сокеты, таймеры и слайсы на месте
multi-user.target службы сервера, вход по SSH и на консоли
graphical.target графический вход поверх multi-user.target
rescue.target ФС смонтированы, служб нет, root-оболочка на консоли
emergency.target почти ничего, root-оболочка на консоли

Сама цель — короткий юнит. Вот multi-user.target:

ini
[Unit]
Description=Multi-User System
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes

AllowIsolate=yes разрешает переключить машину в эту цель целиком — systemctl isolate: всё, что ей не нужно, systemd остановит.

Цель по умолчанию

default.target — символическая ссылка на настоящую цель. Пакет systemd ставит ссылку на graphical.target, а на учебной машине поверх неё лежит своя, в /etc:

text
student@ubuntu:~$ systemctl get-default
multi-user.target
student@ubuntu:~$ readlink /etc/systemd/system/default.target
/usr/lib/systemd/system/multi-user.target

На сервере без графики graphical.target ничего не добавляет к multi-user.target, поэтому обе дают одну и ту же загрузку.

Как служба попадает в загрузку

Служба стартует при загрузке, если её хочет какая-то цель. Строка WantedBy=multi-user.target в секции [Install] сама ничего не делает: systemctl enable превращает её в ссылку в каталоге цели.

text
student@ubuntu:~$ ls /etc/systemd/system/multi-user.target.wants/ \
> | grep -E '^(cron|nginx|ssh)\.'
cron.service
nginx.service
ssh.service

systemctl list-dependencies показывает то же деревом: ● — юнит запущен, ○ — нет:

text
student@ubuntu:~$ systemctl list-dependencies multi-user.target
multi-user.target
● ├─cron.service
○ ├─dmesg.service
  …
● ├─nginx.service
  …
● ├─ssh.service
  …
● ├─basic.target

Юнит без секции [Install] включить нельзя: systemctl status пишет у него static. Такой юнит запускается только как зависимость другого.

Wants и After

Цель тянет юниты так же, как любой юнит: Wants= и Requires= говорят, что запустить вместе, After= и Before= — в каком порядке. After= сам ничего не запускает, поэтому зависимость пишут парой — Wants=x и After=x. Таблица строк и что бывает без пары — systemd.

network-online.target

network.target значит «сетевые службы запущены» — адреса у интерфейсов при этом может ещё не быть. network-online.target — сеть настроена: её держит служба ожидания systemd-networkd-wait-online. Служба, которой при старте нужна сеть — клиент к базе на другой машине, программа, которая слушает конкретный адрес, — пишет:

ini
[Unit]
Wants=network-online.target
After=network-online.target

Кто ждёт сеть на учебной машине:

text
student@ubuntu:~$ systemctl list-dependencies --reverse \
> network-online.target
network-online.target
○ ├─docker.service
○ ├─fwupd-refresh.service
○ ├─iscsid.service
● ├─nginx.service
○ └─open-iscsi.service

У nginx в юните та самая пара: Wants=network-online.target и After=network-online.target remote-fs.target nss-lookup.target.

На учебной машине служба ожидания выключена (masked): у машины нет сети наружу, и ожидание держало бы загрузку до своего тайм-аута. Поэтому здесь network-online.target наступает сразу за network.target.

Rescue и emergency

Обе цели нужны, когда обычная загрузка не доходит до конца. Вместо служб они запускают на консоли root-оболочку и печатают:

text
You are in emergency mode. After logging in, type "journalctl -xb"
to view system logs, "systemctl reboot" to reboot, or "exit"
to continue bootup.
rescue.target emergency.target
файловые системы смонтированы, в том числе из /etc/fstab только корень, часто только для чтения
службы и сеть нет нет
когда сломана служба или настройка, ФС в порядке ошибка в /etc/fstab, ФС не монтируется

Корень в emergency остаётся таким, каким его смонтировало ядро: при ro в строке ядра (cat /proc/cmdline) — только для чтения. Править файлы можно после mount -o remount,rw /.

Перед оболочкой systemd спрашивает пароль root. На учебной машине root заблокирован (sudo passwd -S root → root L …), а в /etc/systemd/system/emergency.service.d/ и rescue.service.d/ лежит Environment=SYSTEMD_SULOGIN_FORCE=1: с ним оболочка открывается без пароля. На сервере без такой строки и с заблокированным root войти не получится — пароль root задают заранее (sudo passwd root).

Цели и уровни запуска

Старые номера уровней запуска SysV — ссылки на цели:

Уровень Цель
0 poweroff.target
1 rescue.target
2, 3, 4 multi-user.target
5 graphical.target
6 reboot.target

runlevel на учебной машине печатает N 3: предыдущего уровня нет, текущий — 3, то есть multi-user.target.

Рецепты

4

Сменить цель по умолчанию

text
student@ubuntu:~$ sudo systemctl set-default graphical.target
Removed "/etc/systemd/system/default.target".
Created symlink /etc/systemd/system/default.target
  → /usr/lib/systemd/system/graphical.target.

Цель сменится при следующей загрузке. Перейти в неё сейчас — sudo systemctl isolate <цель>.

Кто запускает юнит при загрузке

bash
systemctl is-enabled nginx                  # enabled, disabled, static
systemctl show -p WantedBy,RequiredBy nginx  # какие цели его хотят
systemctl list-dependencies --reverse nginx.service

Загрузиться в rescue или emergency

  1. В меню GRUB выбери пункт и нажми e.
  2. В конец строки, которая начинается с linux, допиши systemd.unit=rescue.target или systemd.unit=emergency.target.
  3. Ctrl+X — загрузка с этой строкой, один раз.

Меню GRUB на учебной машине скрыто (GRUB_TIMEOUT=0) и выводится на экран ВМ (GRUB_TERMINAL=console), а терминал урока — последовательная консоль ttyS0: туда идут сообщения ядра и systemd, но не GRUB. Подробнее о загрузчике — boot-grub.

Починить из emergency и загрузиться дальше

bash
journalctl -xb | grep -i -E 'failed|timed out'  # что сломалось
mount -o remount,rw /           # корень на запись
nano /etc/fstab                 # исправить строку
systemctl daemon-reload         # перечитать fstab
mount -a                        # смонтировать всё из fstab
systemctl default               # продолжить загрузку

mount -a без ошибок — fstab в порядке, и systemctl default доведёт загрузку до цели по умолчанию.

Неполадки

5

You are in emergency mode

Загрузку остановила зависимость local-fs.target: чаще всего строка /etc/fstab с устройством, которого нет, или с неверным UUID. В journalctl -xb — Timed out waiting for device и Dependency failed for …. Исправь строку по выводу blkid; диск, без которого система может жить, монтируй с nofail. Подробнее — mount.

Служба работает, а после перезагрузки не запущена

Её не включили: systemctl is-enabled <служба> пишет disabled, и никакая цель её не хочет. sudo systemctl enable <служба> создаст ссылку в multi-user.target.wants. static — у юнита нет секции [Install], допиши её.

Служба стартует раньше сети и падает

В юните нет After=network-online.target или есть только After=network.target. Нужна пара строк из раздела boot-targets; Wants= без After= порядок не задаёт.

Dependency failed for …

Юнит с Requires= (или BindsTo=) не стартовал, потому что не запустилась его зависимость. Причина — в журнале зависимости: journalctl -b -u <зависимость>.

is-system-running: degraded

Загрузка закончилась, но какой-то юнит упал. systemctl --failed покажет какой; после починки — sudo systemctl reset-failed.

Опасно

1

rescue и isolate по SSH

systemctl rescue, systemctl emergency и isolate в цель без сети останавливают ssh.service: сеанс SSH обрывается, вернуться можно только с консоли. Переключай цель, когда консоль под рукой.

Термины

1
цель (target)
Юнит systemd без своей работы — имя для группы юнитов и состояние системы, до которого systemd доводит загрузку: multi-user.target у сервера, rescue.target для починки. Ещё встречается в: Загрузка системы и GRUB, ln, systemd, Символические и жёсткие ссылки и ещё 31

См. также

  • systemd — юниты, drop-in'ы и активация сокетом.
  • systemd-analyze — время загрузки и цепочка зависимостей.
  • boot-grub — загрузчик и строка ядра.
  • systemctl — включение и состояние юнитов.
  • mount — /etc/fstab и монтирование.
  • journalctl — журнал этой загрузки.
Загрузка…