Improperly set display when running a root crontab job involving GUI

When running the script below from my local user crontab, with sudo before /usr/bin/FreeFileSync (last script’s line), a small progress window opens on my GUI and things go well. The only thing is I have to input my sudo passwd, which makes it interactive and somewhat unwieldly.

Root privileges are necessary to run FFS, otherwise it complains about not having rights to get to some directories and files being backed up.

#!/bin/bash
# define default display and pass it on to any child process
# from within the running shell
DISPLAY=:0.0
export DISPLAY

/usr/bin/FreeFileSync /home/user/bu-1.ffs_batch 2>  
   /home/user/bu-1.ffs_log 

When I call the same script from my root crontab with sudo crontab -e, FreeFileSync never gets to run because of the following error:

$ cat /home/user/bu-1.ffs_log
16:35:01: Error: Unable to initialize GTK+, is DISPLAY set properly?

As can be seen, I haveexport DISPLAY=:0.0 within the script and my root crontab file is equipped with:

$ sudo crontab -e | head -4
[sudo] password for user:

1 SHELL=/bin/bash
2 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
3 HOME=/
4 MAILTO=root

Can someone help troubleshooting the error ?

EDIT: Could it be that running this from root’s crontab fails because user root as no open session and therefore no stdout to which to display?
Can I circumvent that difficulty by asking root to display to a current user’s session’s stdout? It seems to be worth a shot if doable; if so how do I do that?

Asked By: Cbhihe

||

You could configure sudo to not need a password for a particular
command
and go back to using a non-root cron.
For this, assuming a user id of “user” wants to run the command FreeFileSync as root, create a file /etc/sudoers.d/user with

user ALL = NOPASSWD: /usr/bin/FreeFileSync

The command must be given with a full pathname. If you don’t explicitly list the args to the command, then any args will be allowed by sudo.
Replace ALL by your hostname (not localhost) to be more secure.

This assumes file /etc/sudoers has the line: (note # is not a comment)

#includedir /etc/sudoers.d

If not, then just add the user entry to /etc/sudoers. Be careful editing this file: use visudo, or ensure you have root logged in or a shell running root to be able to do any repairs.

Your user crontab entry can then just have the command:

DISPLAY=:0.0 sudo /usr/bin/FreeFileSync /home/user/bu-1.ffs_batch 2>/home/user/bu-1.ffs_log

ubuntu sudo will preserve some environment variables for the command including DISPLAY and HOME (see output of sudo sudo -V) so the program will be able to read the ~/.Xauthority file (continue reading for details).


Alternatively, to keep using a root crontab:
if when you do ps alxww|grep X you find your X11 server running with an -auth option, something like this:

/usr/bin/X :0 ... -auth /var/run/lightdm/root/:0 ...

it means clients must connect using the secret in the file /var/run/lightdm/root/:0. This file holds a copy of the secret in the user’s ~/.Xauthority file.
This “secret” is just an arbitrary random number.
If you are root you can read both files, so your client can simply provide in the environment:

XAUTHORITY=/var/run/lightdm/root/:0

Alternatively, you can set the HOME to that of the user of the display,
HOME=/home/user so that the right .Xauthority file is found there.

Alternatively, you can export the secret from this to root’s home:

xauth -f /home/user/.Xauthority nextract - localhost/unix:0 | sudo xauth -f /root/.Xauthority nmerge -

and then XAUTHORITY=/root/.Xauthority or just HOME=/root.

Answered By: meuh
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.