2

I am trying to run a python script when my Raspberry pi 4 boots. THis python script works when I run it directly, with no errors. I have edited the crontab file to do this as can be seen below:

# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
@reboot python /home/pi/FUZEGUI.py > /home/pi/FUZEGUIlog.txt

The log file has no information in it. I have tried a different method, rc.local;

# 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
printf "Launching FUZE GUI"
sudo python home/pi/FUZEGUI.py &
exit 0

But that doesn't work either. Script

#!/usr/bin/env python
try:
    import Tkinter as tk
except:
    import tkinter as tk
from PIL import Image, ImageTk
import time
import threading

root = tk.Tk()
root.attributes('-fullscreen', True)
root.geometry("800x800")

# Define Canvas
canvas = tk.Canvas(root, width=800, height=800)
canvas.grid(row=0, column=0)


# translates an rgb tuple of int to a tkinter friendly color code
def _from_rgb(rgb):
    return "#%02x%02x%02x" % rgb


# Called when user presses View Log button
def viewLogRaise():
    # Hide Previous Windows
    canvas.itemconfigure(logButtonWindow, state="hidden")
    canvas.itemconfigure(titleLabelWindow, state="hidden")
    # Open Closed Windows
    canvas.itemconfigure(backButtonWindow, state="normal")
    canvas.itemconfigure(logTextWindow, state="normal")
    canvas.itemconfigure(scrollbarWindow, state="normal")
    #I want to read the file continuously at this point.
    t =threading.Thread(target=readFile)
    t.start()

def backToMenu():
    # Hide Previous Windows
    canvas.itemconfigure(backButtonWindow, state="hidden")
    canvas.itemconfigure(logTextWindow, state="hidden")
    canvas.itemconfigure(scrollbarWindow, state="hidden")
    # Open Closed Windows
    canvas.itemconfigure(logButtonWindow, state="normal")
    canvas.itemconfigure(titleLabelWindow, state="normal")


def follow(thefile,reading):
    count= 0
    thefile.seek(0, 2)
    count += 1
    while reading == True:
        line = thefile.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line
def readFile():
    logfile = open("fast.log", "r")
    loglines = follow(logfile,True)
    for line in loglines:
        logText.insert(tk.END, line)
    


# Background
pathToGif = "redpoly4.jpg"
# red_background=Image.open("redBackground.gif")
backgroundImage = ImageTk.PhotoImage(file=pathToGif)
canvas.background = backgroundImage
bg = canvas.create_image(0, 0, anchor=tk.NW, image=backgroundImage)
titleLabel = tk.Label(root, fg="white", text="FUZE", borderwidth=2, relief="solid", bg=_from_rgb((239, 36, 37)),
                      font=("Courier", 100))
titleLabelWindow = canvas.create_window(400, 120, window=titleLabel)
logButton = tk.Button(root, fg="white", text="View Log", command=viewLogRaise, borderwidth=2, relief="raised",
                      bg=_from_rgb((239, 36, 37)), font=("Courier", 46))
logButtonWindow = canvas.create_window(400, 320, window=logButton)
backButton = tk.Button(root, fg="white", text="Back", command=backToMenu, borderwidth=2, relief="raised",
                       bg=_from_rgb((239, 36, 37)), font=("Courier", 20))
backButtonWindow = canvas.create_window(70, 360, window=backButton)



canvas.itemconfigure(backButtonWindow, state="hidden")
logText = tk.Text(root, bg="white", height=22, width=60, borderwidth=2, relief="solid")
logTextWindow = canvas.create_window(450, 208, window=logText)
# attach text widget to scrollbar
scrollbar = tk.Scrollbar(root)
scrollbar.grid(row=1,column=3)
scrollbarWindow = canvas.create_window(710,200, window=scrollbar)
logText.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=logText.yview)
canvas.itemconfigure(scrollbarWindow,state="hidden")
canvas.itemconfigure(logTextWindow, state="hidden")
root.mainloop()
4
  • do you run it as a user or root? what does the cron log say? do you have MTA to see if there is an error somewhere?
    – kyjanond
    Commented Jun 18, 2020 at 16:13
  • At startup there is a minimal environment with no $PATH so you need to use the actual location of binaries for example /usr/bin/python Commented Jun 18, 2020 at 19:58
  • 1
    Does this answer your question? What are the relative merits of putting start-up process in cron vs. rc.local?
    – Milliways
    Commented Jun 19, 2020 at 0:53
  • When you say "doesn't work" and "log has no information in it", does that mean that your script runs and the log file gets created, but remains empty? Commented Jun 30, 2020 at 12:21

2 Answers 2

5

You've run into a well-known limitation with cron. The question has been asked and answered here many times. This recent example highlights the two (at least two) choices you have:

  1. use cron (older, simpler)
  2. use systemd (newer, more complex)

The answer to your question in the context of cron usage is this:

If your script runs from the command line, but fails to run from @reboot in your crontab, then put a sleep command before your other command; e.g.:

@reboot (sleep 15; <your command here>)

You can also help yourself by redirecting your stderr stream to a file - otherwise any error messages encountered will go to the "bit bucket":

@reboot (sleep 15; <your command here>) >> /home/pi/cronjoblog.txt 2>&1

>> /home/pi/cronjoblog.txt is a "redirection"; what goes to the screen, is re-directed to the specified file.

stderr is the "error stream" & is numbered "2" by convention

stdout is the "normal output", numbered "1" by convention

2>&1 is an obtuse way of telling your system that you want your error messages to be "merged" with your normal output.

0

If my understanding is correct, since you want this to occur prior to logging in (on boot) you will not have input your password to determine user/root, so i would remove the sudo in the argument.

In rc.local, instead of sudo python ... & try inputting the full path to python. I had a similar issue, and this worked for me: sudo /usr/bin/python [PATH TO SCRIPT.py] &

1
  • That didn't work for me Commented Jun 18, 2020 at 20:41

Your Answer

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

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