Search code examples
pythonpython-3.xlinuxubuntucron

Python script runs fine from terminal but crashes when run from crontab


I have a simple python script that takes screenshots of a computer that is running Ubuntu. I want it to run automatically on startup, so I put @reboot python3 /bin/program.py in the non-sudo version of crontab.

The program works fine when run from terminal, but gives the error pyscreenshot.err.FailedBackendError. I put it in a try loop, and had it write all exceptions to a file, and that's how I found the error message, "All backends failed."

It has something to do with the program 'pyscreenshot' not working correctly.

import pyscreenshot as screen
import os
from numpy import random
from time import sleep
from os.path import expanduser


TMP_SCREEN_PATH = expanduser('~') + '/.UE/tmp.png'
LOG_FILE_PATH = expanduser('~') + '/.UE/log.txt'
GRAB_DELAY_RANGE = (1, 10)


def screenshot(save_path=TMP_SCREEN_PATH):
    img = screen.grab()
    img.save(save_path)


def delay(delay_range):
    sleep_time = random.randint(delay_range[0], delay_range[1])
    print(f"Sleeping for {sleep_time} seconds")
    sleep(sleep_time)


def main():
    try:
        while True:
            screenshot()
            delay(GRAB_DELAY_RANGE)
    except KeyboardInterrupt:
        print("Nope")
        main()
    except Exception as e:
        print(e)
        with open(LOG_FILE_PATH, 'a') as f:
            f.write(str(type(e))+str(e)+'\n')
        sleep(5)
        main()

f = open(LOG_FILE_PATH, 'w+')
f.write('Startup')
f.close()
main()

I need one of the following solutions:

  1. Simply fix the problem
  2. Another way to run a program at startup
  3. A different module to take screenshots with

Any help is appreciated, thanks


Solution

  • If the user that the cron job runs as is also logged in on the console (you mention a reboot, so I'm guessing that you have enabled autologin), then your cron job might work if you also add:

    os.environ["DISPLAY"] = ":0"
    

    This worked for me on Ubuntu in a test using cron and a simplified version of your script:

    import os
    import pyscreenshot as screen
    os.environ["DISPLAY"] = ":0"
    img = screen.grab()
    img.save("/tmp/test.png")
    

    If it doesn't work for you, then you might also have to try setting the value of the XAUTHORITY environment variable to the value found in the environment of the user's interactive processes, which could be extracted using the psutil package, but let's hope this isn't needed.