Почему стоит перейти на ==`systemd`== вместо скриптов: - Более надёжная демонизация. - Автоматический перезапуск при падении. - Логи сохраняются через journalctl. - Возможность ограничения ресурсов (CPU, память). - Красивое управление (`start`, stop, restart, `status`). #### ▪️ Правильный systemd-юнит для сервиса: vim /etc/systemd/system/myapp.service: ```sh [Unit] Description=MyApp Server After=network.target [Service] Type=simple ExecStart=/opt/myapp/server Restart=always RestartSec=5 WorkingDirectory=/opt/myapp/ StandardOutput=append:/var/log/myapp/server.log # Каталог и файл должны существовать!!! StandardError=append:/var/log/myapp/server_error.log # Каталог и файл должны существовать!!! User=appuser Group=appuser Environment=ENV=production [Install] WantedBy=multi-user.target ``` ▪️ Что важно здесь: - Restart=always — перезапуск при сбоях. - StandardOutput и StandardError перенаправляют логи прямо в файлы. - User и Group указывают, под кем должен работать процесс. - WorkingDirectory задаёт рабочую папку для приложения. ▪️ Как активировать сервис: ```sh sudo systemctl daemon-reload sudo systemctl enable myapp sudo systemctl start myapp sudo systemctl status myapp ``` ▪️ Теперь управление сервисом становится надёжным и простым. ▪️ Дополнительные вопросы на собеседовании: ▪️ Вывод: Переход от скриптов к systemd — это шаг к профессиональной эксплуатации Linux-приложений.   Меньше ручных ошибок, лучшее управление процессами, больше надёжности. ```sh # Проверить, включен ли автозапуск сервиса systemctl is-enabled your_service.service # Посмотреть статус сервиса (включая последние ошибки) systemctl status your_service.service # Включить автозапуск sudo systemctl enable your_service.service # Логи сервиса с момента последнего запуска journalctl -u your_service.service -b # Показать ошибки systemd на загрузке systemd-analyze blame ``` 🟢 systemctl — управление сервисами и проверка их состояния 🟢 journalctl — просмотр логов systemd 🟢 systemd-analyze помогает понять, что тормозит загрузку системы. #======================== _bot.service_ ```sh # Создаем НОВУЮ службу или редактируем первоисточник: sudo systemctl edit --force --full bot # или редактируем уже имеющуюся (открывается пустой файл # для добавления или исправления): sudo systemctl edit bot # Все сервисы находятся в: cd /etc/systemd/system/ #============================ ``` ```shell [Unit] Description=bot After=network.target # только после запуска сети # After=multi-user.target [Service] Type=simple ExecStart=python3 /home/vlapa/folder/bot.py WorkingDirectory=/home/vlapa Restart=always # on-failure #---------------------------- User=root Group=root #---------------------------- [Install] WantedBy=multi-user.target # default.target ``` ```sh # перезагрузка всех служб: sudo systemctl daemon-reload # включить в автозагрузку: sudo systemctl enable bot.service # перезапуск с перечитыванием конфигов systemctl restart bot.service # перезапуск без перечитывания конфигов systemctl reload bot.service # включить в автозагрузку systemctl enable bot.service # выключить из автозагрузки systemctl disable bot.service # проверка включена или нет в автозагрузку systemctl is-enabled ssh # Все модули: systemctl list-units --all systemctl list-unit-files --type=service "ssh*" # Оптимизация загрузки: systemd-analyze blame ``` ```sh # Создание исполняемого скрипта: #!/usr/bin/env python3 chmod +x my_script.py # Запуск скрипта: ./my_script.py ``` =============================== Все модули можно найти в трёх каталогах: `/usr/lib/systemd/system` — юниты сервисов, установленных с помощью менеджера пакетов. Самый простой пример — веб-серверы: Apache или Nginx. `/run/systemd/system` — юниты, которые создаются в процессе работы системы. `/etc/systemd/system` — юниты, которые создаёт администратор системы. Список всех запущенных модулей можно посмотреть, использовуя команду `systemctl`. В терминале вы увидите таблицу со статусом каждой службы. Разберём, что означает каждый из столбцов: 1. **UNIT**. Название модуля 2. **LOAD**. Статус загрузки конфигурации, если успешно — loaded. 3. **ACTIVE**. Статус службы. Один из следующих: _active, inactive, running, exited, dead, loaded, not-found, plugged, mounted, waiting, listening._ 4. **SUB**. Детальная информация о юните. 5. **DESCRIPTION**. Краткое описание модуля — за что он отвечает. Чтобы увидеть все модули, независимо от того, запущены они или нет, воспользуйтесь командой `systemctl list-units --all`. Вы увидите все модули, которые когда-либо загружал или пытался загрузить диспетчер systemd. Для отображения конкретных записей используйте флаг `--state`. Так, например, для того, чтобы увидеть все неактивные юниты, нужно использовать: `sudo systemctl list-units --all --state=inactive` `` ### Типы юнитов Модули делятся на категории по типу. Тип каждого модуля можно узнать из названия файла — он указан через точку. Все типы модулей: 1. .service — описывает, как управлять службой и приложением 2. .socket — описывает сетевой буфер, который используется для активации сокета 3. .device — описывает устройство как необходимое для управления systemd 4. .mount — определяет точку монтирования в системе 5. .automount — настраивает автоматическую установку точки монтирования 6. .swap — описывает пространство подкачки в системе 7. .target — обеспечивает синхронизацию устройств при загрузке системы 8. .path — определяет путь, который используется для активации 9. .timer — определяет задержку или активацию по плану 10. .snapshot — делает снимок системы для последующего восстановления 11. .slice — ограничивает узлы группы управления 12. .scope — systemd создаёт эти модули автоматически, пользуясь информацией из интерфейса шины ```sh [Unit] Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) After=network.target sshd-keygen.target Wants=sshd-keygen.target [Service] Type=notify Environment File=-/etc/crypto-policies/back-ends/opensshserver.config EnvironmentFile=-/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target ``` **Unit** Это первая обязательная секция. В ней описаны правила взаимодействия с другими службами и указаны метаданные — описание и документация. Подробнее: - Description — описание модуля. - Documentation — страница руководства man. - After — после каких демонов и событий нужно запускать модуль. Например, модули веб-серверов запускаются только после сетевых интерфейсов. - Requires — сервисы, необходимые для работы юнита - Wants — сервисы, которые желательно запустить перед стартом модуля **Service** В этой секции необходимо указать, какими командами запускать службу: - Type — как запускается демон? По умолчанию — simple, то есть служба просто запускается. Notify это примерно то же самое, но в таком случае процесс сообщит диспетчеру, что он готов к работе. Есть также типы forking (после запуска демона родительский процесс завершается) и one-shot (выполняется один раз). - PIDFile — ссылка на основной процесс - WorkingDirectory — текущая рабочая директория для запуска команд - User — пользователь для запуска сервиса - Group — группа для запуска сервиса - ExecStart — команда для запуска сервиса - ExecStop — команда для остановки сервиса - TimeoutSec — время, которое служба ожидает остановки или старта - Restart — настройки перезапуска **Install** В этой секции нужно указать, на каком уровне загрузки системы нужно запускать сервис. Переменная WantedBy сообщает, как включится устройство, в качестве параметра указываются специальные файлы целей. Они служат для того, чтобы привести систему в разные состояния.  Список доступных целей вы можете получить, выполнив команду  `sudo systemctl list-unit-files --type=target` ### Редактирование модулей Модули нельзя править напрямую. Для этого нужно использовать команду  `systemctl edit` Откроется файл, который можно использовать для переопределения директив службы или добавления новых. При этом настройки из файла переопределения приоритетнее, чем настройки по умолчанию.  Если нужно отредактировать файл модуля целиком, а не добавлять новые директивы, нужно использовать флаг `--full`: `sudo systemctl edit --full apache2.service` `` Перед вами откроется редактор, в котором вы можете править настройки юнита.  По умолчанию файлы переопределения хранятся в  `/etc/systemd/system/` в каталоге который называется так же, как модуль, но с суффиксом `.d`. Например, в случае apache2 это будет директория  `/etc/systemd/system/apache2.service.d/`.  Если вы редактируете конфигурацию напрямую с использованием флага `--full`, нужный файл находится в каталоге  `/etc/systemd/system/` и называется так же, как модуль. Для того, чтобы удалить переопределения, которые вы добавили, просто удалите каталог с суффиксом `.d`. Если нужно восстановить настройки по умолчанию, удалите весь файл модуля. В случае с apache2 это: `sudo rm -r /etc/systemd/system/apache2.service.d` `` или  `sudo rm /etc/systemd/system/apache2.service` `` После этого нужно перезагрузить процесс systemd: `sudo systemctl daemon-reload` ` =============================== ## Создание сервиса В подсистеме systemd также можно легко создать собственную службу и использовать ее для автозапуска приложений или собственных скриптов. Для этого в каталоге **/usr/lib/systemd/system** создаем юнит (файл) с расширением **.service**. Пример простой и частоиспользуемой конфигурации: [Unit] Description=Service Name After=network.target [Service] User=root Group=root Type=simple ExecStart=/usr/bin/myapp ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure [Install] WantedBy=multi-user.target * как правило, файл разделен на 3 части: - **Unit** — позволяет определить метаданные для юнита. - **Service** — раздел для основной конфигурации юнита. - **Install** — определение поведения для юнита при его включении или отключении. Подробнее можно почитать о структуре и возможных опциях на странице [https://linux-notes.org/pishem-systemd-unit-fajl/](https://linux-notes.org/pishem-systemd-unit-fajl/) Более сложный вариант разберем на примере сервиса bind: vi /usr/lib/systemd/system/named.service Содержимое может быть следующего содержания: [Unit] Description=Berkeley Internet Name Domain (DNS) Wants=nss-lookup.target Wants=named-setup-rndc.service Before=nss-lookup.target After=network.target After=named-setup-rndc.service [Service] Type=forking Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/run/named/named.pid ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID' PrivateTmp=true [Install] WantedBy=multi-user.target После внесения изменений и сохранения файла, необходимо перечитать изменения командой: systemctl daemon-reload Теперь можно разрешить автозапуск: systemctl enable named ### Редактирование сервисов Если мы хотим внести изменения в юнит-файл сервиса, который был установлен с последним, необходимо использовать drop-in файл или файл переопределения настроек. В противном случае, после обновления программы наши изменения могут быть удалены. И так, мы для примера взяли юнит для bind. Чтобы создать для него drop-in файл, вводим: systemctl edit named И вносим, например, такие изменения: [Service] Restart=on-failure _* будет создан файл **/etc/systemd/system/named.service.d/override.conf**, который будет переопределять настройки основного юнит-файла. В данном примере, мы указываем на необходимость перезапуска сервиса при сбое._ Чтобы убедиться в использовании Drop-In файла смотрим статус сервиса: systemctl status named Мы должны увидеть что-то на подобие: Drop-In: /etc/systemd/system/named.service.d            — override.conf Также мы можем редаетировать файл юните без drop-in. Для этого добавляем опцию full: systemctl edit --full named Однако, как было сказано выше, при очередном обновлении приложения, если разработчик пакета предоставляет файл systemd наши изменения могут быть перетерты. ## Таймеры Выше мы рассмотрели возможность автоматического запуска сервисов с помощью systemd. Мы также можем настроить периодический запуск данных юнитов по таймеру. Для этого нам нужно создать юнит с таким же названием, но на конце должен быть суффикс ==.timer==. Предположим, мы хотим создать запуск по таймеру named, для которого выше в примере создали юнит сервиса. Тогда создаем файл: ```sh vi /usr/lib/systemd/system/named.timer [Unit] Description=Run named every 10 min [Timer] OnBootSec=5min OnUnitActiveSec=10min [Install] WantedBy=timers.target # в данном примере наш таймер будет создан для юнита named; он запустится через 5 минут после старта службы и будет запускать ее каждые 10 минут # Перечитаем изменения в systemd: systemctl daemon-reload # Разрешаем наш таймер: systemctl enable named.timer # Запустим его: systemctl start named.timer # Вывести список таймеров можно командой: systemctl list-timers ```