How To Autorun A Python Script On Boot Using systemd

22

With the latest release of Raspbian I started to struggle to autorun Python scripts on bootup using Cron or rc.local. It appears that the Raspbian boot sequence has changed and these processes run at different points in that sequence. How much of an issue this is depends on what your Python script is trying to do and what resources it needs.

The point at which your Python script is run in the startup sequence is vital if your script relies on any system features being available at that point in time. For me this often includes :

  • Network is connected and available
  • The /home/pi directory is mounted and read for use
  • System time has been updated by NTP

I decided to use “systemd” as this seems to the recommended way of launching custom features and lots of Linux distributions are adopting it. systemd is a software suite for central management and configuration of a Linux system and aims to replace other popular tools that previously fulfilled this role. As a result it seems to have plenty of enemies but you can read all about the controversy on the systemd Wikipedia page.

systemd is quite scary. Or easy. Depending on your level of experience. My goal was just to get it to launch one of my scripts with the minimum of fuss and without having to do too much typing I didn’t understand.

Step 1 – Your Python Script

My example script was stored in the /home/pi directory and named “myscript.py”. Obviously your script can be called something else but keep an eye on where it is referenced in the commands and text below.

Step 2 – Create A Unit File

Next we will create a configuration file (aka a unit file) that tells systemd what we want it to do and when :

sudo nano /lib/systemd/system/myscript.service

Add in the following text :

[Unit]
Description=My Script Service
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/bin/python /home/pi/myscript.py

[Install]
WantedBy=multi-user.target

You can save and exit the nano editor using [CTRL-X], [Y] then [ENTER].

This defines a new service called “My Script Service” and we are requesting that it is launched once the multi-user environment is available. The “ExecStart” parameter is used to specify the command we want to run. The “Type” is set to “idle” ensures the ExecStart command is only run when everything else has loaded. For my GPIO based scripts the default type of “simple” didn’t work.

Note that the paths are absolute and fully define the location of Python as well as the location of our Python script.

In order to store the script’s text output in a log file you can change the ExecStart line to :

ExecStart=/usr/bin/python /home/pi/myscript.py > /home/pi/myscript.log 2>&1

The permission on the unit file needs to be set to 644 :

sudo chmod 644 /lib/systemd/system/myscript.service

Step 3 – Configure systemd

Now the unit file has been defined we can tell systemd to start it during the boot sequence :

sudo systemctl daemon-reload
 sudo systemctl enable myscript.service

Reboot the Pi and your custom service should run :

sudo reboot

Step 4 – Check status of your service

You can check the status of your service using :

sudo systemctl status myscript.service

Other useful resources for systemd

Share.

22 Comments

  1. Just a little tweak: by default, std out/err are directed to journalctl (systemd’s component that replaces syslog); but with a python3 script, the output is double-buffered, which means it won’t appear normally in the logs (output will be flushed from time to time, which is not precictible), so it is best to launch python3 scripts with the -u flag.

  2. Hey i’ve tried this method and many other methods online to auto run my python script. My python script records a video and uses a for loop to save multiple video files over a designated amount of time. When I used your method (along with others) the LED of the camera turns on as if the script did in fact auto run but I cannot find any video files afterwards! Why is this happening? I’ve tried so many ways.

  3. I’ve been tearing my hair out trying to get my Sense HAT to log to a google spreadsheet on boot up, this finally helped me crack it!. Many thanks for this.

    One tip I have found, is that if you are reading from a file (like I am with my OAuth JSON) then you also need to provide a full path in the script as well. Discovered in the error messages in systemctl status, this might help Noah.

  4. Thanks for this.

    Spent a day trying to get this to work, until I found this tutorial.

    Others seem to be missing the

    sudo systemctl daemon-reload
    sudo systemctl enable myscript.service

    commands, which is vital to get the unit file to actually run.

    Cheers, Ian

  5. Thanks, this has been a huge help for me, a Linux and Pi newbie.

    For other newbies, let’s note that

    sudo chmod644 /lib/systemd/system/myscript.service

    should be

    sudo chmod 644 /lib/systemd/system/myscript.service

  6. I have 3 Python programs that I want to start at reboot. Can one unit file be used to start the 3 Python programs at startup? Do I need a separate unit file for each Python program?

  7. This is great, thanks.

    Now my question. What do you do in order to stop a script? I have my running on an infinite loop. Every 10 minutes it looks at a particular timeline for new tweets. But how do stop the script running to make changes?

    • This technique is really only suitable for a script that runs once. To run a script every 10 minutes I would use cron.

  8. Nice job. Thanks.

    The reboot in step 3 is unnecessary. After ‘sudo systemctl enable myscript.service’ just start the service via: ‘sudo systemctl start myscript.service’.

  9. I followed all the steps but i get an error message after typing “sudo systemctl enable myscript.service” it says no such file or service exists.

    • That error message means you either haven’t created the “myscript.service” file, or you called it something else or you created it in the wrong place. Use :
      cd /lib/systemd/system/my*.service
      to check that it exists in the correct directory and is named “myscript.service”.

  10. my python script imports modules installed using pip . this module is not getting imported when running through systemd. but when i run the python script it runs without any problems

  11. hello i cant see any log file created. how can i see my output? its not showing in the terminal also even without adding that log file line

Leave A Reply