How to display a (zenity/GUI) dialog to the user after a root cron task has completed

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.)

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

Method 2

My system is ubuntu 13.04. I ran a script similar to your’s via anacrontab and it works. Try this ..

Set up your crontab ..

$ cat /path/crontabfile
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*   *   *   *   *   /bin/bash /path/anacron-tst/s1.sh

ALTERNATIVE: Set up your anacrontab ..

$ cat /etc/anacrontab
### original
.. ,, ..
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root

# These replace cron's entries
1   5   cron.daily  run-parts --report /etc/cron.daily
7   10  cron.weekly run-parts --report /etc/cron.weekly
@monthly    15  cron.monthly    run-parts --report /etc/cron.monthly
### end-original

### my custom lines ..
SHELL=/bin/bash
HOME=/home/me
LOGNAME=me

1   2   me1 /bin/bash /path/anacron-tst/s1.sh

In your script ..

$ cat /path/anacron-tst/s1.sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

export DISPLAY=:0.0
export XAUTHORITY=/home/me/.Xauthority

zenity --question --text "Backup time .. is HDD connected?"

if [ $? -ne 0 ]; then
    echo "No confirmation .. quiting"
    exit 1
else
    echo "Will attempt backup now .."
fi

This from man 5 anacrontab ..

.. lines can be of three kinds:  job-description lines, environment assignments, or empty lines.

Environment assignment lines are of the form: VAR = VALUE
.. ,, ..
The assignment takes effect from the next line to the end of the  file,  or
to the next assignment of the same variable.

This is working with a the crontab installed for root. Please note that I have edited the script to include the line “export XAUTHORITY=/home/me/.Xauthority”. It needs that to work.

Method 3

Here’s a report on everything I found so far:

This solution from Ask Ubuntu

This is currently working for me and I haven’t seen any problems so far:

        ACTIVE=$(ck-list-sessions | awk -F' = ' '
            function f(){if(A=="TRUE"){P=U"t"D;gsub("'"'"'","",P);print P}}
            $1=="tunix-user"{U=$2} 
            $1=="tx11-display"{D=$2} 
            $1=="tactive"{A=$2} 
            END{f()} /^[^t]/{f()}
        ')
        USERID=${ACTIVE%    *} # tab
        USERNAME=$(getent passwd $USERID|cut -f1 -d':')
        DISPLAY=${ACTIVE#*  } # tab

        DISPLAY="$DISPLAY" su $USERNAME -c "zenity --info --title='My Title' --text='My text. Notice the single quotes.'"

But I have been testing the notify-send command (mentioned here) and it would seem to be even more appropriate for my situation….

Unfortunately, it has the disadvantage in KDE that the notifications hide shortly and I haven’t found way to disable that timeout (-t 0 didn’t work). For my present use-case I tend to like a dialog box that has to be dismissed by a button click. Anyway, here are the details of notify-send:

notify-send command

The notify-send command allows you to send desktop notifications to the user via a notification daemon from the command line. This is useful to inform the desktop user about an event or display some form of information without getting in the user’s way. You need to install the following package:

$ sudo apt-get install libnotify-bin

In this example, send simple desktop notification from the command line, enter:

notify-send "rsnapshot done :)"

However, in the process of searching for solutions, I also found something that I absolutely love! I’ll be removing all calls to Zenity in all my scripts and replacing them with easybashgui.

easybashgui

http://sites.google.com/site/easybashgui/

EasyBashGUI is a Bash functions library for *BSD and GNU/Linux that
aims to give simple GUI functions using yad, gtkdialog, kdialog,
zenity, Xdialog, (c)dialog, whiptail or bash builtins depending on
KDE or GNOME running or not, Yad/Gtkdialog/Xdialog installed or not
and, eventually, X server running or not.

I also found Yad which will replace Zenity for me in the future. easybashgui can use/call Zenity, yad, gtkdialog, kdialog, Xdialog, (c)dialog, whiptail or bash builtins. So I’ll be phasing out Zenity and using yad where appropriate.

yad

Display graphical dialogs from shell scripts or command line – Google Project Hosting
http://code.google.com/p/yad/

Yad (yet another dialog) is a fork of Zenity with many improvements, such as custom buttons, additional dialogs, pop-up menu in notification icon and more.

There were two main reasons to make this fork. The first one is to
remove dependencies on deprecated libraries, such as libglade and
gnome-canvas. And the second one – as for me, Zenity looks like an
abandoned project. Its ChangeLog consists of just “bump version to…”
and “translation updated” for the long time, but many interesting
ideas which are ignored by developers/maintainers were in GNOME
Bugzilla.

a note

As don_crissti mentions, the solutions at this unix.stackexchange.com are probably relevant:

Open a window on a remote X display (why “Cannot open display”)?

Method 4

Based on Mel Boyce’s answer, here’s what worked for me. This is KDE-based. But I also tested it with Zenity and the same approach works. It is basically the same thing Mel Boyce recommended, but with a few tweaks to get it to work for me. I don’t delete the updateNotification.txt file, for example. And I don’t use printf.

The updater script includes this:

DATE_STAMP=` date`
echo "t***The software has been updated to version ${LATEST} on ${DATE_STAMP}***"
echo "The software has been updated to version ${LATEST} on ${DATE_STAMP}. Please close and reopen the program if it is current running. If you have any issues or questions, please write us at <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f0838580809f8284b09588919d809c95de939f9dde">[email protected]</a> Thank you." > /home/$USERN/.updateNotification.txt

Then we have a script running in /home/$USERN/.kde/Autostart/updateNotificationChecker.sh

#!/bin/bash
while true; do
    if [[ -s ~/.updateNotification.txt ]]; then
                read MSGFE < ~/.updateNotification.txt 
                kdialog --title 'The software has been updated' --msgbox "$MSGFE"
                cat /dev/null > ~/.updateNotification.txt
    fi
    sleep 300
done
exit 0


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x