9

I want to set up a cron job to run a python script, but it gives me this error:

RuntimeError: could not open display

This is because I import a module that requires me to open display (pylab, for example). Even though my script does not generates any pictures to display on the monitor.

Is there any way to let crontab run my jobs with display open (just as if I ssh -X into a machine)? I don't actually need to generate any graphs to the monitor. I just need to import my modules correctly.

CuriousMind
  • 15,168
  • 20
  • 82
  • 120
  • 3
    See http://stackoverflow.com/questions/4931376/generating-matplotlib-graphs-without-a-running-x-server – NPE Jun 13 '12 at 12:42
  • @aix do I have to use matplotlib API directly? I would prefer to use pylab.. and in general, is there a way to get around this issue in crontab? – CuriousMind Jun 13 '12 at 12:47
  • If you add `import matplotlib as mpl; mpl.use('Agg')` at the top of your script (before you import `pylab`), that'll likely fix the problem. – NPE Jun 13 '12 at 12:49
  • @aix thanks aix. Do you know in general, how to open the display in crontab? – CuriousMind Jun 13 '12 at 13:38
  • More fundamentally, this requires your computer to be configured to automatically run a display manager _and_ log you in automatically before it will work. There are other possible mechanisms but none of them will typically be enabled out of the box. See further https://stackoverflow.com/questions/22743548/cronjob-not-running which is a general `cron` troubleshooting question where I posted an answer with (slightly) more details about this topic. – tripleee Sep 15 '22 at 06:09

2 Answers2

6

You will need a valid DISPLAY and XAUTHORITY to use X-Programms in Cron!

To set DISPLAY is very easy, type in the Bash:

export DISPLAY=":0.0"

In order to get a valid XAUTHORITY you have to look for it. Under Debian/Gnome/gdm3 they are saved in var/run/gdm3/*/database I used the following script:

export DISPLAY=":0.0"
[ -z $USER ] && USER=$( who | awk '{ print $1 }' | sort | uniq >/tmp/test )
for I in /var/run/gdm3/*; do
    AUTHUSER="`echo $I | awk -F '-' '{ print $3 }'`"
    for J in $USER; do
        [ "${AUTHUSER}" = "${J}" ] || continue
        USER="$J"
        export XAUTHORITY="${I}/database" && break
    done
done
sudo -u ${USER} /Path/to/xProgramm

The Var $USER can be empty, than the script looks for a valid user, otherwise you can tell the script the var!

Michèle S.
  • 304
  • 1
  • 3
  • 7
2

You could also run your application in a framebuffer using xvfb or a similar tool:

Download or sudo apt-get install xvfb

Usage:

xvfb :1 -screen 0 800x600x8 & # WIDTHxHEIGHTxCOLORDEPTH
export DISPLAY=":1"
java application_name.jar 

or shorter:

xvfb-run -a -e /tmp/some/log/file.log /home/user/application.run

-a chooses a display number automatically, -e file specifies a logfile for error messages.

con-f-use
  • 3,772
  • 5
  • 39
  • 60