4

I have two different Python scripts I'd like to run at start-up on my Raspberry Pi A+. Both work perfectly if I run them via sudo python filename.py. I can get the first one to run, but not the second one in the rc.local below. It doesn't matter if I switch them or not, only the first one runs, and only if I don't have & at the end.

Here is my /etc/rc.local:

(Notice the commented-out version - it doesn't work either; but the hardware clock does...)

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi


python /home/pi/ZBA_Timelapse/shutdown.py
python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py

###python /home/ZBA_Timelapse/shutdown.py &
###(sleep 30; python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py) &

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1_new_device
sudo hwclock -s

exit 0

EDIT:

I tried appending & to the end of the line per SlySven's answer, but it still does nothing. Both Python scripts are infinite loop programs, so I thought I'd try another approach: a shell script. The newly tried rc.local:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

./home/pi/ZBA_Timelapse/startup.sh
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1_new_device
sudo hwclock -s

exit 0

startup.sh looks like this:

#!/bin/bash/
sudo python /home/pi/ZBA_Timelapse/shutdown.py &
sudo python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py &

After both of those were set, I used sudo chmod +x /home/pi/ZBA_Timelapse/startup.sh to make startup.sh executable and rebooted. After reboot I used cd ZBA_Timelapse and ./startup.sh to successfully test the shell script. It worked great. Both Python scripts executed and worked like they should.

I still had no luck on auto-starting both Python scripts on boot. What am I doing wrong here?

4
  • you might wanna & at the end of each execution so that both can run in parallel, ie, instead of your current lines, use python /home/pi/ZBA_Timelapse/shutdown.py & python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py & Hope it helps. For more info on using & in linux, read this question (and answers of course :P) superuser.com/questions/152688/… Dec 8, 2015 at 7:16
  • Thanks, but that doesn't work either (hence the commented out section in the rc.local).
    – pyreflos
    Dec 8, 2015 at 9:44
  • If something mysteriously "doesn't run" from rc.local, you should log the output of the command to see what is happening; I usually do this with an explicit subshell so (sudo foobar) &> /var/log/foobar &. Which version of Raspbian are you running, BTW? If it is jessie I can give you an example of how to do this as a discrete service w/ systemd (which is sort of simpler than it is with sysv on wheezy).
    – goldilocks
    Dec 8, 2015 at 11:28
  • I replaced python /home/... in the rc.local with (python /home/pi/ZBA_Timelapse/shutdown.py) &> /var/log/timelapse.log & & (sleep 30 && python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py) &> /var/log/timelapse.log & The log file is empty after a reboot. And the python scripts still don't run.
    – pyreflos
    Dec 8, 2015 at 20:13

5 Answers 5

1

Try:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi


python /home/pi/ZBA_Timelapse/shutdown.py &
python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py &

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1_new_device
sudo hwclock -s

exit 0

The commented out code with the sleep might work better as:

python /home/ZBA_Timelapse/shutdown.py &
sleep 30 && python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py &

One point to note is "do either of the python scripts in /home/ZBA_Timelapse/ take input from stdin"? If so, they will stop when they get to that point, waiting in the background for input until they are brought back to the foreground - and as this is a non-interactive script run during multi-level startup - they will hang around for ever waiting for input that never comes...

1
  • I tried appending & to the end of the line, but it still does nothing. Both python scripts are infinite loop programs (basically While True), one of which has a GPIO interrupt. I'm not sure what a stdin condition is... I also tried replacing the python calls to a shell script that executed both. The shell script work well when run directly, but does not auto-start on boot. What am I doing wrong here? I also edit the question to show the shell script, but I can't figure out how to approve reviews...
    – pyreflos
    Dec 8, 2015 at 9:40
0

Alright, thanks everyone for the suggestions in the other answers, but this is how I got it to work: I added python /home/pi/ZBA_Timelapse/startup.py to the rc.local, then I created a single python file that starts multiple python files in different threads.

This is what rc.local looks like:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

python /home/pi/ZBA_Timelapse/startup.py

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1_new_device
sudo hwclock -s

exit 0

This is what startup.py looks like:

import time
from threading
import os

def startprgm(i):
    print "Running thread %d" % i
    if (i == 0):
        time.sleep(1)
        print('Running: shutdown.py')
        os.system("sudo python /home/pi/ZBA_Timelapse/shutdown.py")
    elif (i == 1):
        print('Running: ZBA_Timelapse.py')
        time.sleep(1)
        os.system("sudo python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py")
    else:
        pass

for i in range(2):
    t = threasding.Thread(target=startprgm, args=(i,))
    t.start()

Obviously, I could increase the number of programs running by increasing i and adding another elif... It's not particularly pretty, but it works.

1
0

Use:

nohup python /home/pi/ZBA_Timelapse/shutdown.py >/dev/null 2>&1 &
nohup python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py >/dev/null 2>&1 &

This will pipe output to /dev/null (aka nowhere) and not create a nohup.out file.

Or you could try with "screen":

man screen

Your command should look like:

screen -d -m /home/pi/ZBA_Timelapse/ZBA_Timelapse.py
4
  • This did not work either. I don't seem to have screen. Can you point me towards it?
    – pyreflos
    Dec 8, 2015 at 21:01
  • Are the scripts executable ? (Do a 'chmod +x 'on both files) also see if screen is in the repo maybe. Or try without the piping to dev null, just with nohup at the beginning and the & at the end
    – Havnar
    Dec 8, 2015 at 21:11
  • I made the scripts executable, but to no avail. Which makes sense... they're written in python, not shell scripts. I installed screen, but haven't gotten a chance to dig through it yet.
    – pyreflos
    Dec 9, 2015 at 20:27
  • I've updated my answer
    – Havnar
    Dec 10, 2015 at 10:01
0

The environment variables inherited when init runs rc.local are different from the environment you have when you login.

This sounds like a candidate to be service, so learning about services would help you.

0
from threading import Thread
import time
import os


def startprgm(i):
    print "Running thread %d" % i
    if (i == 0):
        time.sleep(1)
        print('Running: shutdown.py')
        os.system("sudo python /home/pi/ZBA_Timelapse/shutdown.py")
    elif (i == 1):
        print('Running: ZBA_Timelapse.py')
        time.sleep(1)
        os.system("sudo python /home/pi/ZBA_Timelapse/ZBA_Timelapse.py")
    else:
        pass

for i in range(2):
    t = Thread(target=startprgm, args=(i,))
    t.start()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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