Systemd service python script

Запуск Python скрипта в виде службы через systemctl/systemd

Есть несколько способов запуска вашей программы в качестве фоновой службы в Linux, таких как crontab, .bashrc и т. д., но сегодня будет разговор о systemd. Изначально я искал способ запустить свой скрипт на Python в качестве фоновой службы, поэтому даже если сервер по какой-то причине перезагрузится, мой скрипт все равно должен работать в фоновом режиме, после небольшого ресерча и я обнаружил, что systemd позволяет мне это сделать. Давайте начнем.

Настройки далее будут производиться на машине с Ubuntu 20.04.

Почти все версии Linux поставляются с systemd из коробки, но если у вас его нет, вы можете просто запустить следующую команду:

sudo apt install -y systemd 

Примечание. Флаг -y означает быструю установку пакетов и зависимостей.

Чтобы проверить, какая версия systemd у вас установлена, просто выполните команду:

Создайте файл python с любым именем. Я назову свой скрипт именем test.py.

import time from datetime import datetime while True: with open("timestamp.txt", "a") as f: f.write("Текущая временная метка: " + str(datetime.now())) f.close() time.sleep(10) 

Приведенный выше скрипт будет записывать текущую метку времени в файл каждые 10 секунд. Теперь напишем сервис.

sudo nano /etc/systemd/system/test.service 

(имя службы, которая тестируется в этом случае)

[Unit] Description=My test service After=multi-user.target [Service] User=deepak Group=admin Type=simple Restart=always ExecStart=/usr/bin/python3 /home//test.py [Install] WantedBy=multi-user.target 

Замените имя пользователя в вашей ОС, где написано . Флаг ExecStart принимает команду, которую вы хотите запустить. Таким образом, в основном первый аргумент — это путь к python (в моем случае это python3), а второй аргумент — это путь к скрипту, который необходимо выполнить. Флаг перезапуска всегда установлен, потому что я хочу перезапустить свою службу, если сервер будет перезапущен.

Здесь мы определили User=deepak и Group=admin, чтобы убедиться, что скрипт будет выполняться только от имени пользователя deepak, входящего в группу admin.

Теперь нам нужно перезагрузить демон.

sudo systemctl daemon-reload 

Давайте включим наш сервис, чтобы он не отключался при перезагрузке сервера.

sudo systemctl enable test.service 

А теперь давайте запустим наш сервис.

sudo systemctl start test.service 

Теперь наш сервис работает.

Примечание. Файл будет записан в корневой каталог (/), потому что программа запишет путь с точки зрения systemd. Чтобы изменить это, просто отредактируйте путь к файлу. Например:

import time from datetime import datetime path_to_file = "введите желаемый путь к файлу" while True: with open(path_to_file, "a") as f: f.write("Текущая временная метка: " + str(datetime.now())) f.close() time.sleep(10) 

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

sudo systemctl stop name_of_your_service 
sudo systemctl restart name_of_your_service 
sudo systemctl status name_of_your_service 

Это было очень поверхностное знакомство с systemd, предназначенное для новичков, которые хотят начать писать свои собственные systemd службы для python.

ПРИМЕЧАНИЕ. Это относится не только к сценариям Python. Вы можете запустить любую программу с ним, независимо от языка программирования, на котором написана ваша программа.

Источник

systemd Service for a Python script¶

If, like many sysadmins, you are an aficionado of cron scripts launched with * * * * * /I/launch/my/script.sh , this article should make you think of another way to do it using all the power and ease offered by systemd .

We will write a python script that will provide a continuous loop to execute the actions you define.

We will see how to run this script as a systemd service, view the logs in journalctl, and see what happens if the script crashes.

Prerequisites¶

Let’s start by installing some python dependencies needed for the script to use journalctl:

shell > sudo dnf install python36-devel systemd-devel shell > sudo pip3 install systemd 

Writing the Script¶

Let’s consider the following script my_service.py :

""" Sample script to run as script """ import time import logging import sys from systemd.journal import JournaldLogHandler # Get an instance of the logger LOGGER = logging.getLogger(__name__) # Instantiate the JournaldLogHandler to hook into systemd JOURNALD_HANDLER = JournaldLogHandler() JOURNALD_HANDLER.setFormatter(logging.Formatter( '[%(levelname)s] %(message)s' )) # Add the journald handler to the current logger LOGGER.addHandler(JOURNALD_HANDLER) LOGGER.setLevel(logging.INFO) class Service(): # pylint: disable=too-few-public-methods """ Launch an infinite loop """ def __init__(self): duration = 0 while True: time.sleep(60) duration += 60 LOGGER.info("Total duration: %s", str(duration)) # will failed after 4 minutes if duration > 240: sys.exit(1) if __name__ == '__main__': LOGGER.info("Starting the service") Service() 

We start by instantiating the necessary variables to send logs in journald. The script then launches an infinite loop and pauses for 60 seconds (which is the minimum of a cron execution, so we can go below this limitation).

I personally use this script in a more advanced form, which continuously queries a database and executes jobs based on the information retrieved via the rundeck API

Systemd Integration¶

Now that we have a script that can serve as a basis for your imagination, we can install it as a systemd service.

Let’s create this file my_service.service and copy it to /etc/systemd/system/ .

[Unit] Description=My Service After=multi-user.target [Service] Type=simple Restart=always ExecStart=/usr/bin/python3 my_service.py WorkingDirectory=/opt/my_service/ StandardOutput=syslog StandardError=syslog SyslogIdentifier=my_service [Install] WantedBy=multi-user.target 

As you can see, the script is launched from /opt/my_service/ . Remember to adapt the path to your script and the syslog identifier.

Launch and enable the new service:

shell > sudo systemctl daemon-reload shell > sudo systemctl enable my_service.service shell > sudo systemctl start my_service.service 

Tests¶

We can now view the logs via journalctl:

shell > journalctl -f -u my_service oct. 14 11:07:48 rocky8 systemd[1]: Started My Service. oct. 14 11:07:49 rocky8 __main__[270267]: [INFO] Starting the service oct. 14 11:08:49 rocky8 __main__[270267]: [INFO] Total duration: 60 oct. 14 11:09:49 rocky8 __main__[270267]: [INFO] Total duration: 120 

Now let’s see what happens if the script crashes:

shell > ps -elf | grep my_service 4 S root 270267 1 0 80 0 - 82385 - 11:07 ? 00:00:00 /usr/bin/python3 my_service.py shell > sudo kill -9 270267 
shell > journalctl -f -u my_service oct. 14 11:10:49 rocky8 __main__[270267]: [INFO] Total duration: 180 oct. 14 11:11:49 rocky8 __main__[270267]: [INFO] Total duration: 240 oct. 14 11:12:19 rocky8 systemd[1]: my_service.service: Main process exited, code=killed, status=9/KILL oct. 14 11:12:19 rocky8 systemd[1]: my_service.service: Failed with result 'signal'. oct. 14 11:12:19 rocky8 systemd[1]: my_service.service: Service RestartSec=100ms expired, scheduling restart. oct. 14 11:12:19 rocky8 systemd[1]: my_service.service: Scheduled restart job, restart counter is at 1. oct. 14 11:12:19 rocky8 systemd[1]: Stopped My Service. oct. 14 11:12:19 rocky8 systemd[1]: Started My Service. oct. 14 11:12:19 rocky8 __main__[270863]: [INFO] Starting the service 

We can also wait 5 minutes for the script to crash by itself: (remove this for your production)

oct. 14 11:16:02 rocky8 systemd[1]: Started My Service. oct. 14 11:16:03 rocky8 __main__[271507]: [INFO] Starting the service oct. 14 11:17:03 rocky8 __main__[271507]: [INFO] Total duration: 60 oct. 14 11:18:03 rocky8 __main__[271507]: [INFO] Total duration: 120 oct. 14 11:19:03 rocky8 __main__[271507]: [INFO] Total duration: 180 oct. 14 11:20:03 rocky8 __main__[271507]: [INFO] Total duration: 240 oct. 14 11:21:03 rocky8 __main__[271507]: [INFO] Total duration: 300 oct. 14 11:21:03 rocky8 systemd[1]: my_service.service: Main process exited, code=exited, status=1/FAILURE oct. 14 11:21:03 rocky8 systemd[1]: my_service.service: Failed with result 'exit-code'. oct. 14 11:21:03 rocky8 systemd[1]: my_service.service: Service RestartSec=100ms expired, scheduling restart. oct. 14 11:21:03 rocky8 systemd[1]: my_service.service: Scheduled restart job, restart counter is at 1. oct. 14 11:21:03 rocky8 systemd[1]: Stopped My Service. oct. 14 11:21:03 rocky8 systemd[1]: Started My Service. oct. 14 11:21:03 rocky8 __main__[271993]: [INFO] Starting the service 

As you can see, the restart feature of systemd is very useful.

Conclusion¶

systemd and journald provide us the tools to make robust and powerful scripts easily enough to replace our old reliable crontab scripts.

I hope this solution will be useful for you.

Contributors: Steven Spencer

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Tutorial to run Python script via systemd

License

Nivratti/python-systemd

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

Tutorial to run Python script via systemd

Systemd Service file location and management

Оцените статью