1. Overview

Today, many Linux users would like to choose a GUI desktop environment such as GNOME, XFCE, or KDE as their daily working platform. However, in Linux, many jobs are done with shell scripts. Usually, when we launch a shell script, it’ll run in the Linux command-line.

We can start a shell script from a GUI desktop environment. But if we want to know if the script has done its job or check the execution status, we have to switch to the terminal where the script is started from or check the process status and log files of the shell script.

In this tutorial, we’ll have a look at how to send a GUI notification from a shell script so that we can see straightforwardly how the script is running.

2. A Shell Script Example

To address and demonstrate GUI notifications from a shell script, we’ll first create a simple shell script as an example.

Let’s say we want to know our public IP address by executing a shell script called tell_me_ip.sh:

#!/bin/bash
IP_MSG="$(curl --no-progress-meter http://ifconfig.io 2>&1)"
STATUS=$?

if [ $STATUS -ne 0 ]; then
    MESSAGE="Error Occurred! [ $IP_MSG ]"
else
    MESSAGE="My Public IP: $IP_MSG"
fi
echo $MESSAGE

The script is pretty straightforward. Let’s walk through quickly.

First, we get our public IP address using the curl command to read the website http://ifconfig.io.

Here, we tell the curl command to suppress the progress meter output by setting the option –no-progress-meter.

Second, depending on the curl command’s exit code, we build up the message with the IP address or the error message.

Finally, we print the message out.

Let’s test the script quickly:

$ ./tell_me_ip.sh
My Public IP: 149.224.212.24

To simulate an error case, let’s simply change the website URL in our tell_me_ip.sh script to a non-existent one, for example, “http://who.is.it“:

$ ./tell_me_ip.sh
Error Occurred! [ curl: (6) Could not resolve host: who.is.it ]

Good! Our shell script works.

Next, let’s see if we can send the messages to our GUI desktop environment as notifications.

3. Using the notify-send Command

Most modern GUI desktop environments will start notification servers automatically on login to receive the notifications sent by different applications through D-Bus.

libnotify is an implementation of the Desktop Notifications Specification. It is widely used and desktop independent.

The libnotify package ships with a notify-send command. We can use it to send notifications from our shell scripts to a GUI desktop easily.

3.1. notify-send in a Nutshell

The syntax of using the notify-send command is pretty intuitive:

notify-send [OPTIONS] [Message Summary] [Message Body]

The [message body] supports XML-based markup. It’s a small subset of HTML along with a few additional tags. 

Let’s see some commonly used examples:

  • Hello World will display Hello World in bold
  • Hello World will show the message in italics: Hello World
  • Hello World will underline the message: Hello World

The notify-send command supports options to control how the notification is displayed. Let’s take a look at a couple of pretty useful options:

  • -t : defines the duration in milliseconds for the notification to appear on the desktop screen
  • -i : specifies an icon name to display in the notification together with the message

Let’s send a “Hello World” notification from the command line:

 notify-send -t 3000 -i face-smile "The First Notification" "Hello <b>World</b>"

If we run the command above, a notification with a joyful smile face icon will be shown in the notification area for three seconds:

noti1

Apart from the smiling face, the notify-send command supports many other icons.

3.2. Sending Notifications From Our Shell Script

Now, it’s time to assemble notify-send commands in our shell script to send desktop notifications:

#!/bin/bash 
IP_MSG="$(curl --no-progress-meter http://ifconfig.io 2>&1)" 
STATUS=$? 
ICON="dialog-information"

if [ $STATUS -ne 0 ]; then
    MESSAGE="Error Occurred! [ $IP_MSG ]" 
    ICON="dialog-error"
else
    MESSAGE="My Public IP: $IP_MSG" 
fi
notify-send -t 4000 -i "$ICON" "Public IP" "$MESSAGE"
echo $MESSAGE

We modified the original script a little bit.

We added an $ICON variable to store the notification icon name because we would like to see different icons for success and error cases.

Also, we added a notify-send command to send the notification to the desktop.

Finally, let’s test our shell script:

noti2

Let’s change the URL of the website and test the error case quickly:

noti3

Cool! Now our shell script can send its execution status to our GUI desktop.

4. Using the zenity Utility

zenity is a utility to display GTK dialog boxes in command-line and shell scripts. If we want to display Qt GUI elements, we can use qarama, a “zenity clone for Qt”.

In this tutorial, we’ll only address how to use zenity to send GTK notifications.

4.1. zenity in a Nutshell

zenity can display desktop notifications and other types of GTK dialogs — for example, information dialogs, error alerts, calendar dialogs, checkboxes, and radio buttons.

The syntax to use the zenity command is as simple as:

zenity [Options]

The [Options] define everything we want zenity to do for us. For example, we can tell it what kind of GUI dialog we want to show, how to arrange the elements in the dialog, or how to transmit data between the GUI dialog and our shell script.

After all, we don’t want to design a full-featured GTK application. Instead, our goal is merely to display the information generated in a shell script to the GUI desktop.

Therefore, several options are interesting for us:

  • –info: display an info dialog
  • –error: display an error dialog
  • –text=STRING: set the dialog text
  • –notification: display a desktop notification

To understand how zenity works, let’s write a couple of “Hello World” examples using the zenity command.

First, let’s create a desktop notification with the “Hello World” message:

zenity --notification --window-icon=info --text "Hello World"

If we execute the command above, a notification will show up:

noti4

We should keep in mind when we display a notification, the text with the –text option doesn’t support markup.

Also, we can display info or an error dialog box to contain our “Hello World” message. Let’s create an error dialog using this command:

zenity --error --text "Hello World"

noti5

When a message is showing in a dialog, we can select the text or copy it. This can be handy in some cases.

However, unlike the notification popup, the info or error dialog will block the shell script. In other words, the shell script will continue its execution once we click the “OK” button.

4.2. Displaying Dialog and Notification From Our Shell Script

Now, let’s add zenity to our tell_me_ip.sh script.

If we get the public IP successfully, we’ll display it as a message in an info dialog box. In this way, we can copy the IP address easily. But if an error occurs, we want to be informed by a notification:

#!/bin/bash 
IP_MSG="$(curl --no-progress-meter http://ifconfig.io 2>&1)"
STATUS=$? 

if [ $STATUS -ne 0 ]; then
    MESSAGE="Error Occurred! [ $IP_MSG ]"
    zenity --notification --window-icon=error --text="$MESSAGE"
else
    MESSAGE="My Public IP: $IP_MSG"
    zenity --info --text="$MESSAGE"
fi
echo $MESSAGE

Our public IP address will be shown in an info dialog box if we execute the shell script. We can select the IP address using the mouse:

noti7

Once we click the “OK” button, the shell script’s execution will continue, and the IP address is printed.

If we change the URL in the script to http://who.is.it and launch the script once again, we’ll see an error notification with the detailed error message:

noti6

5. Conclusion

In this article, we discussed how to send information from a shell script to a GUI desktop environment. We’ve introduced two utilities to do the job: notify-send and zenity.

Both utilities are pretty straightforward to use, as we’ve demonstrated through some simple examples. However, they have different capabilities. Whereas notify-send can only send desktop notifications, zenity can do that and much more.