Выделенные GPU-серверы меняют ландшафт современных вычислений - от обучения моделей искусственного интеллекта и анализа данных до рендеринга видео и научных исс...
Блог компании 3v-Hosting
15 мин.
Перезагрузка сервера - это операция, которую администраторы обычно стараются выполнять как можно реже, и всё же иногда приходится это делать. Да, процедура не сложная и зачастую достаточно безобидная. Однако, если после reboot машина несколько минут не возвращается в строй, то это может стать причиной вполне существенных проблем. Согласитесь, выглядит не очень, когда ты решил "по быстрому" перезагрузить сервер, а вместо этого получил несколько минут учащенного сердцебиения и пару десятков седых волос.
При этом медленная загрузка Linux-сервера далеко не всегда означает нехватку процессорных ресурсов или медленный диск. Сервер даже может иметь NVMe и достаточно быстрый CPU, но терять минуту из-за одного сервиса, ожидающего сеть, несуществующее устройство или файловую систему.
Поэтому оптимизация загрузки Linux часто становится необходимостью. И начинать её следует не с отключения всего подряд, а с измерения вполне конкретных метрик, которые покажут, на каком этапе возникает задержка.
В общем, лишние 30-60 секунд при загрузке сервера быстро превращаются во вполне заметную проблему, которую мы и попробуем устранить в этой статье.
Если сильно упростить, то загрузка Linux проходит через несколько последовательных этапов:

Сначала BIOS или UEFI инициализирует оборудование и передает управление загрузчику, обычно GRUB. Тот загружает в память ядро Linux и initramfs. Ядро запускается, инициализирует основные подсистемы и подключает доступные на этом этапе драйверы.
Дальше в работу вступает initramfs - это своего рода временное минимальное окружение, которое помогает подготовить систему к работе с настоящей корневой файловой системой. Тут могут загружаться дополнительные модули, обнаруживаться диски, собираться RAID-массивы или открываться зашифрованные разделы. После монтирования корневой файловой системы управление переходит к systemd.
На физическом сервере время BIOS/UEFI и инициализации оборудования может занимать заметную часть всей загрузки. У VPS этот этап частично зависит от гипервизора и обычно находится за пределами самой гостевой Linux-системы.
Дальше systemd запускает системные сервисы и приводит систему к нужному состоянию (targets). Причем сервисы не выстраиваются в одну длинную очередь, так как если зависимости позволяют, то несколько задач выполняются параллельно. Поэтому сервис с временем запуска 15 секунд вовсе не обязательно задерживает готовность системы на те же 15 секунд.
Вот эту часть загрузки уже удобно разбирать с помощью такого инструмента как systemd-analyze. Перейдём-же к конкретному анализу.
Итак, начинать диагностику стоит с самой простой команды:
systemd-analyze
или:
systemd-analyze time
Ответ будет выглядеть примерно так:
Startup finished in 1.842s (kernel) + 5.731s (userspace) = 7.573s multi-user.target reached after 5.214s in userspace
systemd-analyze отдельно показывает время ядра, initrd и userspace, если соответствующие этапы присутствуют. При этом результат нельзя воспринимать буквально как момент полной готовности всех приложений. Systemd измеряет прохождение определенных этапов запуска системы, а отдельные сервисы после этого еще могут продолжать инициализацию.
Но уже здесь можно определить направление будущего поиска, так как если, например, ядро запускается за две секунды, а userspace занимает минуту, то очевидно бессмысленно начинать с параметров GRUB или сборки собственного ядра, так как проблема почти наверняка находится выше.
Прежде чем искать конкретный медленный сервис, нужно понять, где вообще теряется время. Задержка может появиться еще до запуска systemd, например когда ядро долго инициализирует устройство, initramfs пытается найти корневую файловую систему или система ждет недоступный диск из /etc/fstab.
Есть и менее очевидный вариант, когда Linux уже почти загрузился, SSH уже доступен, но вот нужное приложение "оживает" спустя полминуты. И тут проблема лежит где-то выше по цепочке - например, сервис ждет базу данных, контейнеры или завершение миграций.
Поэтому сначала полезно определить проблемный этап, а уже потом разбирать отдельные units. Мы свели все базовые инструменты для этой работы в одну наглядную и удобную таблицу. Конечно, она не исчерпывающая, да и не может такой быть, но по крайней мере начать с неё можно.
| Где теряется время | Что может быть причиной | Что проверять |
|---|---|---|
| Ядро (Kernel) | долгая инициализация драйверов, дисков или виртуальных устройств | dmesg, journalctl -b -k |
| Initramfs / Initrd | LVM, RAID, шифрование, ожидание диска или поиск root FS | ранние boot logs, конфигурация initramfs |
| Userspace | медленные systemd units, зависимости между ними | systemd-analyze, systemd-analyze blame |
| Сеть | DHCP, настройка интерфейса, ожидание wait-online |
networkctl, NetworkManager, журналы сетевых сервисов |
| Монтирование | неверный UUID, отсутствующий диск, недоступный сетевой mount | /etc/fstab, lsblk, findmnt |
| Приложение запускается поздно | ожидание базы данных, запуск контейнеров, миграции приложения, собственная инициализация | systemctl status, journalctl -u, журнал приложения |
Если задержка находится в userspace, то можно перейти к отдельным systemd units. Для начала посмотрим, какие из них активировались дольше остальных с помощью команды:
systemd-analyze blame
На сервере с большим количеством сервисов вывод быстро разрастается, поэтому удобнее сразу оставить первые 20 строк:
systemd-analyze blame --no-pager | head -20
В результате вы должны увидеть такой, приблизительно, ответ:
21.384s systemd-networkd-wait-online.service 8.912s mysql.service 3.421s docker.service 1.204s ssh.service
Теперь уже видно, куда смотреть. В примере сильнее всего выделяется systemd-networkd-wait-online.service, так как его активация заняла больше 21 секунды. Но тут легко сделать неправильный вывод.
systemd-analyze blame показывает продолжительность активации каждого unit. Это время нельзя напрямую считать задержкой всей загрузки, ведь systemd запускает множество независимых units параллельно, поэтому пока один сервис ждет 21 секунду, то рядом могут запускаться другие.
Получается, отключение первой строки из blame совсем не гарантирует, что сервер загрузится на 21 секунду быстрее. Чтобы найти задержки, которые действительно лежат на пути к готовой системе, нужно посмотреть зависимости и критическую цепочку загрузки.
Команда systemd-analyze blame хорошо показывает медленные units, но для диагностики загрузки Linux этого мало. Нас интересует другой вопрос: какие из этих задержек действительно влияют на момент, когда система достигает нужного состояния?
Для этого есть отдельная команда:
systemd-analyze critical-chain
Она показывает критическую цепочку загрузки, то есть последовательность units, время запуска которых связано зависимостями и влияет на достижение выбранного target.
Условный вывод может выглядеть так:
multi-user.target @18.921s └─docker.service @12.412s +6.401s └─network-online.target @12.390s └─systemd-networkd-wait-online.service @2.341s +10.032s
Вот здесь уже есть конкретный след. docker.service ожидает network-online.target, а тот достигается только после завершения systemd-networkd-wait-online.service. Последний в нашем примере активируется около десяти секунд.
Получается цепочка, которую можно разбирать сверху вниз. Вместо длинного списка медленных сервисов мы видим связанные между собой units и можем искать место, где задержка действительно распространяется дальше по загрузке.
При этом critical-chain тоже не стоит воспринимать как полный граф загрузки. Эта команда показывает критичную по времени ветку зависимостей, но параллельно с ней systemd может выполнять множество других задач. Для первого поиска узкого места этого обычно достаточно.
Допустим, подозрительный unit найден и теперь нужно выяснить, что с ним происходит: когда он запускается, сколько времени занимает активация и от каких других units зависит.
Начать проще всего со статуса:
systemctl status docker.service
Здесь видны текущее состояние сервиса, время его запуска и последние сообщения журнала. Если информации мало, можно посмотреть все свойства unit:
systemctl show docker.service
Следующий шаг - это поиск зависимостей:
systemctl list-dependencies docker.service
Эта команда покажет units, связанные с запуском выбранного сервиса, но иногда интереснее посмотреть и в обратную сторону:
systemctl list-dependencies --reverse docker.service
Так можно увидеть, какие units зависят уже от docker.service. Это особенно полезно, когда сам сервис запускается долго и хочется понять, что именно он задерживает.
Одного факта, что unit потратил десять или двадцать секунд, недостаточно, так как нужно найти причину ожидания и понять его место в цепочке загрузки. Иногда проблема действительно может находиться внутри сервиса, но иногда он просто стоит в очереди за другим unit - и искать причину нужно уже там.
Одной из наиболее частых причин длительной загрузки Linux-сервера является ожидание готовности сети. В результатах systemd-analyze при этом обычно появляется один из двух сервисов:
systemd-networkd-wait-online.service
или, если сеть управляется через NetworkManager:
NetworkManager-wait-online.service
Логика у них простая. systemd может считать базовую настройку сети завершенной раньше, чем нужный интерфейс действительно получит адрес и соединение станет пригодным для работы. wait-online задерживает достижение network-online.target до выполнения заданных сетевых условий.
Такое ожидание необходимо некоторым системам, ведь, например, при загрузке может потребоваться сетевой файловый ресурс, а отдельный сервис способен нормально запуститься только после появления рабочего соединения. Но на обычном VPS эти несколько секунд ожидания иногда оказываются совершенно лишними.
Проблемы начинаются, когда ожидаемое состояние сети долго не наступает: DHCP не отвечает, в конфигурации сохранился старый интерфейс, дополнительный NIC отключен - в итоге система продолжает ждать до выполнения условия или истечения тайм-аута.
Для проверки именно этого сценария сначала посмотрим, что связано с network-online.target:
systemctl list-dependencies network-online.target
Текущее состояние интерфейсов при использовании systemd-networkd можно проверить так:
networkctl
Также полезно сразу свериться с обычными сетевыми командами:
ip addr ip route
А если сервер использует NetworkManager, тогда смотрим устройства и сохраненные подключения:
nmcli device status nmcli connection show
Причины, по которым wait-online может задерживать загрузку на десятки секунд, бывают разными, причем часть из них после первого взгляда на конфигурацию сети легко пропустить. Например:
network-online.target, хотя способен работать без ожидания полностью готовой сети.
Особенно неприятен последний случай, когда с самой сетью все может быть в полном порядке, но один лишний dependency заставляет процесс загрузки ждать network-online.target.
Поэтому следующая команда может убрать задержку:
systemctl disable systemd-networkd-wait-online.service
Но применять ее вслепую не стоит! После отключения сервер действительно способен начать загружаться быстрее, а вот зависимый сервис может получить сеть позже, чем рассчитывает. В результате проблема просто переедет из времени загрузки в журнал этого сервиса.
Сначала лучше выяснить, кому вообще нужен network-online.target. Для обратного просмотра зависимостей подойдет команда:
systemctl list-dependencies --reverse network-online.target
Если выяснится, что гарантированно готовая сеть перед запуском этих служб не требуется, тогда уже есть смысл пересматривать зависимости или настройки wait-online.
Иногда сама продолжительность задержки уже подсказывает направление поиска.
Так, если загрузка каждый раз замирает примерно на одинаковое время - например, около 30, 60 или 90 секунд, то стоит искать компонент, который ожидает событие до истечения определенного timeout.
Типичный сценарий выглядит так:

Причиной может быть отсутствующий или неправильно прописанный диск, недоступный сетевой ресурс, DHCP, неправильно настроенный mount или сервис, ожидающий какой либо внешний ресурс.
Именно поэтому при диагностике полезно обращать внимание не только на ошибки, но и на подозрительно повторяемые интервалы времени.
После поиска явных задержек можно посмотреть на набор сервисов, которые запускаются вместе с системой. В универсальном образе Linux нередко остаются службы, которые конкретному серверу просто не нужны. Особенно много такого встречается в образах, рассчитанных сразу на разные сценарии установки.
Список включенных unit-файлов можно получить командой:
systemctl list-unit-files --state=enabled
Но статус enabled сам по себе еще ничего не говорит о том, можно ли отключать сервис. Сначала стоит посмотреть, что он делает и с какими units связан:
systemctl status имя.service systemctl list-dependencies имя.service
Напомним, что полезно проверить зависимости и в обратную сторону, ведь так видно, кто может рассчитывать на этот сервис:
systemctl list-dependencies --reverse имя.service
Если служба на сервере действительно не используется, то ее автозапуск можно отключить:
sudo systemctl disable имя.service
При этом disable не запрещает запуск сервиса полностью и его по-прежнему можно будет запустить вручную. А в некоторых случаях он может активироваться через другие механизмы systemd, например socket или D-Bus activation.
Однако есть и более жесткий вариант, полного отключения сервиса:
sudo systemctl mask имя.service
mask связывает unit с /dev/null, поэтому systemd блокирует его обычный запуск. Это уже инструмент для случаев, когда сервис вовсе не должен стартовать. Использовать его только ради выигрыша нескольких сотен миллисекунд смысла не имеет.
Также стоит быть осторожнее с сетевыми службами, такими как SSH, mount units, cloud-init и агентами виртуализации. Часть из них нужна только во время загрузки сервера, поэтому после запуска системы может ошибочно показаться, что эти службы вообще ничего не делают.
После всех изменений стоит перезагрузить сервер и снова выполнить systemd-analyze, так как любая оптимизация имеет смысл только тогда, когда задержка действительно исчезла, а все нужные сервисы после перезагрузки остались рабочими.
Иногда задержка появляется не потому, что какой-либо сервис медленный сам по себе, а потому, что система может несколько десятков секунд ждать ресурс, которого вообще не существует. Чтобы исключить этот вариант проверим несколько журналов:
Начнем с общего:
systemctl --failed
После этого стоит проверить журнал текущей загрузки:
journalctl -b
Для быстрого поиска предупреждений и ошибок можно использовать фильтр:
journalctl -b -p warning
Здесь можно обнаружить ошибки монтирования, проблемы с устройствами, сетевыми интерфейсами, драйверами и сервисами.
Если подозрение падает на конкретный unit, то удобнее будет сразу ограничить выборку из журнала с помощью того-же фильтра:
journalctl -b -u имя.service
Например:
journalctl -b -u systemd-networkd-wait-online.service
Очевидно, что так искать причину обычно проще, чем просматривать весь boot journal вручную.
/etc/fstab и отсутствующие дискиЗадержка при загрузке может крыться в ошибке, допущенной при конфигурации дисков в /etc/fstab. Такое часто происходит после изменений в конфигурации дисков, после того, как устройство уже удалили или отключили, а запись для его автоматического монтирования осталась.
Например:
UUID=xxxx /mnt/storage ext4 defaults 0 2
При следующей загрузке systemd попытается найти устройство с указанным UUID и смонтировать его. Но если этого диска в действительности больше нет, то система может потратить время на ожидание его появления. И иногда именно отсюда берутся подозрительные паузы в несколько десятков секунд.
Чтобы исключить этот вариант, сначала посмотрим доступные файловые системы и их UUID с помощью команды:
lsblk -f
UUID можно дополнительно проверить через:
blkid
Теперь проверим сам файл /etc/fstab:
findmnt --verify
Если в fstab указан UUID, которого нет среди доступных устройств, то эту запись стоит проверить первой.
При этом удалять ее сразу необязательно. Для дополнительного диска, отсутствие которого не мешает работе сервера, можно использовать параметр nofail. Тогда ошибка монтирования такого хранилища не должна делать его обязательным условием успешной загрузки.
Есть и другие варианты. Например x-systemd.automount позволяет монтировать файловую систему при первом обращении к ней, а x-systemd.device-timeout= задает время, в течение которого systemd будет ждать появления устройства.
Ну и для необязательного архивного диска такая конфигурация может быть вполне разумной:
UUID=xxxx /mnt/archive ext4 defaults,nofail,x-systemd.device-timeout=5s 0 2
С критическими файловыми системами ситуация немного другая. Так, если на разделе лежат данные PostgreSQL или Docker, скрывать проблему с его доступностью через nofail ради более быстрой загрузки сервера достаточно опасно.
Иногда задержка возникает еще до запуска systemd. Если systemd-analyze показывает заметное время на этапе kernel, то искать медленный сервис уже бессмысленно, ведь проблема очевидно находится раньше в цепочке загрузки.
Начать поиск, в таком случае, можно с сообщений ядра:
dmesg
А для текущей загрузки удобен журнал kernel:
journalctl -b -k
Он показывает сообщения ядра только для текущей загрузки. Это особенно полезно, если часть ранних сообщений уже исчезла из kernel ring buffer и вывод dmesg получился неполным.
В журнале стоит искать такие события как:
Последний пункт часто дает хороший ориентир. Сообщение само по себе может выглядеть совершенно нормально, но если следующая строка появилась спустя 20 секунд, то стоит выяснить, чем ядро занималось в этот промежуток.
Можно сразу вывести сообщения с удобными для сравнения временными метками с помощью команды:
journalctl -b -k -o short-monotonic
Тут уже проще будет заметить место, где нормальный поток сообщений внезапно прерывается длинной паузой.
Как мы уже вскользь упоминали выше, набор возможных причин зависит и от типа сервера. В VPS ядро работает с виртуальным оборудованием, которое предоставляет гипервизор, поэтому часть физических проблем скрыта от гостевой системы. А вот на bare metal приходится учитывать реальные диски, контроллеры, сетевые карты, firmware и другое оборудование.
Если задержка обнаружилась именно здесь, то дальнейшая диагностика обычно строится вокруг сообщений непосредственно перед временным разрывом и сразу после него.
Напомним, что initramfs - это временная файловая система, которую ядро использует на раннем этапе загрузки. В ней находятся компоненты, необходимые для подготовки и монтирования настоящей корневой файловой системы, такие например, как драйверы накопителей, инструменты LVM, модули программного RAID или средства работы с зашифрованными разделами.
Но состав initramfs можно оптимизировать. Можно убрать ненужные модули, изменить способ его формирования и тем самым немного сократить время ранней загрузки. Правда потенциальный выигрыш здесь обычно невелик, а ошибка способна закончиться системой, которая вообще не найдет root FS после перезагрузки.
Особенно осторожно нужно работать с серверами, где используются LVM, программный RAID, шифрование дисков или нестандартная конфигурация хранилища. В таких случаях содержимое initramfs напрямую связано с возможностью загрузить систему.
На обычном VPS лезть сюда ради оптимизации есть смысл только тогда, когда диагностика действительно указывает на задержку на этапе initramfs. Поэтому если systemd-networkd-wait-online отнимает 25 секунд, а весь ранний этап загрузки занимает пару секунд, начинать с пересборки initramfs явно рано и сначала стоит разбираться с крупными задержками. Ведь экономия нескольких сотен миллисекунд мало что изменит, если дальше по цепочке система десятки секунд ждет сеть, диск или зависший сервис.
Всё описанное выше, все эти списки и цепочки зависимостей удобны, пока количество units остается достаточно небольшим. Но на сервере с десятками сервисов текстовый вывод быстро разрастается, и понять общую картину становится куда сложнее. Тут пригодится еще одна возможность утилиты systemd-analyze - построение временной диаграммы загрузки.
Создать ее можно одной командой:
systemd-analyze plot > boot.svg
В результате появится файл boot.svg, который можно открыть обычным браузером. На диаграмме загрузка сервера разложена по времени: видно момент запуска каждого unit, продолжительность его активации и работу других units в тот же период.

Пример временной диаграммы загрузки Linux
Эта диаграмма наглядно показывает параллельность systemd. Сервис из верхней части systemd-analyze blame может выглядеть медленным, но на диаграмме окажется, что все это время рядом запускались другие компоненты и общую загрузку он почти не задерживал. И обратная ситуация тоже может быть заметна сразу, когда короткие по отдельности units могут выстроиться в длинную последовательность зависимостей, где следующий начинает работу только после завершения предыдущего.
На сервере с Docker, PostgreSQL, Nginx, системами мониторинга, резервного копирования и собственными systemd units такая визуализация особенно полезна, ведь несколько десятков строк терминала превращаются в одну временную шкалу, по которой гораздо проще искать подозрительные участки.
Здесь хорошо подойдет реальный фрагмент boot.svg с выделенным долгим unit или цепочкой зависимостей. На таком примере разница между временем отдельного сервиса и его реальным влиянием на загрузку видна почти сразу.
Мы подходим к концу и для быстрой диагностики, всю, описанную выше методику, можно свести к небольшой таблице:
| Симптом | Вероятное направление поиска | С чего начать |
|---|---|---|
| Долгий userspace | systemd unit | systemd-analyze blame |
| Несколько медленных units | зависимости | systemd-analyze critical-chain |
| Долгое ожидание сети | wait-online, DHCP, интерфейс | networkctl, nmcli |
| Пауза одинаковой длительности | timeout | journalctl -b |
| Проблема появилась после удаления диска | /etc/fstab |
lsblk -f, findmnt --verify |
| Долго загружается kernel | storage, driver, device | dmesg, journalctl -b -k |
| Есть failed units | ошибка сервиса или ресурса | systemctl --failed |
| Linux загрузился, но сайт еще недоступен | приложение, БД, контейнеры | service logs, health check |
Такая таблица полезна еще и тем, что помогает не начинать диагностику не с того конца, ведь если userspace занимает 40 секунд, то ковырять параметры ядра рано. Если systemd запускается мгновенно, но PostgreSQL еще минуту выполняет recovery, ускорение multi-user.target вообще не решит исходную проблему.
Увы, единого нормального времени загрузки не существует, так как очевидно, что небольшой VPS и физический сервер с RAID-контроллером, несколькими сетевыми интерфейсами и большим набором сервисов будут загружаться по-разному.
Да и достижение multi-user.target еще не всегда означает, что сервер готов к работе, ведь, например, PostgreSQL может продолжать восстановление после сбоя, Docker - запускать контейнеры, а ваше приложение - выполнять миграции.
Поэтому полезнее определить свою точку готовности. Для веб-сервера это может быть успешный ответ Nginx на health check, для базы данных - возможность принимать подключения, а у инфраструктурного узла критерием станет доступность нужных сетевых служб.
По сути, правильным и важным является время восстановления сервера - то время, которое проходит от запуска машины до момента, когда она снова способна выполнять свою работу.
Итак, оптимизация времени загрузки Linux-сервера редко требует экзотических патчей ядра или радикального удаления системных компонентов. Чаще всего виновником оказывается вполне прозаичная вещь, как то ожидание сети, отсутствующий диск, ненужный сервис, неправильная зависимость или слишком долгий timeout.
Главные инструменты для поиска причин задержек загрузки уже находятся в системе. Это такие инструменты как systemd-analyze, critical-chain, systemctl, journalctl, dmesg, lsblk и findmnt. Вместе они позволяют разложить загрузку на понятные этапы и понять, куда действительно уходят драгоценные секунды.
Самое важное во всей этой работе - не превращать ускорение загрузки в соревнование за минимальную цифру, так как для рабочего Linux-сервера стабильные 12 секунд лучше нестабильных семи, а хорошая оптимизация - это когда после reboot машина не просто быстрее появляется в сети, а каждый раз предсказуемо возвращается в полностью рабочее состояние.
Единого норматива нет и быть не может, так как время зависит от оборудования или виртуальной машины, конфигурации дисков, сети и количества запускаемых служб. Гораздо полезнее сравнивать конкретный сервер с его обычным временем загрузки и искать резкие отклонения.
Чаще всего причина связана с ожиданием какого-либо ресурса. Это может быть диск, сетевой интерфейс, DHCP, файловая система или systemd-сервис. Задержка может возникнуть и раньше - во время работы ядра или initramfs.
Одинаковая продолжительность паузы часто указывает на какой либо timeout. Система чего-то ждет, не получает ожидаемого события и продолжает загрузку только после истечения заданного времени.
/etc/fstab замедлять загрузку?Да. Например, в /etc/fstab может остаться запись о диске, который уже отключен. При загрузке система попытается найти устройство и некоторое время будет ждать его появления.
systemd запускает многие службы параллельно. Сервис может активироваться 15 секунд, но в это же время система занимается другими задачами. Поэтому длительность запуска отдельного unit и его влияние на общее время загрузки - это разные вещи.
Зависит от службы. Отключение действительно ненужного сервиса обычно не создает проблем, но вмешательство в работу сети, файловых систем, SSH или компонентов виртуализации может привести к сбоям после перезагрузки. Сначала нужно выяснить назначение службы и ее зависимости.
Что делать, если закончилось место в /var на Linux-сервере. Пошаговая диагностика и безопасная очистка логов, Docker, journald и APT в Debian и Ubuntu.
Настройка gzip и Brotli в Nginx: сжатие HTML, CSS и JavaScript, выбор уровня компрессии, снижение нагрузки на сервер, проверка и решение типичных проблем.
Что такое epoll и почему Nginx считается одним из самых быстрых веб-серверов? Разбираем работу epoll, отличия от select и poll, событийную модель и настройку Ng...