Перейти к содержанию

Unit for tg bot: различия между версиями

Материал из RAMBA Wiki
Содержимое страницы заменено на «== '''Создаем Unit для tg bot''' ==»
Метки: замена с мобильного устройства из мобильной версии
Нет описания правки
Метки: с мобильного устройства из мобильной версии
 
(не показана 1 промежуточная версия этого же участника)
Строка 1: Строка 1:
== '''Создаем Unit для tg bot''' ==
= Запуск Python-скрипта как службы systemd =
 
В Linux Python-скрипт можно запустить как системную службу с помощью ‘’‘systemd’’’ .
 
Это удобно для Telegram-ботов, веб-сервисов и других приложений, которые должны:
 
* автоматически запускаться вместе с сервером;
* работать в фоновом режиме;
* автоматически перезапускаться после ошибки;
* управляться стандартными командами systemctl;
* сохранять журнал работы в journalctl.
 
В этой статье рассмотрим два варианта запуска Python-приложения на примере Telegram-бота ‘’‘noProdaction’’’.
 
TOC
 
== Способ №1 — запуск через отдельный shell-скрипт ==
 
В этом варианте systemd запускает вспомогательный shell-скрипт, который, в свою очередь, запускает Python-приложение.
 
Схема запуска:
 
<pre>
systemd
  │
  ▼
noProdaction.sh
  │
  ▼
python3
  │
  ▼
main.py
</pre>
 
=== Создание скрипта запуска ===
 
Создаём каталог для скрипта запуска, если его ещё нет:
 
<syntaxhighlight lang="bash">
mkdir -p /opt/Python/Telegram/start
</syntaxhighlight>
 
Создаём файл:
 
<syntaxhighlight lang="bash">
nano /opt/Python/Telegram/start/noProdaction.sh
</syntaxhighlight>
 
Добавляем:
 
<syntaxhighlight lang="bash">
#!/bin/bash
 
exec /usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
Сохраняем файл:
 
<pre>
Ctrl + O
Enter
Ctrl + X
</pre>
 
Делаем его исполняемым:
 
<syntaxhighlight lang="bash">
chmod +x /opt/Python/Telegram/start/noProdaction.sh
</syntaxhighlight>
 
{{Note|Использование exec позволяет заменить процесс shell непосредственно процессом Python. Благодаря этому systemd корректнее отслеживает PID приложения и управляет его завершением.}}
 
=== Создание systemd unit ===
 
Создаём unit-файл:
 
<syntaxhighlight lang="bash">
nano /etc/systemd/system/noprodaction.service
</syntaxhighlight>
 
Добавляем:
 
<syntaxhighlight lang="ini">
[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
User=root
WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1
ExecStart=/opt/Python/Telegram/start/noProdaction.sh
 
Restart=on-failure
RestartSec=5
 
NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full
 
[Install]
WantedBy=multi-user.target
Сохраняем файл:
 
<pre>
Ctrl + O
Enter
Ctrl + X
</pre>
 
=== Активация службы ===
 
После создания или изменения unit-файла необходимо перечитать конфигурацию systemd:
 
<syntaxhighlight lang="bash">
systemctl daemon-reload
</syntaxhighlight>
 
Добавляем службу в автозагрузку:
 
<syntaxhighlight lang="bash">
systemctl enable noprodaction.service
</syntaxhighlight>
 
Запускаем:
 
<syntaxhighlight lang="bash">
systemctl start noprodaction.service
</syntaxhighlight>
 
Можно выполнить обе команды сразу:
 
<syntaxhighlight lang="bash">
systemctl enable --now noprodaction.service
</syntaxhighlight>
 
=== Проверка работы ===
 
Проверяем состояние:
 
<syntaxhighlight lang="bash">
systemctl status noprodaction.service
</syntaxhighlight>
 
При нормальной работе должна присутствовать строка:
 
<pre>
Active: active (running)
</pre>
 
Например:
 
<pre>
● noprodaction.service - Telegram bot noProdaction
    Loaded: loaded (/etc/systemd/system/noprodaction.service; enabled)
    Active: active (running)
  Main PID: 173 (python3.11)
      Tasks: 2
    Memory: 34.1M
        CPU: 1.766s
</pre>
 
== Способ №2 — запуск Python напрямую из systemd ==
 
{{Note|’’‘Рекомендуемый вариант.’’’ Если для запуска приложения не требуется выполнять дополнительные команды, создавать отдельный .sh-файл нет необходимости. Python можно запускать непосредственно из systemd.}}
 
Схема становится проще:
 
<pre>
systemd
  │
  ▼
python3
  │
  ▼
main.py
</pre>
 
Создаём unit-файл:
 
<syntaxhighlight lang="bash">
nano /etc/systemd/system/noprodaction.service
</syntaxhighlight>
 
Добавляем:
 
<syntaxhighlight lang="ini">
[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
 
User=root
WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1
 
ExecStart=/usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
 
Restart=on-failure
RestartSec=5
 
NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full
 
[Install]
WantedBy=multi-user.target
После создания файла выполняем:
 
<syntaxhighlight lang="bash">
systemctl daemon-reload
systemctl enable --now noprodaction.service
</syntaxhighlight>
 
Проверяем:
 
<syntaxhighlight lang="bash">
systemctl status noprodaction.service
</syntaxhighlight>
 
== Управление службой ==
 
После создания unit-файла ботом можно управлять стандартными командами systemd.
 
{| class=“wikitable”
! Действие
 
! Команда
 
Проверить состояние
 
systemctl status noprodaction
 
-
 
Запустить
 
systemctl start noprodaction
 
-
 
Остановить
 
systemctl stop noprodaction
 
-
 
Перезапустить
 
systemctl restart noprodaction
 
-
 
Добавить в автозагрузку
 
systemctl enable noprodaction
 
-
 
Убрать из автозагрузки
 
systemctl disable noprodaction
 
}
 
== Просмотр логов ==
 
Одно из преимуществ запуска через systemd — вывод Python-приложения автоматически попадает в системный журнал.
 
Посмотреть последние записи:
 
<syntaxhighlight lang="bash">
journalctl -u noprodaction.service
</syntaxhighlight>
 
Последние 100 строк:
 
<syntaxhighlight lang="bash">
journalctl -u noprodaction.service -n 100
</syntaxhighlight>
 
Следить за журналом в реальном времени:
 
<syntaxhighlight lang="bash">
journalctl -u noprodaction.service -f
</syntaxhighlight>
 
Выйти из режима просмотра:
 
<pre>
Ctrl + C
</pre>
 
Посмотреть журнал только с момента последней загрузки сервера:
 
<syntaxhighlight lang="bash">
journalctl -u noprodaction.service -b
</syntaxhighlight>
 
== После изменения Python-кода ==
 
Если был изменён только код main.py или других файлов приложения, выполнять daemon-reload не требуется.
 
Достаточно перезапустить приложение:
 
<syntaxhighlight lang="bash">
systemctl restart noprodaction
</syntaxhighlight>
 
Если же был изменён сам файл:
 
<pre>
/etc/systemd/system/noprodaction.service
</pre>
 
необходимо выполнить:
 
<syntaxhighlight lang="bash">
systemctl daemon-reload
systemctl restart noprodaction
</syntaxhighlight>
 
== Автоматический перезапуск ==
 
В нашем unit-файле используются параметры:
 
<syntaxhighlight lang="ini">
Restart=on-failure
RestartSec=5
</syntaxhighlight>
 
Это означает, что если Python-процесс аварийно завершится, systemd подождёт 5 секунд и попробует запустить его снова.
 
Проверить количество перезапусков можно командой:
 
<syntaxhighlight lang="bash">
systemctl show noprodaction.service -p NRestarts
</syntaxhighlight>
 
== Проверка пути к Python ==
 
Путь к Python может отличаться в зависимости от системы.
 
Проверить его можно командой:
 
<syntaxhighlight lang="bash">
which python3
</syntaxhighlight>
 
Например:
 
<pre>
/usr/bin/python3
</pre>
 
Версию Python:
 
<syntaxhighlight lang="bash">
python3 --version
</syntaxhighlight>
 
Если конкретная версия Python не требуется, в unit-файле можно использовать:
 
<syntaxhighlight lang="ini">
ExecStart=/usr/bin/python3 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
</syntaxhighlight>
 
== Запуск через Python Virtual Environment ==
 
Если проект использует собственное виртуальное окружение Python, рекомендуется запускать Python непосредственно из него.
 
Например, если виртуальное окружение находится здесь:
 
<pre>
/opt/Python/Telegram/noProdaction/venv/
</pre>
 
то ExecStart будет выглядеть так:
 
<syntaxhighlight lang="ini">
ExecStart=/opt/Python/Telegram/noProdaction/venv/bin/python /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
</syntaxhighlight>
 
Активировать venv командой source внутри systemd не требуется.
 
== Рекомендуемый unit-файл ==
 
Для обычного Python-приложения итоговый вариант может выглядеть следующим образом:
 
<syntaxhighlight lang="ini">
[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
User=root
 
WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1
ExecStart=/usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
 
Restart=on-failure
RestartSec=5
 
NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full
 
[Install]
WantedBy=multi-user.target
После создания:
 
<syntaxhighlight lang="bash">
systemctl daemon-reload
systemctl enable --now noprodaction.service
</syntaxhighlight>
 
Проверяем:
 
<syntaxhighlight lang="bash">
systemctl status noprodaction.service
</syntaxhighlight>
 
и журнал:
 
<syntaxhighlight lang="bash">
journalctl -u noprodaction.service -f
</syntaxhighlight>
 
== Примечание по безопасности ==
 
В примерах выше служба запускается от пользователя:
 
<syntaxhighlight lang="ini">
User=root
</syntaxhighlight>
 
Для собственного сервера это работает, однако большинству Python-приложений права root не нужны.
 
Более безопасный вариант — создать отдельного системного пользователя для приложения и запускать службу от его имени.
 
Например:
 
<syntaxhighlight lang="bash">
useradd --system --home /opt/Python/Telegram/noProdaction --shell /usr/sbin/nologin noprodaction
</syntaxhighlight>
 
После этого необходимо выдать пользователю права на необходимые файлы приложения и заменить в unit-файле:
 
<syntaxhighlight lang="ini">
User=root
</syntaxhighlight>
 
на:
 
<syntaxhighlight lang="ini">
User=noprodaction
</syntaxhighlight>
 
{{Warning|Не храните токены Telegram-бота, API-ключи, пароли баз данных и другие секреты непосредственно в публичном unit-файле или исходном коде проекта. Для секретов лучше использовать отдельный файл окружения с ограниченными правами доступа.}}
 
== Итог ==
 
Для простого Python-приложения рекомендуется использовать ‘’‘Способ №2’’’:
 
<pre>
            Загрузка Linux
                    │
                    ▼
                systemd
                    │
                    ▼
        noprodaction.service
                    │
                    ▼
                Python
                    │
                    ▼
                main.py
                    │
                    ▼
            Telegram Bot
</pre>
 
После этого приложение автоматически запускается вместе с системой, работает в фоне и при аварийном завершении автоматически запускается снова.

Текущая версия от 21:36, 31 августа 2026

Запуск Python-скрипта как службы systemd

В Linux Python-скрипт можно запустить как системную службу с помощью ‘’‘systemd’’’ .

Это удобно для Telegram-ботов, веб-сервисов и других приложений, которые должны:

  • автоматически запускаться вместе с сервером;
  • работать в фоновом режиме;
  • автоматически перезапускаться после ошибки;
  • управляться стандартными командами systemctl;
  • сохранять журнал работы в journalctl.

В этой статье рассмотрим два варианта запуска Python-приложения на примере Telegram-бота ‘’‘noProdaction’’’.

TOC

Способ №1 — запуск через отдельный shell-скрипт

В этом варианте systemd запускает вспомогательный shell-скрипт, который, в свою очередь, запускает Python-приложение.

Схема запуска:

systemd
   │
   ▼
noProdaction.sh
   │
   ▼
python3
   │
   ▼
main.py

Создание скрипта запуска

Создаём каталог для скрипта запуска, если его ещё нет:

mkdir -p /opt/Python/Telegram/start

Создаём файл:

nano /opt/Python/Telegram/start/noProdaction.sh

Добавляем:

#!/bin/bash

exec /usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py
Сохраняем файл:

<pre>
Ctrl + O
Enter
Ctrl + X
</pre>

Делаем его исполняемым:

<syntaxhighlight lang="bash">
chmod +x /opt/Python/Telegram/start/noProdaction.sh

Шаблон:Note

Создание systemd unit

Создаём unit-файл:

nano /etc/systemd/system/noprodaction.service

Добавляем:

[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1
ExecStart=/opt/Python/Telegram/start/noProdaction.sh

Restart=on-failure
RestartSec=5

NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
Сохраняем файл:

<pre>
Ctrl + O
Enter
Ctrl + X
</pre>

=== Активация службы ===

После создания или изменения unit-файла необходимо перечитать конфигурацию systemd:

<syntaxhighlight lang="bash">
systemctl daemon-reload

Добавляем службу в автозагрузку:

systemctl enable noprodaction.service

Запускаем:

systemctl start noprodaction.service

Можно выполнить обе команды сразу:

systemctl enable --now noprodaction.service

Проверка работы

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

systemctl status noprodaction.service

При нормальной работе должна присутствовать строка:

Active: active (running)

Например:

● noprodaction.service - Telegram bot noProdaction
     Loaded: loaded (/etc/systemd/system/noprodaction.service; enabled)
     Active: active (running)
   Main PID: 173 (python3.11)
      Tasks: 2
     Memory: 34.1M
        CPU: 1.766s

Способ №2 — запуск Python напрямую из systemd

Шаблон:Note

Схема становится проще:

systemd
   │
   ▼
python3
   │
   ▼
main.py

Создаём unit-файл:

nano /etc/systemd/system/noprodaction.service

Добавляем:

[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

User=root
WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1

ExecStart=/usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py

Restart=on-failure
RestartSec=5

NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
После создания файла выполняем:

<syntaxhighlight lang="bash">
systemctl daemon-reload
systemctl enable --now noprodaction.service

Проверяем:

systemctl status noprodaction.service

Управление службой

После создания unit-файла ботом можно управлять стандартными командами systemd.

Действие Команда

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

systemctl status noprodaction

-

Запустить

systemctl start noprodaction

-

Остановить

systemctl stop noprodaction

-

Перезапустить

systemctl restart noprodaction

-

Добавить в автозагрузку

systemctl enable noprodaction

-

Убрать из автозагрузки

systemctl disable noprodaction

}

Просмотр логов

Одно из преимуществ запуска через systemd — вывод Python-приложения автоматически попадает в системный журнал.

Посмотреть последние записи:

journalctl -u noprodaction.service

Последние 100 строк:

journalctl -u noprodaction.service -n 100

Следить за журналом в реальном времени:

journalctl -u noprodaction.service -f

Выйти из режима просмотра:

Ctrl + C

Посмотреть журнал только с момента последней загрузки сервера:

journalctl -u noprodaction.service -b

После изменения Python-кода

Если был изменён только код main.py или других файлов приложения, выполнять daemon-reload не требуется.

Достаточно перезапустить приложение:

systemctl restart noprodaction

Если же был изменён сам файл:

/etc/systemd/system/noprodaction.service

необходимо выполнить:

systemctl daemon-reload
systemctl restart noprodaction

Автоматический перезапуск

В нашем unit-файле используются параметры:

Restart=on-failure
RestartSec=5

Это означает, что если Python-процесс аварийно завершится, systemd подождёт 5 секунд и попробует запустить его снова.

Проверить количество перезапусков можно командой:

systemctl show noprodaction.service -p NRestarts

Проверка пути к Python

Путь к Python может отличаться в зависимости от системы.

Проверить его можно командой:

which python3

Например:

/usr/bin/python3

Версию Python:

python3 --version

Если конкретная версия Python не требуется, в unit-файле можно использовать:

ExecStart=/usr/bin/python3 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py

Запуск через Python Virtual Environment

Если проект использует собственное виртуальное окружение Python, рекомендуется запускать Python непосредственно из него.

Например, если виртуальное окружение находится здесь:

/opt/Python/Telegram/noProdaction/venv/

то ExecStart будет выглядеть так:

ExecStart=/opt/Python/Telegram/noProdaction/venv/bin/python /opt/Python/Telegram/noProdaction/noprodaction-1/main.py

Активировать venv командой source внутри systemd не требуется.

Рекомендуемый unit-файл

Для обычного Python-приложения итоговый вариант может выглядеть следующим образом:

[Unit]
Description=Telegram bot noProdaction
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root

WorkingDirectory=/opt/Python/Telegram/noProdaction/noprodaction-1
ExecStart=/usr/bin/python3.11 /opt/Python/Telegram/noProdaction/noprodaction-1/main.py

Restart=on-failure
RestartSec=5

NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
После создания:

<syntaxhighlight lang="bash">
systemctl daemon-reload
systemctl enable --now noprodaction.service

Проверяем:

systemctl status noprodaction.service

и журнал:

journalctl -u noprodaction.service -f

Примечание по безопасности

В примерах выше служба запускается от пользователя:

User=root

Для собственного сервера это работает, однако большинству Python-приложений права root не нужны.

Более безопасный вариант — создать отдельного системного пользователя для приложения и запускать службу от его имени.

Например:

useradd --system --home /opt/Python/Telegram/noProdaction --shell /usr/sbin/nologin noprodaction

После этого необходимо выдать пользователю права на необходимые файлы приложения и заменить в unit-файле:

User=root

на:

User=noprodaction

Шаблон:Warning

Итог

Для простого Python-приложения рекомендуется использовать ‘’‘Способ №2’’’:

             Загрузка Linux
                    │
                    ▼
                 systemd
                    │
                    ▼
         noprodaction.service
                    │
                    ▼
                Python
                    │
                    ▼
                main.py
                    │
                    ▼
             Telegram Bot

После этого приложение автоматически запускается вместе с системой, работает в фоне и при аварийном завершении автоматически запускается снова.