Cron GUI Dialog – How to Display a Zenity Dialog After Root Cron Task Completion

crondialogguikubuntuzenity

I have a simple periodic cron task that must run as root. I want to use Zenity (or similar) to display a GUI informational dialog to user 1000 (or logged in user or all users) when the cron task finishes.

I'm looking for a simple, easy, quick solution. I'll adapt to the requirements of such a simple solution.

Here's where I am so far. My bash script works fine if run manually, but when Anacron runs it, nothing happens and I see Gtk-WARNING **: cannot open display in the logs. I hoped it would display my dialog to the user after being run by cron.

I realize (after reading related questions) that cron needs to be decoupled from the GUI. If user 1000 is not logged in, I could take one of several options:

  1. do nothing (possibly acceptable because I want to keep it simple)
  2. display the dialog with completion message to the user when they log in next time (best)
  3. display some other type of notification (NOTE: the computer is a desktop system without a mail server installed)

I found these related questions:
x11 – Anacron job complains "Gtk-WARNING **: cannot open display" – Unix & Linux Stack Exchange
Anacron job complains "Gtk-WARNING **: cannot open display"

shell – How to pass data outside process for zenity progress? – Unix & Linux Stack Exchange
How to pass data outside process for zenity progress?

Example Code (from other question which is essentially the same as mine):

#!/bin/bash
# Backs up the local filesystem on the external HDD

sleep 60

DISPLAY=:0.0

zenity --question --text "Do you want to backup? Be sure to turn on the HDD."
if [ $? -ne 0 ]
    then exit 1
fi

*Do backup stuff here*

Error:

(zenity:9917): Gtk-WARNING **: cannot open display: 
run-parts: /etc/cron.daily/backup-on-external exited with return code 1

(I'm running Kubuntu, so a KDE solution would be even better than Zenity, but I already installed Zenity, so I can keep using it.)

Best Answer

Try adding something like the following to your ~/.xinitrc (or ~/.xsession if you use a login manager):

while true; do
    if [[ -a ~/.messages ]]; then
        zenity --info --text="$(printf "%q" $(cat ~/.messages))"
        rm ~/.messages
    fi
    sleep 10
done &

I haven't tested this with zenity as I don't have it and I'm assuming that .xsession works as expected - I've never used a login manager.

The while/done block will execute indefinitely with a ten second delay between checks (the sleep 10 part). Each time there's a check, the if guard succeeds if there's a non-empty file called .messages in the user's homedir. On success, the contents of the file are read into zenity and the file is removed.

I'm not thrilled with the printf vomit, but it should be fine.

The content that gets put into ~/.messages should be redirected from cron and you'll need to make sure you change the owner and group of the file appropriately. Perhaps something like:

10 * * * * /usr/bin/mything && echo "mything completed" > /home/username/.messages && chown username:groupname /home/username/.messages
Related Question