Zen and the Art of Shell Scripting

You know what it’s like with a little kid at his birthday party. They get all excited, eat far too many sugary foods and then run around behaving badly.
Oracle Openworld has ended for another year, and not a minute too soon. Hopefully, Larry will have an early night and stop being so excitable and upsetting all those jolly nice open source types he had round.
Meanwhile, in the comparative calm of the backwater that is this blog, I’ve been getting all Zen. Well, zenity, to be precise. Yep, I’ve decided that some my batch scripts needed to get all GUI with Gnome and zenity looks to be the tool to do it.
What follows is an account of my first steps with zenity followed by a demonstration of some of it’s capabilities.

I was going to say “the first time I used zenity in anger”…but that wouldn’t really fit in with my attempts to attain enlightenment…so…the first problem I managed to solve with zenity arose from my adventures with VLC, which I posted here.

As you may recall, the solution I decided upon for getting VLC to read music from my Samba share was to mount it on my PC. Now, the command to do this requires sudo, and sudo, by default, asks for re-verification of my password.
I need to mount the share everytime I start VLC because that’s where all the music files are stored, but I don’t really want to have to open a terminal and type out the command ( or even run a batch script). So, how could I run VLC and mount the share from the menu without removing sudo’s secure habit of asking for a password ?
Well, first off, sudo can take the password from stdin by means of the -S switch. So, all we need to do is to provide a dialog box for the user to enter the password and then pipe it into sudo…

#! /bin/bash 
zenity --entry --title="Sudo Password"\ 
--text="Enter your password:" --hide-text \ 
| sudo -S sudo mount -t cifs //mikeserver/share /home/mikes/server_share -o iocharset=utf8,file_mode=0777,dir_mode=0777 
vlc 

Enter the sudo password and away we go

Now all I need to do is change the menu entry for VLC to run this script.
To do this, go into the Gnome System Menu, Preferences, Main Menu. In the Sound & Video section, select VLC and click Properties. In the Command box, just enter the full path to the script.
There is rather more to zenity than facilitating my musical indulgences. It offers a wide range of GUI interfaces that can be invoked from a shell script.
A full description of them can be found in the Zenity Manual.
There's also a really good illustration of the available dialogs here.

I've taken this on just a little, to work out how to handle the user input coming back from these dialogs. I thought the best way to do it would be a quiz. A Karma Quiz.
What we're going to do here is :

  1. Invite the user to the quiz
  2. Ask some questions in various formats ( text box, checklist, radiolist, calendar)
  3. Show a progress bar whilst we tot up the results
  4. Tell the user their score
  5. Output the contents of a file explaining the scoring scale

I've tried to make some of the messages sound suitably gnomic. Unfortunately, haikus are not really my strong point. Dirty limericks are more my metier.
The quiz consists of five questions of varying levels of obscurity. Question 3 ( about fruit salad) is taken from a Christmas cracker and is still one of my Mum's favourite jokes. Well, she does tell it at every opportunity.

Before we get to the script, we need to create a text file for the scoring scale.
The file is called karma.txt and contains the following lines :

0-1 - Megalomaniac head of a Software Behemoth
2-4 - On the road to the (Leyton) Orient
5   - You have attained fortune-cookie wisdom

Now for the script...

#!/bin/sh
# The Zenity Karma Quiz
# Script to demonstrate zenity functionality
#
# First ask the user if they want to continue. Zenity returns
# 0 if OK is pressed
# 1 if Cancel
#
zenity --question --text "Are you ready to face the trial ?"
#
# Display the appropriate message in a dialog box
#
if [ $? == 0 ]; then
    zenity \
        --info \
        --text "Prepare for your first steps on the path to enlightenment"
else
    zenity --info --text "You are not yet ready to seek enlightenment"
    exit 0;
fi
#
# If we're still here then Grasshopper has chosen to undertake the trial
# Start with a text dialog
#
score=0;
ans1=$(zenity --entry --text "Which team plays at Kenilworth Road ?");
if [ "$ans1" = "Luton Town" ]; then
    score=$((score+1));
    zenity --info --text "Confucius say, C'mon you Hatters !"
else
    zenity --error \
        --text "You have much to learn of the ways of the Blue Square Premier"
fi
#
# Next up is a checklist
# define two columns. The value of the Pick column is a BOOLEAN
#
ans2=$(zenity \
        --list \
        --height=210 \
        --text "Pick two teams who have knocked England out on penalties" \
        --checklist \
        --column "Pick" \
        --column "Team" \
        FALSE "France" \
        FALSE "Germany" \
        FALSE "Spain" \
        FALSE "Argentina" \
        --separator=":");
if [ "$ans2" = "Germany:Argentina" ]; then
    score=$((score+1));
    zenity --info --text "You have experienced much pain"
else
    zenity --error --text "You cannot know the feeling...unless you are Dutch"
fi
#
# radiolist - with apologies to Huey Lewis 
# As with the checklist, the first column is a BOOLEAN
#
ans3=$(zenity --list --text "What is the most romantic fruit salad ?" \
    --radiolist \
    --column "Pick" \
    --column "Answer" \
    FALSE "Something involving bananas" \
    FALSE "A date with a peach");
if [ "$ans3" = "A date with a peach" ]; then
    score=$((score+1));
    zenity --info --text "The power of love is a curious thing"
else
    zenity --error --text "You have still to obtain the fruits of wisdom"
fi
#
# calendar
#
ans4=$(zenity --calendar \
    --text "Pick the day Britain switched to the Julian Calendar" \
    --title "Question 4" --day 1 --month 9 --year 1752);
if [ $ans4 = "02/09/52" ]; then
    score=$((score+1));
    zenity --info --text "Reading the man page is the path to wisdom"
else
    zenity --error --text "Youth and wisdom are seldom combined"
fi
#
# Last question - another radiolist
#
ans5=$(zenity \
    --list --text "Which way to the shops ?"\
    --radiolist \
    --column="Pick" \
    --column="Answer" \
    FALSE "Left" \
    FALSE "Right" \
    FALSE "Straight On");
if [ "$ans5" = "Left" ]; then
    score=$((score+1));
    zenity --info --text "Right"
else
    zenity --error --text "Sometimes the right answer is the wrong one".
fi
#
# Now display a progress bar. We're not doing anything here except
# trying to build the tension...
#
(
echo "20"; sleep 1
echo "40"; sleep 1
echo "60"; sleep 1
echo "80"; sleep 1
echo "100"; sleep 1
) |zenity --progress \
          --title="Counting..." \
          --text="Calculating your Karma" \
          --percentage=0;
#
# Now display the score
#
zenity --info --text "Your Karma level is $score";
#
# Finally display the scoring scale of the quiz.
# This is held in a file - karma.txt
#
zenity --text-info \
    --height=250 \
    --width=360 \
    --title="Karmic Scale" \
    --filename="karma.txt";
exit 0;

When we run it, we get a variety of dialogs...

Start with a dialog box

...and off we go

easy one to start...if your name is Simon !

Celebrity fans, they get everywhere !

You may well ask to name two that haven't

Misery loves company

Fruity

Huey Lewis - Zen master

Calendar dialog

If you're none the wiser, do a man on cal

starting to run out of ideas...

No, I've no idea what that means either

Desparate attempt to keep your user on tenterhooks

...before revealing the final score

And finally, output the contents of a file

After all that I can't be bothered to cook any tea. I really fancy a Chinese for some reason...

About these ads

2 thoughts on “Zen and the Art of Shell Scripting

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s