Search code examples
pythonlinuxraspberry-pisystemdboot

Executing multiple Python scripts in a particular order using systemd


I am running Raspbian GNU Linux (9) Stretch, on my Raspberry Pi 3.

Project Overview

  1. Python script which makes use of 2 inputs to the Pi. Calculations are performed based on these inputs, and values are stored in a database.
  2. A separate Django website which reads values from this database and updates the content of the web page.

Django Server run using: /home/pi/mysite/manage.py runserver 127.0.0.1:8000

Python Script located at: /home/pi/Desktop/myscript.py

On startup I would like to first make sure that my Django server is up and running and then start my python script.

What I have done so far

Initially I started by trying to get the python script to run on startup. To do this I am using a simple systemd service as follows.

[Unit]
Description=My script

[Service]
ExecStart=/usr/bin/python3 /home/pi/Desktop/myscript.py

[Install]
WantedBy=multi-user.target

This runs without error and initiates the python script on startup.

However, I cannot get my Django server up and running inside the same systemd service since only one ExecStart is allowed. I need both to be run in parallel, but the Django up to be started first.

I think I am looking for something like Wants.

I came across the following question, but I have not managed to implement a working solution. However most of the information is relevant.

if Type=simple in your unit file, you can only specify one ExecStart, but you can add as many ExecStartPre,ExecStartPost, but none of this is suited for long running commands, because they are executed serially and everything one start is killed before starting the next one. If Type=oneshot you can specify multiple ExecStart, they run serially not in parallel.

I tried creating another unit as follows:

sudo systemctl edit --force mysite.service


[Unit]
Description=my site

[Service]
ExecStart=/usr/bin/python /home/pi/mysite/manage.py runserver 127.0.0.1:8000

[Install]
WantedBy=multi-user.target

This works on it's own.

However I need both to be run in parallel, but the Django up to be started first.

That's why I edited myscript.serviceas follows:

[Unit]
Description=My script

[Service]
ExecStart=/usr/bin/python3 /home/pi/Desktop/Scripts/oee_calc.py
Wants=mysite.service

[Install]
WantedBy=multi-user.target

The python script is initiated, but the django server is not.

Any suggestions on how this can be done?


Solution

  • What you need are 2 different systemd unit and define the dependency using requires

    [Unit]
    Description=My script
    
    [Service]
    ExecStart=/usr/bin/python3 /home/pi/Desktop/myscript.py
    Requires=dhangioserver.service 
    
    [Install]
    WantedBy=multi-user.target
    

    It will also be good to specify RequiredBy in DjangoService unit

    There is a related spec called Wants which differs only in whether service should continue if dependendcy fails or not. Looking at your requirement , it looks like you need Requires and not Wants