Cron job to run python script at reboot does not work

I am new to linux and I read and followed many instructions to run a python script at reboot but non of them worked:

this is the command I want to run:

/usr/bin/python3 /home/am/projects/AMAcc/map.py

I used crontab -e and added

@reboot /usr/bin/python3 /home/am/projects/AMAcc/map.py

I tried sudo crontab -e and added the same command

I even edited /etc/crontab file and added above command.

Tried adding #!/usr/bin/python3 at top of my python code and changing its permissions like: sudo chmod a+x map.py

As documents suggested that all users would be able to run cron jobs if cron.deny file exists but its empty, so I tried creating empty cron.deny files in both /etc/cron.deny and /usr/lib/cron/cron.deny. But still no luck running the cron job.

What am I doing worng?


To execute any GUI application from Cron you should export few desktop environment variables. In most cases it is quite enough to export the current $DISPLAY value. I would suggest you to create an additional startup (bash) script, that will launch your application.

In this answer is provided robust approach how to find and export the current user's $DISPLAY value. But there is a problem. While the user is not logged into the DE the $DISPLAY value is not set. Sо we could add an additional condition, like it is made in this answers:

# Get the value of the $DISPLAY variable for the current user. Unset it just in case this is a `ssh -X` connection
unset DISPLAY;
while [ "$DISPLAY" == "" ]; do
        export DISPLAY=$(w "$USER" | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}' 2>/dev/null) && sleep 3
done
  • This condition works in all other cases, but it fails within @reboot Cron jobs and I can't figure out the reason. So, within the script below is used another approach to check whether the user is logged in Mate.

Some applications need and few more variables (for example see this and this answers) as $DBUS_SESSION_BUS_ADDRESS and $DESKTOP_SESSION. In my opinion the best approach is to find the current user's desktop session process within the directory /proc (process information pseudo-filesystem) and export all variables from the file environ that is inside /proc/process-number.

I've created a small project, called cron-gui-launcher dedicated to this. It works but it's not tested for all user's cases (like the current). Here I've extracted the essential part that refers to Mate DE and made the modification mentioned above.

1. Create an executable file with this content:

#!/bin/bash -e

# Check whether the user is logged in Mate
while [ -z "$(pgrep mate-session -n -U $UID)" ]; do
        sleep 3 && count=$((count+1)) && echo "$count" > /tmp/mate-cron.log
done

# Get the content of the Current-Desktop-Session Environment File as an array:
EnvVarList=`cat -e "/proc/$(pgrep mate-session -n -U $UID)/environ" | sed 's/\^@/\n/g'`

# Export the Current-Desktop-Session Environment Variables:
for EnvVar in $EnvVarList; do
        echo "$EnvVar" >> /tmp/mate-cron.log
        export "$EnvVar"
done

# Execute the list of the input commands
nohup "${1}" >/dev/null 2>&1 &

exit 0
  • Better version of the scrip: How can I show notify-send messages triggered by crontab?

2. Now in crontab use:

@reboot /path-to-the/script "your-application"

3. Notes:

  • This script shall not work with root's crontab. Because of the variables $UID and $USER. You could replace them wit the certain user's UID and NAME.

  • For other DE change mate-session from this part $(pgrep mate-session -n -U $UID) with the name of the process of the other DE, for example gnome-session.

  • Maybe for GUI applications, that are executed within system startup it is better idea to create an entry within Startup Applications. For Mate DE: Control Centre > Personal > Startup Applications (source).

4. Here is presented how the script works:

enter image description here