systemd: свой сервис для скрипта и логи через journalctl
Как управлять службами через systemctl, написать свой сервис для скрипта или Python-бота с автозапуском и перезапуском, заменить cron таймером systemd и читать логи через journalctl. Команды, разбор вывода и частые ошибки.
Содержание
- 1Что такое unit и где они лежат
- 2Управление службами: systemctl
- Запуск, остановка, перезапуск
- Автозапуск при загрузке
- Состояние службы
- Короткие проверки для скриптов
- Что сломалось
- 3Свой сервис для скрипта или Python-бота
- Файл юнита
- Проверка и запуск
- Сервис для обычного скрипта
- simple или oneshot
- Как поправить юнит, не создавая файл вручную
- 4Таймеры systemd вместо cron
- Как проверить расписание
- 5Пользовательские сервисы
- 6Логи: journalctl
- Основные ключи
- Сколько места занимает журнал
- 7Что тормозит загрузку: systemd-analyze
- 8Шпаргалка
- 9Частые ошибки
- 10Чек-лист
- 11Частые вопросы
- Чем start отличается от enable?
- Где лежат логи systemd?
- Как удалить свою службу?
- Почему systemctl пишет «System has not been booted with systemd as init system»?
- Что лучше: таймер systemd или cron?
- Можно ли запустить несколько копий одной службы?
- Как сделать, чтобы служба перезапускалась всегда, даже после нормального выхода?
- Нужно ли перезапускать службу после изменения скрипта?
- 12Что дальше
Рано или поздно на сервере появляется что-то своё: Telegram-бот на Python, скрипт резервного копирования, небольшой веб-сервис. Запустить его в терминале просто, но стоит закрыть SSH — и он умирает. После перезагрузки его нужно запускать руками, а если он упал ночью, никто об этом не узнает.
Всё это решает systemd — менеджер служб, который есть в Ubuntu, Debian, Fedora и почти во всех современных дистрибутивах. Он запускает программы при загрузке, перезапускает их после падения, собирает их вывод в единый журнал и умеет запускать задачи по расписанию вместо cron.
Ниже покажу, как управлять службами через systemctl, как написать свой сервис из десятка строк, как сделать таймер и как читать логи через journalctl. Все команды — для Ubuntu, но в других дистрибутивах с systemd они те же.
Что такое unit и где они лежат
В systemd всё, чем он управляет, называется unit (юнит). У каждого юнита есть тип — он виден по расширению файла:
.service— служба: программа или скрипт;.timer— таймер, который запускает службу по расписанию;.socket,.mount,.targetи другие — сокеты, точки монтирования, группы юнитов.
Файлы юнитов лежат в трёх местах:
/usr/lib/systemd/system/(он же/lib/systemd/system/) — юниты из пакетов. Руками их не правят: обновление пакета затрёт изменения./etc/systemd/system/— ваши юниты и переопределения. Файл здесь имеет приоритет над одноимённым из/usr/lib.~/.config/systemd/user/— пользовательские юниты, о них ниже.
Посмотреть, из какого файла загружен юнит и что в нём написано, можно командой:
systemctl cat ssh.serviceПервой строкой команда выводит путь к файлу, дальше — его содержимое вместе со всеми переопределениями.
Управление службами: systemctl
Чтобы запускать и останавливать службы, нужны права root, поэтому команды идут через sudo. Смотреть состояние можно и без него. Если с правами пока путаница, загляните в статью про root и sudo в Ubuntu.
Запуск, остановка, перезапуск
sudo systemctl start nginx # запустить
sudo systemctl stop nginx # остановить
sudo systemctl restart nginx # остановить и запустить заново
sudo systemctl reload nginx # перечитать конфиг без остановкиreload поддерживают не все службы: веб-серверы умеют, а ваш скрипт — скорее всего нет. Если не уверены, используйте restart. Расширение .service в командах можно не писать — systemd подставит его сам.
Автозапуск при загрузке
start запускает службу только сейчас. Чтобы она стартовала после перезагрузки, её нужно включить:
sudo systemctl enable nginx # включить автозапуск
sudo systemctl disable nginx # выключить автозапуск
sudo systemctl enable --now nginx # включить и сразу запустить
sudo systemctl disable --now nginx # выключить и сразу остановитьКлюч --now экономит одну команду и избавляет от частой ошибки: включили автозапуск, а запустить забыли — и до перезагрузки служба не работает.
enable создаёт символическую ссылку на файл юнита — это видно в выводе:
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.Состояние службы
Главная команда для диагностики:
systemctl status nginx● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sun 2026-10-11 10:12:41 MSK; 2h 5min ago
Docs: man:nginx(8)
Main PID: 812 (nginx)
Tasks: 5 (limit: 9387)
Memory: 6.1M (peak: 7.4M)
CPU: 143ms
CGroup: /system.slice/nginx.service
├─812 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
└─813 "nginx: worker process"
окт 11 10:12:41 server systemd[1]: Starting nginx.service - A high performance web server...
окт 11 10:12:41 server systemd[1]: Started nginx.service - A high performance web server...На что смотреть:
- Loaded — путь к файлу юнита и
enabled/disabled, то есть включён ли автозапуск; - Active — текущее состояние:
active (running)— работает,inactive (dead)— остановлена,failed— упала,activating (auto-restart)— упала и ждёт перезапуска; - Main PID — номер главного процесса;
- последние строки — хвост журнала службы. Чаще всего причина падения видна прямо здесь.
Если вывод не помещается, status открывает его в пейджере — выход по Q. Чтобы вывести всё сразу, добавьте --no-pager, а чтобы строки не обрезались по ширине терминала — -l.
Короткие проверки для скриптов
Для условий в скриптах удобнее команды, которые отвечают одним словом и кодом возврата:
systemctl is-active nginx
systemctl is-enabled nginxactive
enabledКод возврата 0 означает «да». Поэтому можно писать так: systemctl is-active --quiet nginx || echo "nginx лежит". Ключ --quiet убирает вывод и оставляет только код.
Что сломалось
Список всех упавших юнитов:
systemctl list-units --failed UNIT LOAD ACTIVE SUB DESCRIPTION
● mybot.service loaded failed failed Telegram-бот NixLife
1 loaded units listed.Если список пуст — всё в порядке. После того как причину устранили, состояние failed сбрасывается командой sudo systemctl reset-failed mybot. Все запущенные службы показывает systemctl list-units --type=service, а все установленные файлы юнитов вместе с состоянием автозапуска — systemctl list-unit-files --type=service.
Свой сервис для скрипта или Python-бота
Допустим, у вас есть бот в /opt/mybot/bot.py с виртуальным окружением в /opt/mybot/venv, а токен лежит в файле /opt/mybot/.env. Запускать его будем от отдельного пользователя nixlife, а не от root.
Файл юнита
Создайте файл:
sudo nano /etc/systemd/system/mybot.serviceИ вставьте:
[Unit]
Description=Telegram-бот NixLife
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=nixlife
WorkingDirectory=/opt/mybot
ExecStart=/opt/mybot/venv/bin/python /opt/mybot/bot.py
Restart=on-failure
RestartSec=5
EnvironmentFile=/opt/mybot/.env
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.targetРазберу по строкам.
Секция [Unit] — описание и зависимости:
Description— название, которое видно вstatusи в журнале;After=network-online.target— запускать после того, как сеть поднята. Без этого бот при загрузке может стартовать раньше сети и упасть на первом же запросе;Wants=network-online.target— заодно попросить systemd дождаться сети.Afterзадаёт только порядок, аWants— саму зависимость, поэтому их ставят парой.
Секция [Service] — как запускать:
Type=simple— программа работает, пока работает служба. Это значение по умолчанию, подходит для ботов и большинства скриптов с бесконечным циклом;User— от чьего имени запускать. Если не указать, служба работает от root;WorkingDirectory— рабочий каталог. Относительные пути внутри скрипта (open("config.json")) будут считаться от него;ExecStart— команда запуска. Путь к программе — полный. Python берём из виртуального окружения, тогда активировать его не нужно;Restart=on-failure— перезапускать, если процесс завершился с ошибкой или был убит. Другие варианты:always— перезапускать всегда, даже после нормального выхода;no— никогда (по умолчанию);RestartSec=5— пауза перед перезапуском, чтобы при постоянной ошибке служба не перезапускалась без остановки;EnvironmentFile— файл с переменными окружения в форматеИМЯ=значение, по одной на строку. Сюда кладут токены и пароли;Environment— переменная прямо в юните.PYTHONUNBUFFERED=1заставляет Python сразу отдаватьprint()в журнал, иначе вывод копится в буфере и появляется с большой задержкой.
Секция [Install] — куда «вешать» службу при enable. WantedBy=multi-user.target означает «при обычной загрузке системы». Для серверных служб это стандартное значение.
Проверка и запуск
Перед запуском файл стоит проверить:
sudo systemd-analyze verify /etc/systemd/system/mybot.serviceЕсли всё в порядке, команда ничего не выводит. Если есть ошибка — укажет строку. Вот реальный вывод для юнита, где ExecStart записан с относительным путём ./bot.py:
mybot.service:10: Neither a valid executable name nor an absolute path: ./bot.py
mybot.service: Unit configuration has fatal error, unit will not be started.
Unit mybot.service has a bad unit file setting.А так выглядит ошибка, когда программы по указанному пути нет — например, забыли создать виртуальное окружение:
mybot.service: Command /opt/mybot/venv/bin/python is not executable: No such file or directoryОпечатку в значении verify тоже заметит. Здесь вместо on-failure написано sometimes:
mybot.service:11: Failed to parse service restart specifier, ignoring: sometimesОбратите внимание на слово ignoring: с такой опечаткой служба запустится, но перезапускаться не будет. Без проверки это легко пропустить.
Теперь главное — сообщить systemd о новом файле и запустить службу:
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
systemctl status mybotdaemon-reload заставляет systemd перечитать файлы юнитов. Его нужно выполнять после каждой правки .service или .timer, иначе systemd продолжит работать со старой версией. Если забыть, status об этом напомнит строкой Warning: The unit file, source configuration file or drop-ins of mybot.service changed on disk. Run 'systemctl daemon-reload' to reload units.
После изменения кода самого бота daemon-reload не нужен — достаточно sudo systemctl restart mybot.
Сервис для обычного скрипта
Если это bash-скрипт, всё то же самое, только ExecStart указывает на сам скрипт:
ExecStart=/usr/local/bin/myscript.shУ скрипта должны быть две вещи: первая строка-shebang #!/bin/bash и право на исполнение sudo chmod +x /usr/local/bin/myscript.sh. Без них служба упадёт с ошибкой 203/EXEC. Другой вариант — явно указать интерпретатор: ExecStart=/bin/bash /usr/local/bin/myscript.sh.
simple или oneshot
Тип службы зависит от того, как ведёт себя программа:
Type=simple— программа работает постоянно: бот, веб-сервер, циклwhile true. Пока процесс жив, службаactive (running).Type=oneshot— программа делает дело и завершается: резервная копия, очистка, отправка отчёта. systemd ждёт её окончания и считает успехом код выхода0. После этого служба переходит вinactive (dead)— и это нормально.
Если скрипт, который быстро завершается, оформить как simple с Restart=always, systemd будет перезапускать его снова и снова. Через несколько попыток сработает защита от зацикливания, и служба окажется в failed с пометкой start-limit-hit.
Как поправить юнит, не создавая файл вручную
Есть два удобных способа:
sudo systemctl edit --full mybot # открыть весь файл юнита в редакторе
sudo systemctl edit nginx # создать переопределение (drop-in)Второй вариант нужен для юнитов из пакетов: он создаёт /etc/systemd/system/nginx.service.d/override.conf, куда вы пишете только изменённые строки. Обновление пакета их не затрёт. После systemctl edit делать daemon-reload не нужно — команда выполнит его сама.
Таймеры systemd вместо cron
Таймер — это юнит, который по расписанию запускает одноимённую службу. По сравнению с cron у него три плюса: вывод попадает в журнал, видно время последнего и следующего запуска, а пропущенный из-за выключения запуск можно выполнить при включении.
Нужно два файла. Служба /etc/systemd/system/backup.service:
[Unit]
Description=Резервная копия /srv/data
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.shИ таймер с тем же именем /etc/systemd/system/backup.timer:
[Unit]
Description=Ежедневный запуск резервной копии
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=10min
[Install]
WantedBy=timers.targetOnCalendar— расписание в форматедень_недели год-месяц-день часы:минуты:секунды, звёздочка означает «любой»;Persistent=true— если в 03:00 компьютер был выключен, задача выполнится сразу после включения;RandomizedDelaySec— случайная задержка до 10 минут, чтобы несколько задач не стартовали в одну секунду.
У службы нет секции [Install]: включать её не нужно, её запускает таймер. Включают именно таймер:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timerОба файла можно проверить одной командой — systemd-analyze verify backup.timer backup.service. Список всех таймеров:
systemctl list-timersNEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-10-12 03:04:12 MSK 7h Sun 2026-10-11 03:07:55 MSK 16h ago backup.timer backup.service
Mon 2026-10-12 06:41:30 MSK 10h Sun 2026-10-11 06:12:01 MSK 13h ago apt-daily-upgrade.timer apt-daily-upgrade.service
2 timers listed.Колонки NEXT и LAST — следующий и последний запуск. Добавьте --all, чтобы увидеть и неактивные таймеры. Чтобы запустить задачу прямо сейчас, не дожидаясь расписания, запустите службу: sudo systemctl start backup.service.
Как проверить расписание
Формат OnCalendar непривычен, но его не нужно угадывать: systemd-analyze calendar покажет, когда выражение сработает. Эта команда работает даже там, где systemd не запущен. Реальный вывод:
systemd-analyze calendar "Mon..Fri 09:00" "*:0/15" daily Original form: Mon..Fri 09:00
Normalized form: Mon..Fri *-*-* 09:00:00
Next elapse: Mon 2026-10-12 09:00:00 MSK
(in UTC): Mon 2026-10-12 06:00:00 UTC
From now: 13h left
Original form: *:0/15
Normalized form: *-*-* *:00/15:00
Next elapse: Sun 2026-10-11 20:00:00 MSK
(in UTC): Sun 2026-10-11 17:00:00 UTC
From now: 2min 45s left
Original form: daily
Normalized form: *-*-* 00:00:00
Next elapse: Mon 2026-10-12 00:00:00 MSK
(in UTC): Sun 2026-10-11 21:00:00 UTC
From now: 4h 2min leftNormalized form — как systemd понял выражение, Next elapse — ближайшее срабатывание. Чтобы увидеть несколько следующих запусков, добавьте --iterations=3:
systemd-analyze calendar --iterations=3 "Sun *-*-* 04:30" Original form: Sun *-*-* 04:30
Normalized form: Sun *-*-* 04:30:00
Next elapse: Sun 2026-10-18 04:30:00 MSK
(in UTC): Sun 2026-10-18 01:30:00 UTC
From now: 6 days left
Iteration #2: Sun 2026-10-25 04:30:00 MSK
(in UTC): Sun 2026-10-25 01:30:00 UTC
From now: 1 week 6 days left
Iteration #3: Sun 2026-11-01 04:30:00 MSK
(in UTC): Sun 2026-11-01 01:30:00 UTC
From now: 2 weeks 6 days leftНесколько готовых выражений: hourly — каждый час, daily — в полночь, weekly — в понедельник в полночь, *:0/15 — каждые 15 минут, Mon..Fri 09:00 — по будням в 9 утра, *-*-01 02:00 — первого числа каждого месяца.
Пользовательские сервисы
Если у вас нет root или служба нужна только вам, её можно запустить в пользовательском экземпляре systemd. Файл кладут в ~/.config/systemd/user/, а в командах добавляют --user — без sudo:
mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/mybot.service
systemctl --user daemon-reload
systemctl --user enable --now mybot
journalctl --user -u mybot -fДва отличия от системных служб:
- строка
User=не нужна — служба и так работает от вас; - в
[Install]пишутWantedBy=default.target, а неmulti-user.target.
Есть важная тонкость. По умолчанию пользовательские службы запускаются при входе в систему и останавливаются, когда вы выходите из последнего сеанса — например, закрываете SSH. Чтобы они работали всегда и стартовали при загрузке без входа, включите «задержку» (linger):
sudo loginctl enable-linger nixlifeПроверить можно командой loginctl show-user nixlife --property=Linger — должно быть Linger=yes.
Логи: journalctl
Всё, что служба пишет в стандартный вывод и в поток ошибок, systemd сохраняет в журнал. print() в Python, echo в bash — всё оказывается там с отметкой времени. Читается журнал командой journalctl. Свои логи пользователь видит и так, а чтобы читать журналы системных служб, нужен sudo или членство в группе adm.
Основные ключи
journalctl -u mybot # журнал одной службы
journalctl -u mybot -f # следить в реальном времени
journalctl -u mybot -n 50 # последние 50 строк
journalctl -u mybot -b # только с последней загрузки
journalctl -u mybot -b -1 # за предыдущую загрузку
journalctl -u mybot --since "1 hour ago"
journalctl -u mybot --since today
journalctl --since "2026-10-11 09:00" --until "2026-10-11 10:00"
journalctl -p err -b # только ошибки с последней загрузки
journalctl -u mybot -o cat --no-pager # чистый текст без пейджераЧто делает каждый ключ:
-u— фильтр по юниту. Можно указать несколько:-u nginx -u mybot;-f— показывать новые строки по мере появления, какtail -f. Выход — Ctrl + C;-n— сколько последних строк вывести;-b— с текущей загрузки,-b -1— с предыдущей. Список загрузок —journalctl --list-boots. Это работает, только если журнал хранится на диске; в Ubuntu так и есть по умолчанию;--sinceи--until— интервал. Понимаютtoday,yesterday,"1 hour ago","30 min ago"и точные даты;-p— минимальный уровень важности:emerg,alert,crit,err,warning,notice,info,debug.-p errпокажет ошибки и всё, что серьёзнее;-o cat— только текст сообщений, без даты, хоста и имени процесса. Удобно, чтобы скопировать вывод бота или передать его вgrep;--no-pager— вывести всё сразу, без пролистывания. Нужен в скриптах;-e— открыть журнал сразу в конце,-r— показать новые записи первыми.
Обычный вывод выглядит так:
journalctl -u mybot -n 5окт 11 14:02:10 server systemd[1]: Started mybot.service - Telegram-бот NixLife.
окт 11 14:02:11 server python[2741]: Бот запущен, ожидаю сообщения
окт 11 14:20:37 server python[2741]: Traceback (most recent call last):
окт 11 14:20:37 server python[2741]: File "/opt/mybot/bot.py", line 42, in <module>
окт 11 14:20:37 server systemd[1]: mybot.service: Main process exited, code=exited, status=1/FAILUREСлева дата, имя хоста, процесс и его PID, справа — сообщение. Строки от systemd[1] — это события самой службы: запуск, падение, перезапуск. По ним видно, с каким кодом процесс завершился.
Сколько места занимает журнал
journalctl --disk-usageArchived and active journals take 312.5M in the file system.По умолчанию журнал занимает не больше 10% файловой системы и не больше 4 ГБ. Освободить место можно вручную:
sudo journalctl --vacuum-size=200M # оставить не больше 200 МБ
sudo journalctl --vacuum-time=2weeks # удалить записи старше двух недельЧистятся только архивные файлы журнала, текущий не трогается, поэтому итоговый размер может оказаться чуть больше заданного. Чтобы ограничение действовало постоянно, откройте /etc/systemd/journald.conf, раскомментируйте строку SystemMaxUse= и задайте, например, SystemMaxUse=500M. Затем перезапустите журнал командой sudo systemctl restart systemd-journald. Если место на диске заканчивается и непонятно, куда оно ушло, поможет статья про свободное место на диске в Linux.
Что тормозит загрузку: systemd-analyze
systemd запускает службы параллельно и знает, сколько ушло на каждую. Общее время загрузки:
systemd-analyzeStartup finished in 4.112s (firmware) + 2.031s (loader) + 1.874s (kernel) + 9.640s (userspace) = 17.658s
graphical.target reached after 9.581s in userspace.Самые долгие службы — первыми:
systemd-analyze blame | head6.012s systemd-networkd-wait-online.service
1.204s snapd.seeded.service
843ms apt-daily-upgrade.service
512ms dev-sda2.device
318ms systemd-journal-flush.service
247ms nginx.serviceЦифры показывают, сколько стартовала каждая служба, но не то, сколько из-за неё ждала система — многие запускаются одновременно. Цепочку, которая реально задерживает загрузку, показывает systemd-analyze critical-chain. Частый лидер на серверах — systemd-networkd-wait-online.service: она ждёт, пока поднимутся все сетевые интерфейсы, и если какой-то из них не подключён, висит до таймаута.
Шпаргалка
| Команда | Что делает |
|---|---|
systemctl status имя | Состояние службы и хвост журнала |
sudo systemctl start / stop / restart имя | Запустить, остановить, перезапустить |
sudo systemctl enable --now имя | Включить автозапуск и сразу запустить |
sudo systemctl disable --now имя | Выключить автозапуск и остановить |
systemctl is-active / is-enabled имя | Короткий ответ для скриптов |
systemctl list-units --failed | Все упавшие юниты |
systemctl cat имя | Показать файл юнита |
sudo systemctl edit --full имя | Отредактировать юнит |
sudo systemctl daemon-reload | Перечитать файлы после правки |
systemd-analyze verify файл | Проверить юнит на ошибки |
systemctl list-timers | Таймеры: последний и следующий запуск |
systemd-analyze calendar "выражение" | Проверить расписание OnCalendar |
journalctl -u имя -f | Журнал службы в реальном времени |
journalctl -p err -b | Ошибки с последней загрузки |
journalctl --since "1 hour ago" | Записи за последний час |
sudo journalctl --vacuum-size=200M | Ужать журнал |
systemd-analyze blame | Что дольше всего стартует |
Частые ошибки
Если служба не запускается, начните с systemctl status имя и journalctl -u имя -n 50. В строке Main process exited будет код, по которому почти всегда понятна причина.
Относительные пути. ExecStart=python3 bot.py или ExecStart=./bot.py — плохая идея. Имя программы без пути systemd ищет в стандартных каталогах и найдёт системный Python, а не тот, что в виртуальном окружении. Путь с ./ или ~ он вообще не примет. Пишите полные пути и к интерпретатору, и к скрипту. Внутри скрипта относительные пути считаются от WorkingDirectory, а если она не задана — от корня /.
Нет прав. Служба работает от пользователя из User=, а не от вас. Если ему не хватает прав на чтение файлов или запись в каталог, будет Permission denied в журнале. Если такого пользователя нет вовсе — код 217/USER, если не существует WorkingDirectory — 200/CHDIR.
Забыли daemon-reload. Поправили файл, сделали restart, а ничего не изменилось — systemd работает со старой версией. После любой правки юнита: sudo systemctl daemon-reload, потом restart.
Скрипт без shebang или без права на исполнение. Код 203/EXEC и в журнале Exec format error или Permission denied. Добавьте в первую строку #!/bin/bash (или #!/usr/bin/env python3) и выполните chmod +x. systemd-analyze verify такую проблему ловит заранее: Command /usr/local/bin/myscript.sh is not executable: Permission denied.
Служба сразу выходит. Если скрипт отработал и завершился, а status показывает inactive (dead) — для Type=simple это значит, что программа закончилась. Для разовых задач поставьте Type=oneshot. Если же программа должна работать постоянно, ищите причину выхода в журнале. Ещё один вариант — скрипт сам уходит в фон через & или nohup. В службе так делать не нужно: systemd сам держит процесс.
Бот молчит в журнале. Python буферизует вывод, когда пишет не в терминал. Добавьте Environment=PYTHONUNBUFFERED=1 или запускайте с ключом -u.
Нет переменных окружения. У службы нет вашего ~/.bashrc и переменных из сеанса. Всё нужное передавайте через Environment= или EnvironmentFile=.
Чек-лист
Частые вопросы
Чем start отличается от enable?
start запускает службу сейчас и до перезагрузки. enable включает автозапуск при загрузке, но сам по себе службу не запускает. Чтобы сделать и то и другое, используйте enable --now.
Где лежат логи systemd?
В двоичных файлах журнала в /var/log/journal/. Читать их нужно через journalctl, а не текстовым редактором. Если этого каталога нет, журнал хранится только в памяти в /run/log/journal/ и пропадает при перезагрузке.
Как удалить свою службу?
Остановите и выключите её: sudo systemctl disable --now mybot. Затем удалите файл /etc/systemd/system/mybot.service, выполните sudo systemctl daemon-reload и при необходимости sudo systemctl reset-failed.
Почему systemctl пишет «System has not been booted with systemd as init system»?
Вы внутри контейнера Docker или WSL, где systemd не запущен как первый процесс. Службы там запускают по-другому — средствами самого контейнера. На обычном сервере и в виртуальной машине этой ошибки нет. Например, в LXC-контейнерах Proxmox systemd работает как обычно.
Что лучше: таймер systemd или cron?
Для серверных задач — таймер: логи в журнале, видно последний и следующий запуск, есть Persistent=true. Для одной простой строки быстрее cron, его выражения удобно собирать в генераторе cron.
Можно ли запустить несколько копий одной службы?
Да, через шаблоны: файл называется mybot@.service, а внутри вместо изменяемой части пишут %i. Запуск — systemctl start mybot@first mybot@second, и %i заменится на first и second.
Как сделать, чтобы служба перезапускалась всегда, даже после нормального выхода?
Поставьте Restart=always. Но если программа выходит сразу после запуска, systemd после нескольких быстрых перезапусков остановится с ошибкой start-limit-hit — сначала разберитесь, почему она выходит.
Нужно ли перезапускать службу после изменения скрипта?
Да: sudo systemctl restart имя. Запущенный процесс продолжает работать со старым кодом. А daemon-reload нужен только при правке самого файла .service.
Что дальше
Свой сервис — обычно следующий шаг после установки Ubuntu Server и базовой защиты. Если сервис нужно держать запущенным в терминале только на время отладки, удобнее tmux: сессия переживёт отключение SSH, а когда всё заработает, остаётся перенести запуск в systemd.
Если статья пригодилась — отметьте, это помогает выбирать темы
Статья помогла?
Комментарии
Пока никто не написал. Будьте первым — вопрос или свой опыт одинаково полезны.