systemctl и systemd: как управлять службами в Linux

опубликовано
читать
≈ 9 мин
автор
среда и версия
Debian 12, systemd 252
содержание пройти тест Linux

systemd запускает службы Linux при загрузке и следит за ними, а systemctl — команда, которой ими управляют. systemctl status имя показывает, работает ли служба. start, stop и restart меняют её состояние сейчас, enable и disable — запустится ли она при следующей загрузке. Ниже всё это на живом выводе Debian 12: статус, своя служба, журнал и таймер вместо cron.

Linux / 01

start — сейчас, enable — при загрузке

start — сейчас, enable — при загрузкеКоманды systemctl меняют две разные вещи. start, stop и restart решают, работает ли служба сейчас: в systemctl status это строка Active: active (running). enable и disable решают, запустится ли служба при загрузке: это слово enabled в строке Loaded. enable --now делает оба сразу. daemon-reload перечитывает изменённые unit-файлы; без него systemctl предупреждает, что файл changed on disk.командачто меняетчто видноstart · stop · restartработает ли служба сейчасActive: active (running)enable · disableзапустится ли при загрузкеLoaded: …; enabledenable --nowоба сразуenabled + activedaemon-reloadперечитать unit-файлыбез него: changed on disk
Служба, которую только запустили, не переживёт перезагрузку, а включённая через enable не заработает до следующей загрузки. Чтобы и сразу, и потом, нужен enable --now.

Как прочитать systemctl status

Пример ниже — служба report: небольшое веб-приложение на Python, которое отвечает на порту 8080. Пока её не запускали, статус короткий:

systemctl status report
○ report.service - Report web app
     Loaded: loaded (/etc/systemd/system/report.service; disabled; preset: enabled)
     Active: inactive (dead)

После запуска появляются процесс и последние строки журнала:

sudo systemctl start report
systemctl status report
● report.service - Report web app
     Loaded: loaded (/etc/systemd/system/report.service; disabled; preset: enabled)
     Active: active (running) since Sun 2026-10-18 16:17:19 UTC; 1s ago
   Main PID: 70 (python3)
      Tasks: 1 (limit: 11517)
     Memory: 8.9M
        CPU: 27ms
     CGroup: /system.slice/report.service
             └─70 /usr/bin/python3 -u /opt/report/app.py

Oct 18 16:17:19 server systemd[1]: Started report.service - Report web app.
Oct 18 16:17:19 server python3[70]: report: listening on 8080

Главное — две строки. Loaded говорит, где лежит файл службы и включена ли она при загрузке: здесь disabled. Active говорит, что происходит сейчас: active (running), inactive (dead) или failed. Кружок в начале дублирует это значком: ● — работает, ○ — остановлена, × — упала. CGroup показывает дерево процессов службы, а внизу — последние строки её журнала.

Для скриптов есть короткие вопросы с ответом одним словом:

systemctl is-active report
systemctl is-enabled report
active
disabled

Код возврата у status тоже значимый: 0 — служба работает, 3 — не запущена, 4 — такой службы нет. Его удобно проверять в скриптах вместо разбора текста.

Запуск, остановка и перезапуск

start, stop и restart ничего не печатают, если всё прошло хорошо. Изменения состояния требуют прав root, поэтому на сервере их запускают через sudo:

sudo systemctl restart report
sudo systemctl stop report
systemctl status report
○ report.service - Report web app
     Loaded: loaded (/etc/systemd/system/report.service; enabled; preset: enabled)
     Active: inactive (dead) since Sun 2026-10-18 16:17:30 UTC; 4ms ago
   Duration: 3ms
    Process: 98 ExecStart=/usr/bin/python3 -u /opt/report/app.py (code=killed, signal=TERM)
   Main PID: 98 (code=killed, signal=TERM)
        CPU: 3ms

Oct 18 16:17:30 server systemd[1]: Started report.service - Report web app.
Oct 18 16:17:30 server systemd[1]: Stopping report.service - Report web app...
Oct 18 16:17:30 server systemd[1]: report.service: Deactivated successfully.
Oct 18 16:17:30 server systemd[1]: Stopped report.service - Report web app.

code=killed, signal=TERM — так выглядит остановка: systemd послал процессу сигнал SIGTERM. Что значат сигналы и почему программа может их перехватить, разобрано в материале о процессах и сигналах.

reload просит службу перечитать собственные настройки без перезапуска процесса. Работает он, только если служба это умеет, то есть в её файле описана команда перезагрузки. У нашего приложения такой команды нет:

sudo systemctl reload report
Failed to reload report.service: Job type reload is not applicable for unit report.service.

В таком случае нужен restart. Он останавливает процесс и запускает новый, поэтому на секунду служба недоступна.

Автозапуск: enable и disable

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

sudo systemctl enable report
Created symlink /etc/systemd/system/multi-user.target.wants/report.service → /etc/systemd/system/report.service.

disable убирает ссылку:

sudo systemctl disable report
Removed "/etc/systemd/system/multi-user.target.wants/report.service".

Чтобы включить автозапуск и сразу запустить службу, есть флаг --now. С disable он, наоборот, ещё и остановит её:

sudo systemctl enable --now report
systemctl is-active report
Created symlink /etc/systemd/system/multi-user.target.wants/report.service → /etc/systemd/system/report.service.
active

Главная мысль: start действует до перезагрузки, enable — начиная со следующей загрузки. Новую службу почти всегда включают командой enable --now.

Своя служба: unit-файл

Описание службы — текстовый unit-файл. Свои файлы кладут в /etc/systemd/system/, а файлы из пакетов лежат в /lib/systemd/system/. Вот весь /etc/systemd/system/report.service:

[Unit]
Description=Report web app
After=network.target

[Service]
User=dev
WorkingDirectory=/opt/report
ExecStart=/usr/bin/python3 -u /opt/report/app.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

Description — подпись, которую ты видишь в статусе и журнале. After=network.target просит запускать службу после настройки сети. User задаёт пользователя, от которого работает процесс: без этой строки служба запустится от root. WorkingDirectory — каталог, от которого считаются относительные пути. ExecStart — команда запуска, и путь к программе в ней пишут полностью. Restart=on-failure перезапускает процесс, если он упал. Строка WantedBy=multi-user.target в секции [Install] объясняет, где появится ссылка после enable. Флаг -u у Python выключает буферизацию вывода, чтобы строки сразу попадали в журнал.

Новый файл systemd подхватит при первом start. А вот правку уже загруженного файла он сам не заметит. Допустим, в ExecStart попала опечатка pyhton3, и службу перезапустили без перечитывания:

sudo systemctl restart report
systemctl is-active report
Warning: The unit file, source configuration file or drop-ins of report.service changed on disk. Run 'systemctl daemon-reload' to reload units.
active

Служба работает, но со старой версией файла. Новая вступает в силу только после daemon-reload, и тогда опечатка ломает запуск:

sudo systemctl daemon-reload
sudo systemctl restart report
systemctl status report
× report.service - Report web app
     Loaded: loaded (/etc/systemd/system/report.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Sun 2026-10-18 16:17:52 UTC; 1s ago
   Duration: 535us
    Process: 166 ExecStart=/usr/bin/pyhton3 -u /opt/report/app.py (code=exited, status=203/EXEC)
   Main PID: 166 (code=exited, status=203/EXEC)
        CPU: 560us

Oct 18 16:17:52 server systemd[1]: report.service: Scheduled restart job, restart counter is at 5.
Oct 18 16:17:52 server systemd[1]: Stopped report.service - Report web app.
Oct 18 16:17:52 server systemd[1]: report.service: Start request repeated too quickly.
Oct 18 16:17:52 server systemd[1]: report.service: Failed with result 'exit-code'.
Oct 18 16:17:52 server systemd[1]: Failed to start report.service - Report web app.

Обрати внимание: сам restart ошибки не показал. По умолчанию у службы Type=simple, и systemd считает её запущенной сразу после создания процесса, ещё до того, как выяснится, что программы нет. Если добавить в секцию [Service] строку Type=exec, systemd дождётся запуска программы, и та же опечатка сломает уже саму команду:

sudo systemctl restart report
Job for report.service failed because the control process exited with error code.
See "systemctl status report.service" and "journalctl -xeu report.service" for details.

Чужой файл службы, например из пакета, лучше не править на месте: обновление пакета перезапишет правку. Добавки кладут в отдельный файл /etc/systemd/system/report.service.d/override.conf — его же создаёт команда sudo systemctl edit report. systemctl cat показывает итог, исходный файл и добавку вместе:

systemctl cat report
# /etc/systemd/system/report.service
[Unit]
Description=Report web app
After=network.target

[Service]
User=dev
WorkingDirectory=/opt/report
ExecStart=/usr/bin/python3 -u /opt/report/app.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/report.service.d/override.conf
[Service]
Environment=REPORT_LIMIT=500

Журнал службы: journalctl

Всё, что служба печатает, и всё, что systemd делает с ней, попадает в журнал. Читать его по одной службе — journalctl -u:

journalctl -u report -n 3
Oct 18 16:18:46 server systemd[1]: Started report.service - Report web app.
Oct 18 16:18:46 server python3[284]: report: listening on 8080
Oct 18 16:18:47 server python3[284]: 127.0.0.1 - - [18/Oct/2026 16:18:47] "GET / HTTP/1.1" 200 -

Первая строка от systemd, две следующие напечатало само приложение, в том числе строку о запросе. -n 3 ограничивает вывод тремя последними строками. Ещё пригодятся -f, чтобы смотреть новые строки по мере появления, -b — только с последней загрузки, --since "1 hour ago" — за последний час. Сочетание -xeu имя из подсказки systemctl открывает конец журнала службы с пояснениями.

Таймер вместо cron

Задачу по расписанию systemd запускает парой файлов: служба с командой и таймер с расписанием. Служба report-cleanup.service удаляет файлы старше семи дней:

[Unit]
Description=Delete report files older than 7 days

[Service]
Type=oneshot
User=dev
ExecStart=/usr/bin/find /opt/report/tmp -type f -mtime +7 -print -delete

Type=oneshot значит, что команда отрабатывает и завершается, а не висит постоянно. Таймер с тем же именем, report-cleanup.timer, запускает её каждый день в 3:00:

[Unit]
Description=Daily report cleanup

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

Включают таймер, а не службу:

sudo systemctl enable --now report-cleanup.timer
systemctl list-timers report-cleanup.timer
Created symlink /etc/systemd/system/timers.target.wants/report-cleanup.timer → /etc/systemd/system/report-cleanup.timer.
NEXT                        LEFT     LAST PASSED UNIT                 ACTIVATES
Mon 2026-10-19 03:00:00 UTC 10h left -    -      report-cleanup.timer report-cleanup.service

1 timers listed.
Pass --all to see loaded but inactive timers, too.

Проверить задачу, не дожидаясь трёх часов ночи, можно, запустив службу вручную. Результат виден в её журнале:

sudo systemctl start report-cleanup.service
journalctl -u report-cleanup -n 4
Oct 18 16:18:58 server systemd[1]: Starting report-cleanup.service - Delete report files older than 7 days...
Oct 18 16:18:58 server find[351]: /opt/report/tmp/old.csv
Oct 18 16:18:58 server systemd[1]: report-cleanup.service: Deactivated successfully.
Oct 18 16:18:58 server systemd[1]: Finished report-cleanup.service - Delete report files older than 7 days.

Выражение для OnCalendar проверяет systemd-analyze calendar: оно показывает полную форму и ближайший запуск. Будни в 9 утра:

systemd-analyze calendar "Mon..Fri 09:00"
  Original form: Mon..Fri 09:00
Normalized form: Mon..Fri *-*-* 09:00:00
    Next elapse: Mon 2026-10-19 09:00:00 UTC
       From now: 16h left

Чем таймер лучше строки в crontab: вывод сам попадает в журнал, ошибки видны в systemctl status, а Persistent=true запускает пропущенную задачу, если сервер был выключен в момент срабатывания. Цена — два файла вместо одной строки.

Ошибки, на которых спотыкаются

System has not been booted with systemd. Так отвечает systemctl там, где systemd не первый процесс системы: в обычном контейнере Docker или в WSL без systemd.

systemctl status ssh
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

Управлять тут нечем: в контейнере программу запускают напрямую, основным процессом контейнера.

Unit не найден. Опечатка в имени или файл лежит не там. Команда завершается с кодом 4:

systemctl status reprot
Unit reprot.service could not be found.

status=203/EXEC. systemd не смог запустить программу из ExecStart: файла нет или у него нет права на выполнение. Причина видна в журнале:

Oct 18 16:17:52 server (pyhton3)[166]: report.service: Failed to locate executable /usr/bin/pyhton3: No such file or directory
Oct 18 16:17:52 server (pyhton3)[166]: report.service: Failed at step EXEC spawning /usr/bin/pyhton3: No such file or directory
Oct 18 16:17:52 server systemd[1]: report.service: Main process exited, code=exited, status=203/EXEC

status=217/USER. Пользователя из строки User= нет в системе. В общем журнале загрузки, journalctl -b, это выглядит так:

Oct 18 16:18:18 server (python3)[230]: report.service: Failed to determine user credentials: No such process

Start request repeated too quickly. Служба с Restart=on-failure падала снова и снова, и systemd перестал её запускать. По умолчанию разрешено пять запусков за 10 секунд — это видно в systemctl show report -p StartLimitBurst -p StartLimitIntervalUSec. После исправления причины сбрось счётчик и запусти службу заново:

sudo systemctl daemon-reload
sudo systemctl reset-failed report
sudo systemctl start report

Правка файла не применилась. systemctl предупреждает changed on disk и работает со старой версией. Нужен sudo systemctl daemon-reload, потом restart.

Служба пропала после перезагрузки. Её запустили через start, но не включили через enable. Проверка — systemctl is-enabled имя.

Job failed because the control process exited with error code. Это общее сообщение, а не причина. Причину ищи в systemctl status имя и journalctl -xeu имя.

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

Чем restart отличается от reload

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

Как посмотреть все работающие службы

systemctl list-units --type=service --state=running
  UNIT                     LOAD   ACTIVE SUB     DESCRIPTION
  dbus.service             loaded active running D-Bus System Message Bus
  report.service           loaded active running Report web app
  systemd-journald.service loaded active running Journal Service
  systemd-logind.service   loaded active running User Login Management

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.
4 loaded units listed.

Упавшие службы показывает systemctl --failed, включённые в автозапуск — systemctl list-unit-files --state=enabled.

Где лежит файл службы

Первая строка systemctl status и заголовки в systemctl cat показывают путь. Свои службы держи в /etc/systemd/system/, файлы пакетов в /lib/systemd/system/ не правь.

Где потренироваться

Службы и таймеры — тема в карте навыков DevOps, рядом с правами, процессами и доступом по SSH. Проверить себя по Linux можно в тесте навыков: 8 вопросов, баллы видны без регистрации. Как попасть на сервер, где всё это запускается, разобрано в материале о подключении по SSH.

Источники