UglyTeapot
UglyTeapot

Reputation: 393

RPi running a GPIO script on boot

I have a script that needs to run when the Raspberry Pi boots (Raspbian- latest version, the Pi is a model B+). The script needs to be none-blocking, and accesses the GPIO pins, so needs to run as root. It's also Python3.

I have tried to set the script up as a service, and put it in init.d to run on boot.

This is my service:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          myservice
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Put a short description of the service here
# Description:       Put a long description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/home/pi
DAEMON=$DIR/server2.py
DAEMON_NAME=bottleserver

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;
    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;

esac
exit 0

I can run it by typing

sudo /etc/init.d/bottleserver.sh start

I have done

sudo update-rc.d bottleservice.sh defaults

in an effort to set up the links so things run on boot. If I check the status of these links I get:

ls -l /etc/rc?.d/*bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc0.d/K01bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc1.d/K01bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc2.d/S02bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc3.d/S02bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc4.d/S02bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc5.d/S02bottleserver.sh -> ../init.d/bottleserver.sh
lrwxrwxrwx 1 root root 25 Oct 2 20:56 /etc/rc6.d/K01bottleserver.sh -> ../init.d/bottleserver.sh

so some definitely exist. However it doesn't start on boot. I don't get any errors (the script itself- server2.py, has error logging to a file), but it also doesn't run. I assume it is something to do with permissions? (GPIO stuff usually is).

Any ideas on what I can try?

The service was set up following these instructions: Getting a Python script to run in the background (as a service) on boot. I'm not really very good on Linux (have used it for years.. but I never had to solder bits to the PC...)

Alternatively, better ideas on how to run a script needed GPIO access when the Pi boots?

Upvotes: 1

Views: 2692

Answers (1)

dentex
dentex

Reputation: 3263

I'm not sure about what this "bottleserver" actually does for you, but if it needs to do something requiring a working network connection, there are possibilities that it starts and then it suddenly exits with an error status. This can be due to the fact that on startup it can't find the active connection and this would explain also why, a few moments after, you can successfully start it manually.

This is exactly the case I encountered while using ngrok (and actually I was searching for some more info when I found your question).

Instead of using the "service" approach, I started using the afterscript = $PATH_TO_YOUR_SCRIPT section of /etc/wicd/wired-settings.conf and /etc/wicd/wireless-settings.conf (I'm using wicd to manage networks). Before using this solution, I tried adding a post-up script to /etc/network/interfaces. It's the same: I found anyway that I always need about one minute of delay (using simply a sleep 60) in launching any script that relies on the network, even if they are executed after the connection by the chosen network manager.

To have a second alternative, that I find more reliable, you could switch back to crontab, scheduling your script to be executed every X minutes (say */3 * * * * $PATH_TO_YOUR_SCRIPT) and adding to your script a section where you check if it's already running. Something like:

pidof $YOUR_COMMAND # returns nothing if no PID exists
if (( $? )); then
  # Failure
  # rest of your script, launch your network stuff
else
  # Success, NOTHING TO DO
fi
exit 0

This will also have the advantage of a continuous check if the script it's running, relaunching it when needed.

I hope this helps, bye.

Upvotes: 1

Related Questions