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()
2 Answers 2
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:
- use
cron
(older, simpler) - 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 yourcrontab
, then put asleep
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.
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] &
-
That didn't work for meLyra Orwell– Lyra Orwell2020年06月18日 20:41:03 +00:00Commented Jun 18, 2020 at 20:41
/usr/bin/python