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>— это первый шаг при любой проблеме со стартом.