ServerAID
Найти гайд, команду, тег… ⌘ K
Сервер

systemd unit и systemctl enable: что делают, чем отличаются от start

Команда `systemctl enable` создаёт симлинки, чтобы сервис стартовал при загрузке системы. Разбираем разницу с `start`, шорткат `--now`, свой unit-файл с `Restart=always`, пользовательские сервисы и частые ошибки на Ubuntu 24.04 LTS.

systemctl enable: включаем сервис в автозагрузку и пишем свой unit

Команда systemctl enable создаёт симлинки, чтобы сервис стартовал при загрузке системы. Разбираем разницу с start, шорткат --now, свой unit-файл с Restart=always, пользовательские сервисы и частые ошибки на Ubuntu 24.04 LTS.

Различаем enable и start

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

  • systemctl start <service> — запускает сервис прямо сейчас, до ближайшей перезагрузки.
  • systemctl enable <service> — добавляет сервис в автозагрузку, но не стартует его в текущей сессии.
  • systemctl disable <service> — убирает из автозагрузки, но не останавливает текущий процесс.
  • systemctl stop <service> — останавливает текущий процесс, но не снимает автозагрузку.

Проверить состояние:

sudo systemctl is-active nginx     # запущен ли сейчас (active/inactive)
sudo systemctl is-enabled nginx    # будет ли запущен после ребута (enabled/disabled)
sudo systemctl status nginx        # подробный вывод

После apt install многие пакеты включают свой сервис автоматически — проверить можно через is-enabled. Вручную делать это нужно только для собственных юнитов.

Используем enable --now

Если нужно «включить и сразу запустить», есть короткий путь:

sudo systemctl enable --now nginx

Эквивалент двух команд:

sudo systemctl enable nginx
sudo systemctl start nginx

Симметрично работает disable --now — снимает автозагрузку и останавливает сервис одной строкой. Для скриптов первичной настройки сервера это самый чистый вариант: одно намерение — одна команда.

Что технически делает enable: создаёт симлинки в /etc/systemd/system/<target>.wants/, ссылаясь на unit-файл. Удалить можно вручную, но disable чище — он же подчищает зависимости.

Включаем системный сервис

Типовой кейс — поставили nginx, запустили его и хотите, чтобы он переживал ребуты:

sudo apt install -y nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx

Если сервис не стартует, первое, что смотрим — systemctl status и журнал:

sudo systemctl status nginx
sudo journalctl -u nginx -n 50 --no-pager

-u nginx фильтрует журнал по сервису, -n 50 — последние 50 строк. Для свежих логов — journalctl -u nginx -f (как tail -f).

Пишем свой systemd unit

Допустим, у нас есть Python-демон или Node.js-приложение, и его нужно держать всегда поднятым. Создаём unit-файл в /etc/systemd/system/:

# /etc/systemd/system/myapp.service
[Unit]
Description=My App backend
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/venv/bin/python -m myapp
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Минимальный набор полей, с которыми стоит разобраться:

  • Description — отображается в systemctl status и в journalctl.
  • After=network-online.target + Wants=network-online.target — стартовать после поднятия сети. Для веб-демонов это must-have, иначе процесс упадёт при попытке забиндить порт раньше сети.
  • Type=simple — по умолчанию, подходит для процессов, которые сами не форкаются. Для классики UNIX-демонов — Type=forking. Для systemd-native сервисов с уведомлением о готовности — Type=notify.
  • User/Group — от какого юзера крутится процесс. Никогда не оставляйте root без причины: создавайте отдельного системного пользователя через sudo adduser --system --no-create-home myapp.
  • EnvironmentFile — переменные окружения отдельным файлом. Удобно для секретов (DATABASE_URL=...), которые не хотим коммитить в unit.
  • ExecStart — абсолютный путь к бинарю и аргументы. Без шелл-сахара (&&, пайпы) — если нужен пайплайн, оборачивайте в bash -c.
  • Restart=always + RestartSec=5 — авторестарт через 5 секунд после падения. Альтернативы: on-failure (только при ненулевом коде), on-abnormal.
  • WantedBy=multi-user.target — на каком уровне работы система запустит сервис. Для обычных демонов — multi-user.

Применяем:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp

Применяем изменения через daemon-reload

Если поправили unit-файл — systemd об этом ещё не знает. Нужно перечитать конфиги:

sudo systemctl daemon-reload
sudo systemctl restart myapp

daemon-reload обновляет внутренний кэш systemd, restart — перезапускает уже запущенный процесс с новыми параметрами. Без daemon-reload после правок unit вы рискуете запустить сервис со старой конфигурацией и долго гадать, почему изменения не применились.

Хороший знак, что пора делать daemon-reload: после restart вы видите в systemctl status строку Warning: The unit file, source configuration file or drop-ins of <service>.service changed on disk.

Запускаем пользовательский сервис

Если демон должен крутиться от имени обычного пользователя (не системного root/www-data), и вам не хочется писать unit в /etc/systemd/system/ — есть user-сервисы. Они живут в ~/.config/systemd/user/:

mkdir -p ~/.config/systemd/user
$EDITOR ~/.config/systemd/user/sync.service

Содержимое аналогичное, но без User= (он подразумевается) и часто с WantedBy=default.target:

[Unit]
Description=Personal sync job

[Service]
Type=simple
ExecStart=%h/bin/sync.sh
Restart=on-failure

[Install]
WantedBy=default.target

%h — встроенная подстановка домашней директории пользователя. Включаем:

systemctl --user daemon-reload
systemctl --user enable --now sync.service
systemctl --user status sync.service

Без sudo — это ключевое отличие user-сервисов.

Важный нюанс: user-сервисы по умолчанию работают только пока пользователь залогинен. Чтобы они стартовали при загрузке и переживали логаут, включите linger:

sudo loginctl enable-linger $USER

Без этого после логаута systemd-user остановит все ваши --user-сервисы. Проверить можно через loginctl show-user $USER | grep Linger.

Что делает enable изнутри

Коротко: systemctl enable myapp.service создаёт симлинк в каталоге, который указан в секции [Install]. Для WantedBy=multi-user.target это:

/etc/systemd/system/multi-user.target.wants/myapp.service
  -> /etc/systemd/system/myapp.service

При загрузке systemd подхватывает multi-user.target и стартует все юниты из .wants/. Поэтому если в unit-файле нет секции [Install]enable выдаст ошибку Unit file ... does not contain Install section. Без [Install] юнит можно стартовать вручную (start), но нельзя поставить в автозагрузку.

Частые вопросы

Чем systemctl enable отличается от systemctl start

enable ставит сервис в автозагрузку, но не запускает его в текущей сессии. start запускает прямо сейчас, но не делает автозагрузку. Если нужно и то и другое одной командой — используйте systemctl enable --now <service>.

Что делает systemctl enable now

Флаг --now объединяет enable и start в одну команду: сервис добавляется в автозагрузку и запускается немедленно. Симметрично работает disable --now — отключает автозагрузку и останавливает текущий процесс.

Зачем нужен sudo systemctl enable

enable пишет симлинк в /etc/systemd/system/, куда обычный пользователь писать не может. Поэтому для системных сервисов нужен sudo. Для user-сервисов (которые лежат в ~/.config/systemd/user/) sudo не нужен — там команда выглядит как systemctl --user enable <service>.

Что делает systemctl daemon-reload

daemon-reload заставляет systemd перечитать unit-файлы с диска. Запускайте его после любой правки *.service-файла, иначе systemd будет работать со старой конфигурацией. После daemon-reload обычно нужен restart, чтобы изменения применились к работающему процессу.

Как сделать чтобы пользовательский сервис стартовал без логина

По умолчанию systemctl --user enable включает сервис только пока пользователь залогинен. Чтобы он стартовал при загрузке и работал после логаута — включите linger: sudo loginctl enable-linger $USER. После этого systemd-user-сессия живёт независимо от login-сессий.

Почему systemctl enable говорит No installation information

Ошибка Unit ... does not contain Install section означает, что в unit-файле нет секции [Install]. Для автозагрузки она обязательна — добавьте [Install]\nWantedBy=multi-user.target (или default.target для user-сервисов) и повторите daemon-reload + enable.

Что запомнить

  • enable — про автозагрузку, start — про текущую сессию. enable --now делает обе операции одной командой.
  • Свой unit лежит в /etc/systemd/system/<name>.service, обязательные секции — [Unit], [Service], [Install]. Без [Install] сервис нельзя enable.
  • После любой правки unit-файла — sudo systemctl daemon-reload, иначе изменения не подхватятся.
  • Для пользовательских демонов — systemctl --user enable, без sudo. Чтобы они переживали логаут, нужен loginctl enable-linger.
  • Логи смотрим через journalctl -u <service> — это первый шаг при любой проблеме со стартом.

Похожие материалы

snap — что это и зачем
Глоссарий

snap — что это и зачем

snap — система упаковки и установки приложений от Canonical, разработанная как альтернатива apt. Каждый snap — самодостаточный пакет со своими зависимостями, изолированный от системы через AppArmor. Используется на Ubuntu для Firefox, Chromium, microk8s и многих desktop-приложений.

Редакция
LVM — что это и зачем
Глоссарий

LVM — что это и зачем

LVM — слой абстракции между физическими дисками и файловыми системами в Linux. Объединяет диски в пулы (Volume Groups), нарезает их на логические тома (Logical Volumes) и позволяет изменять размер на лету. Альтернатива классическому partitioning, которая делает работу с дисками гибкой.

Редакция
swap — что это и зачем
Глоссарий

swap — что это и зачем

swap — пространство на диске, которое Linux использует как «продолжение» оперативной памяти, когда физической RAM не хватает. Бывает в виде отдельного swap-раздела или файла. На современных серверах с большим количеством RAM swap всё равно нужен — но не для скорости, а для устойчивости.

Редакция
chown — что это и зачем
Глоссарий

chown — что это и зачем

chown (change owner) — команда Linux для смены владельца и группы файла или каталога. Парная к chmod: chown управляет тем, **кому** принадлежит файл, chmod — тем, что **можно с ним делать**. Базовая команда деплоя: дать сервисному пользователю доступ к каталогу приложения.

Редакция