6

What I tried:

  • crontab -e
  • creating a desktop entry at /home/pi/.config/autostart
  • edit /etc/rc.local

My python script:

import os
from gpiozero import Button
from time import sleep
from pynput.keyboard import Key, Controller

k = Controller()
shutdown = Button(2)
reld = Button(3)

while True:
    if shutdown.is_pressed:
        print("shutdown")
        os.system("sudo shutdown -h now")
    if reld.is_pressed:
        print("reload")
        k.press(Key.ctrl)
        k.press(Key.f5)
        k.release(Key.f5)
        k.release(Key.ctrl)
    sleep(0.2)

I tried to start the script with this command which works fine in the therminal:

python3 /home/pi/Documents/script.py
3
  • Hot in the therminal? Commented Feb 25, 2020 at 12:32
  • You could alternatively use systemd to start your Python code when a button is pressed, see github.com/ali1234/systemd-gpio.
    – MSalters
    Commented Feb 25, 2020 at 15:20
  • 1
    How can a 8 year old post about an obsolete OS be a duplicate?
    – Milliways
    Commented Mar 24, 2020 at 11:27

5 Answers 5

14

With the endless loop in the script it seems that it should run endless in the background as service. Running services nowadays is done with systemd using unit files. Just create a new service with:

rpi ~$ sudo systemctl --force --full edit myscript.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=My script to monitor the shutdown button
After=multi-user.target

[Service]
ExecStart=/usr/bin/python3 /home/pi/Documents/script.py

[Install]
WantedBy=multi-user.target

Enable and monitor the service with:

rpi ~$ sudo systemctl enable --now myscript.service
rpi ~$ systemctl status myscript.service

The output of the print() statements you will find in the journal:

rpi ~$ journalctl -b -e
1
  • 3
    If the file has an appropriate shebang line the execstart can be simplified to reference just the script. This allows the service to not need to know that it's dealing with python, allowing you to swap the script out for an implementation in another language without having to hunt down how the service is set up
    – Cruncher
    Commented Feb 25, 2020 at 14:34
1

Script file

1. Create a bash script file for running the code:

nano /etc/systemd/system/test.sh

Also, it's not important where you create the file and what name you set.

2. Add the line below to that script file:

#!/bin/bash
sleep 5 && python3 /home/pi/Documents/script.py;  

I set a 5-sec sleep because of skipping any error which faces if you run a python file immediately.


Crontab

1. Open the crontab by:

crontab -e

If the vi editor bothers you, you can open the crontab by:

export VISUAL=nano; crontab -e  

2. Then, add this line at end of the file:

@reboot bash /etc/systemd/system/his-chat-client.sh  

Optional

If you want to check the log of the code, change the script file to:

#!/bin/bash
sleep 5 && python3 /home/pi/Documents/script.py |& tee -a /var/log/test.log;

You can remove the log weekly if you are concern about sd-card capacity. Just add this line at the end of the crontab:

5 8 * * 5 > /var/log/test.log  

It will empty the test.log file each Friday at 08:05 am.

1

First of all, try to understand what's wrong. What you can do:

  • log the output of your cron jobs to a log file or:
  • run your script in a GNU screen session, and log the console output to a file
  • and also the most obvious, add some exception handling in your code, log errors to a file so you can investigate them. If you had exception handling, then you would likely already have some clues about what is happening.

In the present case though the most likely reason is that the cron has no PATH variable set. It is a very common issue with cron jobs. Either set the PATH in your crontab, or add the full path to python3, on the Raspberry PI that should be: /usr/bin/python3 (you can run which python3 to check). So your cron line should look like this:

/usr/bin/python3 /home/pi/Documents/script.py

It is also possible that your script depends on certain services that are not yet loaded at the moment the script is invoked. This is a common pitfall when running startup scripts: many scripts assume for example that networking will be ready but are running too early.

What you can do: write your own Systemd service for your script (example). Then you specify that your service depends on another service and should not be run until all dependencies are satisfied.

I guess from your code that you are dealing with physical push buttons that trigger actions (sorry I am not familiar with all those modules). It seems to me that a service like triggerhappy could address your need nicely (although I haven't used it with GPIO so far). It is available as a standard package in Linux distros.

1

This will run under cron if you keep cron's limitations in mind. You could try this:

crontab -e 
# in the editor, add the following line to your crontab: 
@reboot ( /bin/sleep 30; /usr/bin/python3 /home/pi/Documents/script.py  >> /home/pi/cronjoblog 2>&1)

Summary of crontab entry:

  • 30 sec of sleep are completed before cron attempts to run your script. This overcomes one of cron's limitations. Note that 30 sec may be more sleep than what's required (or less, but that's doubtful), so you can try reducing that if it's inconvenient to wait 30 secs.

  • complete file specs for everything is overkill, but it's best to err on the side of caution until you learn what cron's environment is.

  • any stderr output from your script is redirected to a log file at /home/pi/cronjoblog; this will help you if further debugging is required.

1

You should make a bash script that launches the python script such as:

#!/bin/bash
sudo python3 /path/to/python/file.py

make sure to make it executable with chmod +x after creation of script place the bash file in

/etc/init.d/

then to set it to start up automatically

sudo update-rc.d celeryd defaults
sudo update-rc.d celeryd enable

that is it

Not the answer you're looking for? Browse other questions tagged or ask your own question.