How To Autorun A Python Script On Boot Using systemd


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 “”. 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 :

Description=My Script Service

ExecStart=/usr/bin/python /home/pi/


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/ > /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



  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

    • Most tutorials I found have this one…
      systemctl enable myscript.service
      but they don’t have this one…
      systemctl daemon-reload

      The fact that I didn’t have ‘systemctl daemon-reload’ is most likely why I never got systemd to work in Raspbian Jessie.

      I switched to Arch Linux on the Raspberry Pi, and I got systemd to work fine. In Arch LInux I have never needed to use ‘systemctl daemon-reload’.


  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.

    • systemctl stop myscript service
      systemctl start myscript service

      And… In [service] section you can control the restart:
      Restart=on-failure | always
      …Configures the time to sleep before restarting a service (as configured with Restart=). Takes a unit-less value in seconds, or a time span value such as “5min 20s”. Defaults to 100ms.

  8. Somehow it can’t start my Script. The log says: -bash: /home/pi/folder/ Permission denied
    But everyone has access (chmod 777) to the files:, script.log, script.json.

    And I have also run this Command: sudo chmod 644 /lib/systemd/system/myscript.service

    How can I fix the Problem?

  9. 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’.

  10. 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”.

  11. Thanks for sharing! Working as expected! But not the log file. However I used:
    ExecStart=/usr/bin/python /home/pi/ > /home/pi/myscript.log 2>1
    Note the difference it’s 2>1 and it’s now logging in /var/log/messages and to see it, just run
    journalctl -u myscript

  12. 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

  13. Hey nice guide! One gotcha: for user-defined services, they should live in /etc/systemd/system. The /lib/ location (or /usr/lib on some liinux distros) shouldn’t be touched by humans in general. As a broad rule, the only spots that humans should modify are /etc /home and /var (and sometimes /opt or /srv)

  14. 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

  15. Thanks for this, I’m a n00b but trying to learn. getting very confused by older how-tos when I’m using Jessie.
    Question, would this method be ok to launch another program at boot? I would like to start TTYMidi in the background by using

    ExecStart=/usr/local/bin/ttymidi -s /dev/ttyAMA0 -b 38400 -v &

    I’ve read about editing rc.local but want to find the ‘right’ way 🙂

  16. I have the same problem, as Faizan had – log file is not working. When I just run command from ExecStart in terminal everything work fine, but if it runs from systemctl, log file doesn’t fills.

  17. Hi Matt,

    A good explanation and tutorial and it works just fine.

    Which bit is the best bit to delete/amend to stop it running on boot? I need to make some tweeks to the script but don’t want the old version running alongside the newer one. I’ve tried changing the name of the unit file slightly but that hasn’t stopped it running on reboot.

  18. My application is written in Kivy and runs on pi3. If started manually runs ok but with Autorun touch buttons are not working. It was running ok on pi2 but I had to switch to pi3 to improve performance. I have tried crontab, rc local, profile with the same results. Any idea how to fix this? Again all the methods work fine with pi2 but with pi3 somehow Kivy is not initializing properly.

  19. Brilliant! After my init.d script broke (called a python script to listen to a GPIO pin and set a GPIO pin) when using the latest Raspbian release, I found your explanation of the why, and the solution. I’ll stick with systemd unit files from on.
    Thanks again.

  20. This has been a great, and succinct methodology to get a service running. It worked great first time, thank you.

    A problem I have encountered, which you may be able to shed a little light on, is I can find no evidence of a log file being created, despite having this line in my .service file:

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

    The Python script is a simple counter updates every 10 seconds and prints the counter + time to the screen. I expected the log file to contain this output.

    Any pointers or should I start exploring the journal system?

    Many thanks

  21. Thanks, this was very helpful and got me up and running fast! Only thing I had to add was under the [Service] section, I added a WorkingDirectory line so my log file and INI file are saved in the same folder as my script. Without that, they were being saved to the root directory. So for example:

    ExecStart=/usr/bin/python /home/pi/

  22. Thanks for the awesome tutorial bro. Can you please tell me how can I run multiple python scripts at startup using this method?

  23. + 1 been pulling my hair out with cron @reboot, rc.local and init.d after hours trying to get those methods working, this was running in about 2 minutes. Thanks so much!

  24. thank you, this was helpfull but I did add 2 lines into [Service] section

    and change exec line

    ExecStart=/bin/bash -c ‘/usr/bin/python3 /home/pi/ > /home/pi/me.log 2>&1’

    • sorry, I forgot to mentioned:

      #1 those two lines doing that script is running by user “pi” in its home directory

      #2 that change on exec make really redirect output to the file

  25. Few tips, mainly for any recent readers 🙂

    1. The systemd docs have this to say about ExecStart – “redirection using “<", "<“, and “>>”, pipes using “|”, running programs in the background using “&”, and other elements of shell syntax are not supported.”
    So for logging you should instead look at using the config “StandardOutput=” , or stick with the default (journal).

    2. And about “Type=idle” – “Note that this type is useful only to improve console output, it is not useful as a general unit ordering tool”, you probably need to look at using “After=”


  26. Thanks for the tute.

    Just a note that user services should be defined in /etc/systemd/user/servicename.service and not be dropped in the system location you have specified. I have just done this and it still functions exactly as you describe.

Leave A Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.