Start python script as service

Script as a Service

I’m going to show you how I got a Python script to run as a service on Ubuntu. I was working on a project of mine that is a Twitter Bot that tweets compliments at people. I wrote a (slightly disjointed) post about it a little while ago, if you want more background. Basically, I have this bot running in a Python script, and I want this Python script to run for a long time. I definitely want to be able to kick it off and log out of my server! So I went in search of some options.

The Options

  1. Never log out of the server. Run python main.py and leave the shell open. Pros: very easy to do, and I already knew how to do it. Cons: probably won’t work for long. I assume ssh connections time out eventually. Also, logging becomes an extra step of python main.py | tee fanbot.log or something of that nature. All in all, feels hacky.
  2. nohup . A HUP (hangup) signal is sent to any job if its controlling terminal is closed. One example of this is logging out of an SSH session or closing an open terminal window. This causes it to wrap up and shut down. nohup is a command that tells a job to ignore the HUP signal. I would be able to do nohup python main.py & . The & pushes the job to the background. The job then runs in the background and appends all output to nohup.out . You can get a custom logfile thusly: nohup python main.py > custom.log & . Pros: I can log out, I get logfiles where I want them, fairly simple command. Cons: Dies if the server resets. I’m also not sure how cleanly it could be killed. It would at least be a couple commands to get it done properly.
  3. Use a terminal multiplexer. I could use something like tmux to run in. For those of you that don’t know what tmux is, it’s a neat way of saving and reusing terminal window, pane, and histories. You can attach and detach from a tmux session whenever you want, but the programs running in the session stay running. I’ll have to add a tmux overview to my list of things to write. Pros: Easy to use. Works basically just like running things in the terminal. Cons: Also dies if the server resets. tmux feels like a little bit of overkill just to manage this one single job. If you’re interested, here’s how that would go down:
$ tmux new -s fanbot_session $ python main.py | tee fanbot.log $ d # To detach from tmux # Later, to check on things: $ tmux attach -t fanbot_session 

We Pride Ourselves on Service

Finally I gave in. I had been putting off doing it as a service because it sounded hard and scary, even if it sounded like maybe it was the «right» way of doing things. Turns out, it’s not that bad. But, I hear what you are thinking: less talk, more examples! Let us say that we have the script below.

# /home/ryan/bigben.py import time def bong(): print("BONG! It is now <>".format(time.ctime())) if __name__ == "__main__": while True: bong() time.sleep(3600) # Tell the time once an hour 

Kind of silly, but it is the type of script that you’d like to run for a long time, possibly be auto-restarted, and see the logs later. OK. So we’ll only need one other file: the service’s Unit File! Create a file called bong.service . The .service is not really needed, but I think it’s nice to have.

; /home/ryan/bong.service [Unit] Description=Bong time telling service After=multi-user.target [Service] Type=idle ExecStart=/usr/local/bin/python /home/ryan/bigben.py [Install] WantedBy=multi-user.target 

Some explanation. The Unit section describes what this service is and how it should be run. The After variable tells this service when is allowed to run. After=multi-user.target essentially just means that this service will be ok to run once the server is ready for logging in. The Service section desribes what systemd (the service controller) will do and how. Type=idle tells it to only run our service once there are no more jobs to run. The ExecStart variable is the command we would want it to run. Note that absolute paths are required. Lastly, the Install section allows us to have our service auto-run at boot. The WantedBy variable tells it which already auto-run service our service should get started after.

Читайте также:  Встроить python в с

Copy our service file into the systemd service library, setup permissions, load it up, and let er rip!

$ sudo cp bong.service /lib/systemd/system/bong.service $ sudo chmod 644 /lib/systemd/system/bong.service $ sudo systemctl daemon-reload # Refresh the available service list $ sudo systemctl enable bong.service # Now watch your service auto run at bootup $ sudo reboot . $ sudo systemctl status bong.service # Blah blah blah you should see something happy and green # Want to check your logs? $ sudo journalctl -e -u bong.service # -e scrolls to the end of the logs # -u bong.service filters by the service that we care about # OR: sudo journalctl -f -u bong.service to follow, similar to tail -f 

So that’s really it! Create a service file, pop it in the right directory, and tell systemd about it. Not as hard as I thought! And you get auto-restarting, sane log files, easy status checks. As you can see, this applies not just to Python, but to any language, script, program, etc. that you can run from the command line. It should work with Ruby, Bash, Node, and more!

Bonus: Virtual Environments

If you’re one of the cool kids, you’re programming Python in a virtual environment. You may usually do something like the following to run your script by hand:

$ python -m venv .venv # Creating a virtual environment in .venv/ $ source .venv/bin/activate (.venv) $ which python /home/ryan/.venv/bin/python (.venv) $ python bigben.py . 

How, you ask me excitedly, do you get the service to run from within your virtual environment? It’s simpler than you might think! Remember this line in our bong.service file?

ExecStart=/usr/local/bin/python /home/ryan/bigben.py 

Simply point the python path to your virtual environment. It will automatically pick up the installed packages from there as well.

ExecStart=/home/ryan/.venv/bin/python /home/ryan/bigben.py 

Hopefully this post provides you a useful service! (Womp womp womp)

Источник

Запуск 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. Вы можете запустить любую программу с ним, независимо от языка программирования, на котором написана ваша программа.

Источник

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